def ratint_logpart(f, g, x, t=None):
    """Lazard-Rioboo-Trager algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime, deg(f) < deg(g) and g is square-free, returns a list
       of tuples (s_i, q_i) of polynomials, for i = 1..n, such that s_i
       in K[t, x] and q_i in K[t], and:
                               ___    ___
                     d  f   d  \  `   \  `
                     -- - = --  )      )   a log(s_i(a, x))
                     dx g   dx /__,   /__,
                              i=1..n a | q_i(a) = 0

    """
    f, g = Poly(f, x), Poly(g, x)

    t = t or Symbol('t', dummy=True)
    a, b = g, f - g.diff().mul_term(t)

    res, R = poly_subresultants(a, b)
    Q = poly_sqf(Poly(res, t))

    R_map, H, i = {}, [], 1

    for r in R:
        R_map[r.degree] = r

    for q in Q:
        if q.degree > 0:
            _, q = q.as_primitive()

            if g.degree == i:
                H.append((g, q))
            else:
                h = R_map[i]
                A = poly_sqf(h.LC, t)

                for j in xrange(0, len(A)):
                    T = poly_gcd(A[j], q)**(j+1)
                    h = poly_div(h, Poly(T, x))[0]

                # NOTE: h.LC is always invertible in K[t]
                inv, coeffs = Poly(h.LC, t).invert(q), [S(1)]

                for coeff in h.coeffs[1:]:
                    T = poly_div(inv*coeff, q)[1]
                    coeffs.append(T.as_basic())

                h = Poly(zip(coeffs, h.monoms), x)

                H.append((h, q))

        i += 1

    return H
Example #2
0
def ratint_logpart(f, g, x, t=None):
    """Lazard-Rioboo-Trager algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime, deg(f) < deg(g) and g is square-free, returns a list
       of tuples (s_i, q_i) of polynomials, for i = 1..n, such that s_i
       in K[t, x] and q_i in K[t], and:
                               ___    ___
                     d  f   d  \  `   \  `
                     -- - = --  )      )   a log(s_i(a, x))
                     dx g   dx /__,   /__,
                              i=1..n a | q_i(a) = 0

    """
    f, g = Poly(f, x), Poly(g, x)

    t = t or Symbol('t', dummy=True)
    a, b = g, f - g.diff().mul_term(t)

    res, R = poly_subresultants(a, b)
    Q = poly_sqf(Poly(res, t))

    R_map, H, i = {}, [], 1

    for r in R:
        R_map[r.degree] = r

    for q in Q:
        if q.degree > 0:
            _, q = q.as_primitive()

            if g.degree == i:
                H.append((g, q))
            else:
                h = R_map[i]
                A = poly_sqf(h.LC, t)

                for j in xrange(0, len(A)):
                    T = poly_gcd(A[j], q)**(j+1)
                    h = poly_div(h, Poly(T, x))[0]

                # NOTE: h.LC is always invertible in K[t]
                inv, coeffs = Poly(h.LC, t).invert(q), [S(1)]

                for coeff in h.coeffs[1:]:
                    T = poly_div(inv*coeff, q)[1]
                    coeffs.append(T.as_basic())

                h = Poly(zip(coeffs, h.monoms), x)

                H.append((h, q))

        i += 1

    return H
Example #3
0
def poly_sturm(f, *symbols):
    """Computes the Sturm sequence of a given polynomial.

       Given an univariate, square-free polynomial f(x) returns an
       associated Sturm sequence f_0(x), ..., f_n(x) defined by:

           f_0(x), f_1(x) = f(x), f'(x)
           f_n = -rem(f_{n-2}(x), f_{n-1}(x))

       For more information on the implemented algorithm refer to:

       [1] J.H. Davenport, Y. Siret, E. Tournier, Computer Algebra
           Systems and Algorithms for Algebraic Computation,
           Academic Press, London, 1988, pp. 124-128

    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    if f.is_multivariate:
        raise MultivariatePolyError(f)
    else:
        f = f.as_squarefree()

    sturm = [f, f.diff()]

    while not sturm[-1].is_zero:
        sturm.append(-poly_div(sturm[-2], sturm[-1])[1])

    return sturm[:-1]
Example #4
0
def poly_sturm(f, *symbols):
    """Computes the Sturm sequence of a given polynomial.

       Given an univariate, square-free polynomial f(x) returns an
       associated Sturm sequence f_0(x), ..., f_n(x) defined by:

           f_0(x), f_1(x) = f(x), f'(x)
           f_n = -rem(f_{n-2}(x), f_{n-1}(x))

       For more information on the implemented algorithm refer to:

       [1] J.H. Davenport, Y. Siret, E. Tournier, Computer Algebra
           Systems and Algorithms for Algebraic Computation,
           Academic Press, London, 1988, pp. 124-128

    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    if f.is_multivariate:
        raise MultivariatePolyError(f)
    else:
        f = f.as_squarefree()

    sturm = [f, f.diff()]

    while not sturm[-1].is_zero:
        sturm.append(-poly_div(sturm[-2], sturm[-1])[1])

    return sturm[:-1]
