def test_poly_gcdex(): f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15 g = x**3 + x**2 - 4*x - 4 assert poly_half_gcdex(f, g, x) == \ (Poly(-x/5+Rational(3,5), x), Poly(x+1, x)) assert poly_half_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x/5+Rational(3,5), x), Poly(x+1, x)) assert poly_gcdex(f, g, x) == \ (Poly(-x/5+Rational(3,5), x), Poly(x**2/5-6*x/5+2, x), Poly(x+1, x)) assert poly_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x/5+Rational(3,5), x), Poly(x**2/5-6*x/5+2, x), Poly(x+1, x)) f = x**4 + 4*x**3 - x + 1 g = x**3 - x + 1 s, t, h = poly_gcdex(f, g, x) S, T, H = poly_gcdex(g, f, x) assert s*f + t*g == h assert S*g + T*f == H assert poly_gcdex(2*x, x**2-16, x) == \ (Poly(x/32, x), Poly(-Rational(1,16), x), Poly(1, x))
def test_poly_gcdex(): f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15 g = x**3 + x**2 - 4*x - 4 assert poly_half_gcdex(f, g, x) == \ (Poly(-x+3, x), Poly(5*x+5, x)) assert poly_half_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x+3, x), Poly(5*x+5, x)) assert poly_gcdex(f, g, x) == \ (Poly(-x+3, x), Poly(x**2-6*x+10, x), Poly(5*x+5, x)) assert poly_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x+3, x), Poly(x**2-6*x+10, x), Poly(5*x+5, x)) f = x**4 + 4*x**3 - x + 1 g = x**3 - x + 1 s, t, h = poly_gcdex(f, g, x) S, T, H = poly_gcdex(g, f, x) assert s*f + t*g == h assert S*g + T*f == H
def test_poly_gcdex(): f = x**4 - 2 * x**3 - 6 * x**2 + 12 * x + 15 g = x**3 + x**2 - 4 * x - 4 assert poly_half_gcdex(f, g, x) == \ (Poly(-x+3, x), Poly(5*x+5, x)) assert poly_half_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x+3, x), Poly(5*x+5, x)) assert poly_gcdex(f, g, x) == \ (Poly(-x+3, x), Poly(x**2-6*x+10, x), Poly(5*x+5, x)) assert poly_gcdex(Poly(f, x), Poly(g, x)) == \ (Poly(-x+3, x), Poly(x**2-6*x+10, x), Poly(5*x+5, x)) f = x**4 + 4 * x**3 - x + 1 g = x**3 - x + 1 s, t, h = poly_gcdex(f, g, x) S, T, H = poly_gcdex(g, f, x) assert s * f + t * g == h assert S * g + T * f == H
def apart(f, z, **flags): """Compute partial fraction decomposition of a rational function. Given a rational function 'f', performing only gcd operations over the algebraic closue of the initial field of definition, compute full partial fraction decomposition with fractions having linear denominators. For all other kinds of expressions the input is returned in an unchanged form. Note however, that 'apart' function can thread over sums and relational operators. Note that no factorization of the initial denominator of 'f' is needed. The final decomposition is formed in terms of a sum of RootSum instances. By default RootSum tries to compute all its roots to simplify itself. This behaviour can be however avoided by seting the keyword flag evaluate=False, which will make this function return a formal decomposition. >>> from sympy import * >>> x,y = symbols('xy') >>> apart(y/(x+2)/(x+1), x) y/(1 + x) - y/(2 + x) >>> apart(1/(1+x**5), x, evaluate=False) RootSum(Lambda(_a, -1/5/(x - _a)*_a), x**5 + 1, x) For more information on the implemented algorithm refer to: [1] M. Bronstein, B. Salvy, Full partial fraction decomposition of rational functions, in: M. Bronstein, ed., Proceedings ISSAC '93, ACM Press, Kiev, Ukraine, 1993, pp. 157-160. """ if not f.has(z): return f f = Poly.cancel(f, z) P, Q = f.as_numer_denom() if not Q.has(z): return f partial, r = div(P, Q, z) f, q, U = r / Q, Q, [] u = Function('u')(z) a = Symbol('a', dummy=True) for k, d in enumerate(poly_sqf(q, z)): n, b = k + 1, d.as_basic() U += [u.diff(z, k)] h = together(Poly.cancel(f * b**n, z) / u**n) H, subs = [h], [] for j in range(1, n): H += [H[-1].diff(z) / j] for j in range(1, n + 1): subs += [(U[j - 1], b.diff(z, j) / j)] for j in range(0, n): P, Q = together(H[j]).as_numer_denom() for i in range(0, j + 1): P = P.subs(*subs[j - i]) Q = Q.subs(*subs[0]) P, Q = Poly(P, z), Poly(Q, z) G = poly_gcd(P, d) D = poly_quo(d, G) B, g = poly_half_gcdex(Q, D) b = poly_rem(P * poly_quo(B, g), D) numer = b.as_basic() denom = (z - a)**(n - j) expr = numer.subs(z, a) / denom partial += RootSum(Lambda(a, expr), D, **flags) return partial
def apart(f, z, **flags): """Compute partial fraction decomposition of a rational function. Given a rational function 'f', performing only gcd operations over the algebraic closue of the initial field of definition, compute full partial fraction decomposition with fractions having linear denominators. For all other kinds of expressions the input is returned in an unchanged form. Note however, that 'apart' function can thread over sums and relational operators. Note that no factorization of the initial denominator of 'f' is needed. The final decomposition is formed in terms of a sum of RootSum instances. By default RootSum tries to compute all its roots to simplify itself. This behaviour can be however avoided by seting the keyword flag evaluate=False, which will make this function return a formal decomposition. >>> from sympy import * >>> x,y = symbols('xy') >>> apart(y/(x+2)/(x+1), x) y/(1 + x) - y/(2 + x) >>> apart(1/(1+x**5), x, evaluate=False) RootSum(Lambda(_a, -1/5/(x - _a)*_a), x**5 + 1, x) For more information on the implemented algorithm refer to: [1] M. Bronstein, B. Salvy, Full partial fraction decomposition of rational functions, in: M. Bronstein, ed., Proceedings ISSAC '93, ACM Press, Kiev, Ukraine, 1993, pp. 157-160. """ if not f.has(z): return f f = Poly.cancel(f, z) P, Q = f.as_numer_denom() if not Q.has(z): return f partial, r = div(P, Q, z) f, q, U = r / Q, Q, [] u = Function('u')(z) a = Symbol('a', dummy=True) for k, d in enumerate(poly_sqf(q, z)): n, b = k + 1, d.as_basic() U += [ u.diff(z, k) ] h = together(Poly.cancel(f*b**n, z) / u**n) H, subs = [h], [] for j in range(1, n): H += [ H[-1].diff(z) / j ] for j in range(1, n+1): subs += [ (U[j-1], b.diff(z, j) / j) ] for j in range(0, n): P, Q = together(H[j]).as_numer_denom() for i in range(0, j+1): P = P.subs(*subs[j-i]) Q = Q.subs(*subs[0]) P, Q = Poly(P, z), Poly(Q, z) G = poly_gcd(P, d) D = poly_quo(d, G) B, g = poly_half_gcdex(Q, D) b = poly_rem(P * poly_quo(B, g), D) numer = b.as_basic() denom = (z-a)**(n-j) expr = numer.subs(z, a) / denom partial += RootSum(Lambda(a, expr), D, **flags) return partial