Example #5
0
    def _try_heuristics(f):
        """Find roots using formulas and some tricks. """
        if f.length == 1:
            if f.is_constant:
                return []
            else:
                return [S(0)] * f.degree

        if f.length == 2:
            if f.degree == 1:
                return roots_linear(f)
            else:
                return roots_binomial(f)

        x, result = f.symbols[0], []

        for i in [S(-1), S(1)]:
            if f(i).expand().is_zero:
                f = poly_div(f, x - i)[0]
                result.append(i)
                break

        n = f.degree

        if n == 1:
            result += roots_linear(f)
        elif n == 2:
            result += roots_quadratic(f)
        elif n == 3 and flags.get('cubics', True):
            result += roots_cubic(f)
        elif n == 4 and flags.get('quartics', False):
            result += roots_quartic(f)

        return result
Example #6
0
    def _try_heuristics(f):
        """Find roots using formulas and some tricks. """
        if f.length == 1:
            if f.is_constant:
                return []
            else:
                return [S(0)] * f.degree

        if f.length == 2:
            if f.degree == 1:
                return roots_linear(f)
            else:
                return roots_binomial(f)

        x, result = f.symbols[0], []

        for i in [S(-1), S(1)]:
            if f(i).expand().is_zero:
                f = poly_div(f, x - i)[0]
                result.append(i)
                break

        n = f.degree

        if n == 1:
            result += roots_linear(f)
        elif n == 2:
            result += roots_quadratic(f)
        elif n == 3 and flags.get("cubics", True):
            result += roots_cubic(f)
        elif n == 4 and flags.get("quartics", False):
            result += roots_quartic(f)

        return result
Example #7
0
    def roots_trivial(g):
        if g.length == 1:
            if g.is_constant:
                return []
            else:
                return [S.Zero] * g.degree

        (k,), g = g.as_reduced()

        if k == 0:
            zeros = []
        else:
            zeros = [S.Zero] * k

        if g.length == 2:
            zeros += roots_binomial(g)
        else:
            x = g.symbols[0]

            for i in [S.NegativeOne, S.One]:
                if g(i).expand() is S.Zero:
                    g = poly_div(g, x - i)[0]
                    zeros.append(i)
                    break

            n = g.degree

            if n == 1:
                zeros += roots_linear(g)
            elif n == 2:
                zeros += roots_quadratic(g)
            elif n == 3:
                if flags.get("cubics", False):
                    # TODO: now we can used factor() not only
                    #       for cubic polynomials. See #1158
                    try:
                        _, factors = poly_factors(g)

                        if len(factors) == 1:
                            raise PolynomialError

                        for factor, k in factors:
                            zeros += roots(factor, multiple=True) * k
                    except PolynomialError:
                        zeros += roots_cubic(g)
            elif n == 4:
                if flags.get("quartics", False):
                    zeros += roots_quartic(g)

        return zeros
Example #8
0
    def roots_trivial(g):
        if g.length == 1:
            if g.is_constant:
                return []
            else:
                return [S.Zero] * g.degree

        (k, ), g = g.as_reduced()

        if k == 0:
            zeros = []
        else:
            zeros = [S.Zero] * k

        if g.length == 2:
            zeros += roots_binomial(g)
        else:
            x = g.symbols[0]

            for i in [S.NegativeOne, S.One]:
                if g(i).expand() is S.Zero:
                    g = poly_div(g, x - i)[0]
                    zeros.append(i)
                    break

            n = g.degree

            if n == 1:
                zeros += roots_linear(g)
            elif n == 2:
                zeros += roots_quadratic(g)
            elif n == 3:
                if flags.get('cubics', False):
                    # TODO: now we can used factor() not only
                    #       for cubic polynomials. See #1158
                    try:
                        _, factors = poly_factors(g)

                        if len(factors) == 1:
                            raise PolynomialError

                        for factor, k in factors:
                            zeros += roots(factor, multiple=True) * k
                    except PolynomialError:
                        zeros += roots_cubic(g)
            elif n == 4:
                if flags.get('quartics', False):
                    zeros += roots_quartic(g)

        return zeros
def ratint_ratpart(f, g, x):
    """Horowitz-Ostrogradsky algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime and deg(f) < deg(g), returns fractions A and B in K(x),
       such that f/g = A' + B and B has square-free denominator.

    """
    f, g = Poly(f, x), Poly(g, x)

    u = poly_gcd(g, g.diff())
    v = poly_div(g, u)[0]

    n = u.degree - 1
    m = v.degree - 1
    d = g.degree

    A_coeff = [ Symbol('a' + str(n-i), dummy=True) for i in xrange(0, n+1) ]
    B_coeff = [ Symbol('b' + str(m-i), dummy=True) for i in xrange(0, m+1) ]

    symbols = A_coeff + B_coeff

    A = Poly(zip(A_coeff, xrange(n, -1, -1)), x)
    B = Poly(zip(B_coeff, xrange(m, -1, -1)), x)

    H = f - A.diff()*v + A*poly_div(u.diff()*v, u)[0] - B*u

    result = solve(H.coeffs, symbols)

    A = A.subs(result)
    B = B.subs(result)

    rat_part = Poly.cancel((A, u), x)
    log_part = Poly.cancel((B, v), x)

    return rat_part, log_part
Example #10
0
def ratint_ratpart(f, g, x):
    """Horowitz-Ostrogradsky algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime and deg(f) < deg(g), returns fractions A and B in K(x),
       such that f/g = A' + B and B has square-free denominator.

    """
    f, g = Poly(f, x), Poly(g, x)

    u = poly_gcd(g, g.diff())
    v = poly_div(g, u)[0]

    n = u.degree - 1
    m = v.degree - 1
    d = g.degree

    A_coeff = [ Symbol('a' + str(n-i), dummy=True) for i in xrange(0, n+1) ]
    B_coeff = [ Symbol('b' + str(m-i), dummy=True) for i in xrange(0, m+1) ]

    symbols = A_coeff + B_coeff

    A = Poly(zip(A_coeff, xrange(n, -1, -1)), x)
    B = Poly(zip(B_coeff, xrange(m, -1, -1)), x)

    H = f - A.diff()*v + A*poly_div(u.diff()*v, u)[0] - B*u

    result = solve(H.coeffs, symbols)

    A = A.subs(result)
    B = B.subs(result)

    rat_part = Poly.cancel((A, u), x)
    log_part = Poly.cancel((B, v), x)

    return rat_part, log_part
Example #11
0
def poly_root_factors(f, *symbols, **flags):
    """Returns all factors of a univariate polynomial.

       >>> from sympy.polys.rootfinding import poly_root_factors
       >>> from sympy.abc import x, y

       >>> factors = poly_root_factors(x**2-y, x)

       >>> set(f.as_basic() for f in factors)
       set([x + y**(1/2), x - y**(1/2)])

    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    if f.is_multivariate:
        raise MultivariatePolyError(f)
    else:
        x = f.symbols[0]

    if 'multiple' in flags:
        del flags['multiple']

    zeros = roots(f, **flags)

    if not zeros:
        return [f]
    else:
        factors, N = [], 0

        for r, n in zeros.iteritems():
            h = Poly([(S.One, 1), (-r, 0)], x)
            factors, N = factors + [h]*n, N + n

        if N < f.degree:
            g = reduce(lambda p,q: p*q, factors)
            factors.append(poly_div(f, g)[0])

        return factors
Example #12
0
def poly_root_factors(f, *symbols, **flags):
    """Returns all factors of an univariate polynomial.

       >>> from sympy import *
       >>> x,y = symbols('xy')

       >>> factors = poly_root_factors(x**2-y, x)

       >>> set(f.as_basic() for f in factors)
       set([x + y**(1/2), x - y**(1/2)])
    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    if f.is_multivariate:
        raise MultivariatePolyError(f)
    else:
        x = f.symbols[0]

    if flags.has_key('multiple'):
        del flags['multiple']

    zeros = roots(f, **flags)

    if not zeros:
        return [f]
    else:
        factors, N = [], 0

        for r, n in zeros.iteritems():
            h = Poly([(S.One, 1), (-r, 0)], x)
            factors, N = factors + [h] * n, N + n

        if N < f.degree:
            g = reduce(lambda p, q: p * q, factors)
            factors.append(poly_div(f, g)[0])

        return factors
def log_to_atan(f, g):
    """Convert complex logarithms to real arctangents.

       Given a real field K and polynomials f and g in K[x], with g != 0,
       returns a sum h of arctangents of polynomials in K[x], such that:

                       df   d         f + I g
                       -- = -- I log( ------- )
                       dx   dx        f - I g

    """
    if f.degree < g.degree:
        f, g = -g, f

    p, q = poly_div(f, g)

    if q.is_zero:
        return 2*atan(p.as_basic())
    else:
        s, t, h = poly_gcdex(g, -f)
        A = 2*atan(quo(f*s+g*t, h))

        return A + log_to_atan(s, t)
Example #14
0
def log_to_atan(f, g):
    """Convert complex logarithms to real arctangents.

       Given a real field K and polynomials f and g in K[x], with g != 0,
       returns a sum h of arctangents of polynomials in K[x], such that:

                       df   d         f + I g
                       -- = -- I log( ------- )
                       dx   dx        f - I g

    """
    if f.degree < g.degree:
        f, g = -g, f

    p, q = poly_div(f, g)

    if q.is_zero:
        return 2*atan(p.as_basic())
    else:
        s, t, h = poly_gcdex(g, -f)
        A = 2*atan(quo(f*s+g*t, h))

        return A + log_to_atan(s, t)
def ratint(f, x, **flags):
    """Performs indefinite integration of rational functions.

       Given a field K and a rational function f = p/q, where p and q
       are polynomials in K[x], returns a function g such that f = g'.

       >>> from sympy.integrals.rationaltools import ratint
       >>> from sympy.abc import x

       >>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x)
       -4*log(1 + x) + 4*log(-2 + x) - (6 + 12*x)/(1 - x**2)

       References
       ==========

       .. [Bro05] M. Bronstein, Symbolic Integration I: Transcendental
          Functions, Second Edition, Springer-Verlag, 2005, pp. 35-70

    """
    if type(f) is not tuple:
        p, q = f.as_numer_denom()
    else:
        p, q = f

    p, q = Poly(p, x), Poly(q, x)

    g = poly_gcd(p, q)

    p = poly_div(p, g)[0]
    q = poly_div(q, g)[0]

    result, p = poly_div(p, q)

    result = result.integrate(x).as_basic()

    if p.is_zero:
        return result

    g, h = ratint_ratpart(p, q, x)

    P, Q = h.as_numer_denom()
    q, r = poly_div(P, Q, x)

    result += g + q.integrate(x).as_basic()

    if not r.is_zero:
        symbol = flags.get('symbol', 't')

        if not isinstance(symbol, Symbol):
            t = Symbol(symbol, dummy=True)
        else:
            t = symbol

        L = ratint_logpart(r, Q, x, t)

        real = flags.get('real')

        if real is None:
            if type(f) is not tuple:
                atoms = f.atoms()
            else:
                p, q = f

                atoms = p.atoms() \
                      | q.atoms()

            for elt in atoms - set([x]):
                if not elt.is_real:
                    real = False
                    break
            else:
                real = True

        eps = S(0)

        if not real:
            for h, q in L:
                eps += RootSum(Lambda(t, t*log(h.as_basic())), q)
        else:
            for h, q in L:
                R = log_to_real(h, q, x, t)

                if R is not None:
                    eps += R
                else:
                    eps += RootSum(Lambda(t, t*log(h.as_basic())), q)

        result += eps

    return result
Example #16
0
def test_poly_div():
    f = Poly(x**3-12*x**2-42, x)
    g = Poly(x**2+x-3, x)

    h = poly_div(f, g)

    assert h[0] == Poly(x-13, x)
    assert h[1] == Poly(16*x-81, x)

    assert h[0].as_basic() == x-13
    assert h[1].as_basic() == 16*x-81

    assert f / g == Poly(x-13, x)
    assert f % g == Poly(16*x-81, x)

    assert divmod(f, g) == (Poly(x-13, x), Poly(16*x-81, x))

    assert f / x == Poly(x**2-12*x, x)
    assert f % x == Poly(-42, x)

    assert divmod(f, x) == (Poly(x**2-12*x, x), Poly(-42, x))

    assert f / sin(x) == f.as_basic() / sin(x)
    assert f % sin(x) == 0

    assert divmod(f, sin(x)) == (f.as_basic() / sin(x), 0)

    assert poly_div(4*x**2*y-2*x*y-2*y+4*x+8, 2, x, y) == \
        (Poly(2*x**2*y-x*y-y+2*x+4, x, y), Poly((), x, y))

    assert poly_div(4*x**2*y-2*x*y-2*y+4*x+8, 2*y, x, y) == \
        (Poly(2*x**2-x-1, x, y), Poly(4*x+8, x, y))

    assert poly_div(x-1, y-1, x, y) == (Poly((), x, y), Poly(x-1, x, y))

    assert poly_div(x**3-12*x**2-42, x-3, x) == \
        (Poly(x**2-9*x-27, x), Poly(-123, x))

    assert poly_div(2+2*x+x**2, 1, x) == (Poly(2+2*x+x**2, x), Poly(0, x))
    assert poly_div(2+2*x+x**2, 2, x) == (Poly(1+x+x**2/2, x), Poly(0, x))

    assert poly_div(3*x**3, x**2, x) == (Poly(3*x, x), Poly(0, x))

    assert poly_div(1, x, x) == (Poly(0, x), Poly(1, x))

    assert poly_div(x*y+2*x+y,x,x) == (Poly(2+y, x), Poly(y, x))

    assert poly_div(x*y**2 + 1, [x*y+1, y+1], x, y) == \
        ([Poly(y, x, y), Poly(-1, x, y)], Poly(2, x, y))

    assert poly_div(x**2*y+x*y**2+y**2, [x*y-1, y**2-1], x, y) == \
        ([Poly(x+y, x, y), Poly(1, x, y)], Poly(1+x+y, x, y))
    assert poly_div(x**2*y+x*y**2+y**2, [y**2-1, x*y-1], x, y) == \
        ([Poly(1+x, x, y), Poly(x, x, y)], Poly(1+2*x, x, y))

    f, g = 3*x**3 + x**2 + x + 5, 5*x**2 - 3*x + 1

    q = Poly(Rational(3,5)*x + Rational(14, 25), x)
    r = Poly(Rational(52, 25)*x + Rational(111, 25), x)

    assert poly_div(f, g, x) == (q, r)
    assert poly_div(Poly(f, x), Poly(g, x)) == (q, r)

    q = Poly(15*x + 14, x)
    r = Poly(52*x + 111, x)

    assert poly_pdiv(f, g, x) == (q, r)
    assert poly_pdiv(Poly(f, x), Poly(g, x)) == (q, r)
Example #17
0
def test_poly_div():
    f = Poly(x**3-12*x**2-42, x)
    g = Poly(x**2+x-3, x)

    h = poly_div(f, g)

    assert h[0] == Poly(x-13, x)
    assert h[1] == Poly(16*x-81, x)

    assert h[0].as_basic() == x-13
    assert h[1].as_basic() == 16*x-81

    assert f / g == Poly(x-13, x)
    assert f % g == Poly(16*x-81, x)

    assert divmod(f, g) == (Poly(x-13, x), Poly(16*x-81, x))

    assert f / x == Poly(x**2-12*x, x)
    assert f % x == Poly(-42, x)

    assert divmod(f, x) == (Poly(x**2-12*x, x), Poly(-42, x))

    assert f / sin(x) == f.as_basic() / sin(x)
    assert f % sin(x) == 0

    assert divmod(f, sin(x)) == (f.as_basic() / sin(x), 0)

    assert poly_div(4*x**2*y-2*x*y-2*y+4*x+8, 2, x, y) == \
        (Poly(2*x**2*y-x*y-y+2*x+4, x, y), Poly((), x, y))

    assert poly_div(4*x**2*y-2*x*y-2*y+4*x+8, 2*y, x, y) == \
        (Poly(2*x**2-x-1, x, y), Poly(4*x+8, x, y))

    assert poly_div(x-1, y-1, x, y) == (Poly((), x, y), Poly(x-1, x, y))

    assert poly_div(x**3-12*x**2-42, x-3, x) == \
        (Poly(x**2-9*x-27, x), Poly(-123, x))

    assert poly_div(2+2*x+x**2, 1, x) == (Poly(2+2*x+x**2, x), Poly(0, x))
    assert poly_div(2+2*x+x**2, 2, x) == (Poly(1+x+x**2/2, x), Poly(0, x))

    assert poly_div(3*x**3, x**2, x) == (Poly(3*x, x), Poly(0, x))

    assert poly_div(1, x, x) == (Poly(0, x), Poly(1, x))

    assert poly_div(x*y+2*x+y,x,x) == (Poly(2+y, x), Poly(y, x))

    assert poly_div(x*y**2 + 1, [x*y+1, y+1], x, y) == \
        ([Poly(y, x, y), Poly(-1, x, y)], Poly(2, x, y))

    assert poly_div(x**2*y+x*y**2+y**2, [x*y-1, y**2-1], x, y) == \
        ([Poly(x+y, x, y), Poly(1, x, y)], Poly(1+x+y, x, y))
    assert poly_div(x**2*y+x*y**2+y**2, [y**2-1, x*y-1], x, y) == \
        ([Poly(1+x, x, y), Poly(x, x, y)], Poly(1+2*x, x, y))

    f, g = 3*x**3 + x**2 + x + 5, 5*x**2 - 3*x + 1

    q = Poly(Rational(3,5)*x + Rational(14, 25), x)
    r = Poly(Rational(52, 25)*x + Rational(111, 25), x)

    assert poly_div(f, g, x) == (q, r)
    assert poly_div(Poly(f, x), Poly(g, x)) == (q, r)

    q = Poly(15*x + 14, x)
    r = Poly(52*x + 111, x)

    assert poly_pdiv(f, g, x) == (q, r)
    assert poly_pdiv(Poly(f, x), Poly(g, x)) == (q, r)
Example #18
0
def ratint(f, x, **flags):
    """Performs indefinite integration of rational functions.

       Given a field K and a rational function f = p/q, where p and q
       are polynomials in K[x], returns a function g such that f = g'.

       >>> from sympy import *
       >>> x = Symbol('x')

       >>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x)
       -4*log(1 + x) + 4*log(-2 + x) - (6 + 12*x)/(1 - x**2)

       References
       ==========

       .. [Bro05] M. Bronstein, Symbolic Integration I: Transcendental
          Functions, Second Edition, Springer-Verlang, 2005, pp. 35-70

    """
    if type(f) is not tuple:
        p, q = f.as_numer_denom()
    else:
        p, q = f

    p, q = Poly(p, x), Poly(q, x)

    g = poly_gcd(p, q)

    p = poly_div(p, g)[0]
    q = poly_div(q, g)[0]

    result, p = poly_div(p, q)

    result = result.integrate(x).as_basic()

    if p.is_zero:
        return result

    g, h = ratint_ratpart(p, q, x)

    P, Q = h.as_numer_denom()
    q, r = poly_div(P, Q, x)

    result += g + q.integrate(x).as_basic()

    if not r.is_zero:
        symbol = flags.get('symbol', 't')

        if not isinstance(symbol, Symbol):
            t = Symbol(symbol, dummy=True)
        else:
            t = symbol

        L = ratint_logpart(r, Q, x, t)

        real = flags.get('real')

        if real is None:
            if type(f) is not tuple:
                atoms = f.atoms()
            else:
                p, q = f

                atoms = p.atoms() \
                      | q.atoms()

            for elt in atoms - set([x]):
                if not elt.is_real:
                    real = False
                    break
            else:
                real = True

        eps = S(0)

        if not real:
            for h, q in L:
                eps += RootSum(Lambda(t, t*log(h.as_basic())), q)
        else:
            for h, q in L:
                R = log_to_real(h, q, x, t)

                if R is not None:
                    eps += R
                else:
                    eps += RootSum(Lambda(t, t*log(h.as_basic())), q)

        result += eps

    return result