Series Manipulation using Polynomials

Any finite Taylor series, for all practical purposes is, in fact a polynomial. This module makes use of the efficient representation and operations of sparse polynomials for very fast multivariate series manipulations. Typical speedups compared to SymPy’s series method are in the range 20-100, with the gap widening as the series being handled gets larger.

All the functions expand any given series on some ring specified by the user. Thus, the coefficients of the calculated series depend on the ring being used. For example:

>>> from sympy.polys import ring, QQ, RR
>>> from sympy.polys.ring_series import rs_sin
>>> R, x, y = ring('x, y', QQ)
>>> rs_sin(x*y, x, 5)
-1/6*x**3*y**3 + x*y

QQ stands for the Rational domain. Here all coefficients are rationals. It is recommended to use QQ with ring series as it automatically chooses the fastest Rational type.

Similarly, if a Real domain is used:

>>> R, x, y = ring('x, y', RR)
>>> rs_sin(x*y, x, 5)
-0.166666666666667*x**3*y**3 + x*y

Though the definition of a polynomial limits the use of Polynomial module to Taylor series, we extend it to allow Laurent and even Puiseux series (with fractional exponents):

>>> from sympy.polys.ring_series import rs_cos, rs_tan
>>> R, x, y = ring('x, y', QQ)

>>> rs_cos(x + x*y, x, 3)/x**3
-1/2*x**(-1)*y**2 - x**(-1)*y - 1/2*x**(-1) + x**(-3)

>>> rs_tan(x**QQ(2, 5)*y**QQ(1, 2), x, 2)
1/3*x**(6/5)*y**(3/2) + x**(2/5)*y**(1/2)

By default, PolyElement did not allow non-natural numbers as exponents. It converted a fraction to an integer and raised an error on getting negative exponents. The goal of the ring series module is fast series expansion, and not to use the polys module. The reason we use it as our backend is simply because it implements a sparse representation and most of the basic functions that we need. However, this default behaviour of polys was limiting for ring series.

Note that there is no such constraint (in having rational exponents) in the data-structure used by polys- dict. Sparse polynomials (PolyElement) use the Python dict to store a polynomial term by term, where a tuple of exponents is the key and the coefficient of that term is the value. There is no reason why we can’t have rational values in the dict so as to support rational exponents.

So the approach we took was to modify sparse polys to allow non-natural exponents. And it turned out to be quite simple. We only had to delete the conversion to int of exponents in the __pow__ method of PolyElement. So:

>>> x**QQ(3, 4)
x**(3/4)

and not 1 as was the case earlier.

Though this change violates the definition of a polynomial, it doesn’t break anything yet. Ideally, we shouldn’t modify polys in any way. But to have all the series capabilities we want, no other simple way was found. If need be, we can separate the modified part of polys from core polys. It would be great if any other elegant solution is found.

All series returned by the functions of this module are instances of the PolyElement class. To use them with other SymPy types, convert them to Expr:

>>> from sympy.polys.ring_series import rs_exp
>>> from sympy.abc import a, b, c
>>> series = rs_exp(x, x, 5)
>>> a + series.as_expr()
a + x**4/24 + x**3/6 + x**2/2 + x + 1

rs_series

Direct use of elementary ring series functions does give more control, but is limiting at the same time. Creating an appropriate ring for the desired series expansion and knowing which ring series function to call, are things not everyone might be familiar with.

\(rs\_series\) is a function that takes an arbitrary Expr and returns its expansion by calling the appropriate ring series functions. The returned series is a polynomial over the simplest (almost) possible ring that does the job. It recursively builds the ring as it parses the given expression, adding generators to the ring when it needs them. Some examples:

>>> rs_series(sin(a + b), a, 5) 
1/24*sin(b)*a**4 - 1/2*sin(b)*a**2 + sin(b) - 1/6*cos(b)*a**3 + cos(b)*a

>>> rs_series(sin(exp(a*b) + cos(a + c)), a, 2) 
-sin(c)*cos(cos(c) + 1)*a + cos(cos(c) + 1)*a*b + sin(cos(c) + 1)

>>> rs_series(sin(a + b)*cos(a + c)*tan(a**2 + b), a, 2) 
cos(b)*cos(c)*tan(b)*a - sin(b)*sin(c)*tan(b)*a + sin(b)*cos(c)*tan(b)

It can expand complicated multivariate expressions involving multiple functions and most importantly, it does so blazingly fast:

>>> %timeit ((sin(a) + cos(a))**10).series(a, 0, 5) 
1 loops, best of 3: 1.33 s per loop

>>> %timeit rs_series((sin(a) + cos(a))**10, a, 5) 
100 loops, best of 3: 4.13 ms per loop

\(rs\_series\) is over 300 times faster. Given an expression to expand, there is some fixed overhead to parse it. Thus, for larger orders, the speed improvement becomes more prominent:

>>> %timeit rs_series((sin(a) + cos(a))**10, a, 100) 
10 loops, best of 3: 32.8 ms per loop

To figure out the right ring for a given expression, \(rs\_series\) uses the sring function, which in turn uses other functions of polys. As explained above, non-natural exponents are not allowed. But the restriction is on exponents and not generators. So, polys allows all sorts of symbolic terms as generators to make sure that the exponent is a natural number:

>>> from sympy.polys.rings import sring
>>> R, expr = sring(1/a**3 + a**QQ(3, 7)); R
Polynomial ring in 1/a, a**(1/7) over ZZ with lex order

In the above example, \(1/a\) and \(a**(1/7)\) will be treated as completely different atoms. For all practical purposes, we could let \(b = 1/a\) and \(c = a**(1/7)\) and do the manipulations. Effectively, expressions involving \(1/a\) and \(a**(1/7)\) (and their powers) will never simplify:

>>> expr*R(1/a) 
(1/a)**2 + (1/a)*(a**(1/7))**3

This leads to similar issues with manipulating Laurent and Puiseux series as faced earlier. Fortunately, this time we have an elegant solution and are able to isolate the series and polys behaviour from one another. We introduce a boolean flag series in the list of allowed Options for polynomials (see sympy.polys.polyoptions.Options). Thus, when we want sring to allow rational exponents we supply a series=True flag to sring:

>>> rs_series(sin(a**QQ(1, 2)), a, 3) 
-1/5040*a**(7/3) + 1/120*a**(5/3) - 1/6*a + a**(1/3)

Contribute

\(rs\_series\) is not fully implemented yet. As of now, it supports only multivariate Taylor expansions of expressions involving sin, cos, exp and tan. Adding the remaining functions is not at all difficult and they will be gradually added. If you are interested in helping, read the comments in ring_series.py. Currently, it does not support Puiseux series (though the elementary functions do). This is expected to be fixed soon.

You can also add more functions to ring_series.py. Only elementary functions are supported currently. The long term goal is to replace SymPy’s current series method with rs_series.

Manipulation of power series

Functions in this module carry the prefix rs_, standing for “ring series”. They manipulate finite power series in the sparse representation provided by polys.ring.ring.

Elementary functions

sympy.polys.ring_series.rs_log(p, x, prec)[source]

The Logarithm of p modulo O(x**prec).

Notes

Truncation of integral dx p**-1*d p/dx is used.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_log
>>> R, x = ring('x', QQ)
>>> rs_log(1 + x, x, 8)
1/7*x**7 - 1/6*x**6 + 1/5*x**5 - 1/4*x**4 + 1/3*x**3 - 1/2*x**2 + x
>>> rs_log(x**QQ(3, 2) + 1, x, 5)
1/3*x**(9/2) - 1/2*x**3 + x**(3/2)
sympy.polys.ring_series.rs_LambertW(p, x, prec)[source]

Calculate the series expansion of the principal branch of the Lambert W function.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_LambertW
>>> R, x, y = ring('x, y', QQ)
>>> rs_LambertW(x + x*y, x, 3)
-x**2*y**2 - 2*x**2*y - x**2 + x*y + x

See also

LambertW

sympy.polys.ring_series.rs_exp(p, x, prec)[source]

Exponentiation of a series modulo O(x**prec)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_exp
>>> R, x = ring('x', QQ)
>>> rs_exp(x**2, x, 7)
1/6*x**6 + 1/2*x**4 + x**2 + 1
sympy.polys.ring_series.rs_atan(p, x, prec)[source]

The arctangent of a series

Return the series expansion of the atan of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_atan
>>> R, x, y = ring('x, y', QQ)
>>> rs_atan(x + x*y, x, 4)
-1/3*x**3*y**3 - x**3*y**2 - x**3*y - 1/3*x**3 + x*y + x

See also

atan

sympy.polys.ring_series.rs_asin(p, x, prec)[source]

Arcsine of a series

Return the series expansion of the asin of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_asin
>>> R, x, y = ring('x, y', QQ)
>>> rs_asin(x, x, 8)
5/112*x**7 + 3/40*x**5 + 1/6*x**3 + x

See also

asin

sympy.polys.ring_series.rs_tan(p, x, prec)[source]

Tangent of a series.

Return the series expansion of the tan of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_tan
>>> R, x, y = ring('x, y', QQ)
>>> rs_tan(x + x*y, x, 4)
1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x

See also

_tan1, tan

sympy.polys.ring_series.rs_cot(p, x, prec)[source]

Cotangent of a series

Return the series expansion of the cot of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_cot
>>> R, x, y = ring('x, y', QQ)
>>> rs_cot(x, x, 6)
-2/945*x**5 - 1/45*x**3 - 1/3*x + x**(-1)

See also

cot

sympy.polys.ring_series.rs_sin(p, x, prec)[source]

Sine of a series

Return the series expansion of the sin of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_sin
>>> R, x, y = ring('x, y', QQ)
>>> rs_sin(x + x*y, x, 4)
-1/6*x**3*y**3 - 1/2*x**3*y**2 - 1/2*x**3*y - 1/6*x**3 + x*y + x
>>> rs_sin(x**QQ(3, 2) + x*y**QQ(7, 5), x, 4)
-1/2*x**(7/2)*y**(14/5) - 1/6*x**3*y**(21/5) + x**(3/2) + x*y**(7/5)

See also

sin

sympy.polys.ring_series.rs_cos(p, x, prec)[source]

Cosine of a series

Return the series expansion of the cos of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_cos
>>> R, x, y = ring('x, y', QQ)
>>> rs_cos(x + x*y, x, 4)
-1/2*x**2*y**2 - x**2*y - 1/2*x**2 + 1
>>> rs_cos(x + x*y, x, 4)/x**QQ(7, 5)
-1/2*x**(3/5)*y**2 - x**(3/5)*y - 1/2*x**(3/5) + x**(-7/5)

See also

cos

sympy.polys.ring_series.rs_cos_sin(p, x, prec)[source]

Return the tuple \((rs\_cos(p, x, prec)\), \(rs\_sin(p, x, prec))\).

Is faster than calling rs_cos and rs_sin separately

sympy.polys.ring_series.rs_atanh(p, x, prec)[source]

Hyperbolic arctangent of a series

Return the series expansion of the atanh of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_atanh
>>> R, x, y = ring('x, y', QQ)
>>> rs_atanh(x + x*y, x, 4)
1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x

See also

atanh

sympy.polys.ring_series.rs_sinh(p, x, prec)[source]

Hyperbolic sine of a series

Return the series expansion of the sinh of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_sinh
>>> R, x, y = ring('x, y', QQ)
>>> rs_sinh(x + x*y, x, 4)
1/6*x**3*y**3 + 1/2*x**3*y**2 + 1/2*x**3*y + 1/6*x**3 + x*y + x

See also

sinh

sympy.polys.ring_series.rs_cosh(p, x, prec)[source]

Hyperbolic cosine of a series

Return the series expansion of the cosh of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_cosh
>>> R, x, y = ring('x, y', QQ)
>>> rs_cosh(x + x*y, x, 4)
1/2*x**2*y**2 + x**2*y + 1/2*x**2 + 1

See also

cosh

sympy.polys.ring_series.rs_tanh(p, x, prec)[source]

Hyperbolic tangent of a series

Return the series expansion of the tanh of p, about 0.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_tanh
>>> R, x, y = ring('x, y', QQ)
>>> rs_tanh(x + x*y, x, 4)
-1/3*x**3*y**3 - x**3*y**2 - x**3*y - 1/3*x**3 + x*y + x

See also

tanh

sympy.polys.ring_series.rs_hadamard_exp(p1, inverse=False)[source]

Return sum f_i/i!*x**i from sum f_i*x**i, where x is the first variable.

If invers=True return sum f_i*i!*x**i

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_hadamard_exp
>>> R, x = ring('x', QQ)
>>> p = 1 + x + x**2 + x**3
>>> rs_hadamard_exp(p)
1/6*x**3 + 1/2*x**2 + x + 1

Operations

sympy.polys.ring_series.rs_mul(p1, p2, x, prec)[source]

Return the product of the given two series, modulo O(x**prec).

x is the series variable or its position in the generators.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_mul
>>> R, x = ring('x', QQ)
>>> p1 = x**2 + 2*x + 1
>>> p2 = x + 1
>>> rs_mul(p1, p2, x, 3)
3*x**2 + 3*x + 1
sympy.polys.ring_series.rs_square(p1, x, prec)[source]

Square the series modulo O(x**prec)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_square
>>> R, x = ring('x', QQ)
>>> p = x**2 + 2*x + 1
>>> rs_square(p, x, 3)
6*x**2 + 4*x + 1
sympy.polys.ring_series.rs_pow(p1, n, x, prec)[source]

Return p1**n modulo O(x**prec)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_pow
>>> R, x = ring('x', QQ)
>>> p = x + 1
>>> rs_pow(p, 4, x, 3)
6*x**2 + 4*x + 1
sympy.polys.ring_series.rs_series_inversion(p, x, prec)[source]

Multivariate series inversion 1/p modulo O(x**prec).

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_series_inversion
>>> R, x, y = ring('x, y', QQ)
>>> rs_series_inversion(1 + x*y**2, x, 4)
-x**3*y**6 + x**2*y**4 - x*y**2 + 1
>>> rs_series_inversion(1 + x*y**2, y, 4)
-x*y**2 + 1
>>> rs_series_inversion(x + x**2, x, 4)
x**3 - x**2 + x - 1 + x**(-1)
sympy.polys.ring_series.rs_series_reversion(p, x, n, y)[source]

Reversion of a series.

p is a series with O(x**n) of the form \(p = a*x + f(x)\) where \(a\) is a number different from 0.

\(f(x) = sum( a\_k*x\_k, k in range(2, n))\)

a_k : Can depend polynomially on other variables, not indicated. x : Variable with name x. y : Variable with name y.

Solve \(p = y\), that is, given \(a*x + f(x) - y = 0\), find the solution x = r(y) up to O(y**n)

Algorithm:

If \(r\_i\) is the solution at order i, then: \(a*r\_i + f(r\_i) - y = O(y**(i + 1))\)

and if r_(i + 1) is the solution at order i + 1, then: \(a*r\_(i + 1) + f(r\_(i + 1)) - y = O(y**(i + 2))\)

We have, r_(i + 1) = r_i + e, such that, \(a*e + f(r\_i) = O(y**(i + 2))\) or \(e = -f(r\_i)/a\)

So we use the recursion relation: \(r\_(i + 1) = r\_i - f(r\_i)/a\) with the boundary condition: \(r\_1 = y\)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_series_reversion, rs_trunc
>>> R, x, y, a, b = ring('x, y, a, b', QQ)
>>> p = x - x**2 - 2*b*x**2 + 2*a*b*x**2
>>> p1 = rs_series_reversion(p, x, 3, y); p1
-2*y**2*a*b + 2*y**2*b + y**2 + y
>>> rs_trunc(p.compose(x, p1), y, 3)
y
sympy.polys.ring_series.rs_nth_root(p, n, x, prec)[source]

Multivariate series expansion of the nth root of p.

Parameters

p : Expr

The polynomial to computer the root of.

n : integer

The order of the root to be computed.

x : PolyElement

prec : integer

Order of the expanded series.

Notes

The result of this function is dependent on the ring over which the polynomial has been defined. If the answer involves a root of a constant, make sure that the polynomial is over a real field. It can not yet handle roots of symbols.

Examples

>>> from sympy.polys.domains import QQ, RR
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_nth_root
>>> R, x, y = ring('x, y', QQ)
>>> rs_nth_root(1 + x + x*y, -3, x, 3)
2/9*x**2*y**2 + 4/9*x**2*y + 2/9*x**2 - 1/3*x*y - 1/3*x + 1
>>> R, x, y = ring('x, y', RR)
>>> rs_nth_root(3 + x + x*y, 3, x, 2)
0.160249952256379*x*y + 0.160249952256379*x + 1.44224957030741
sympy.polys.ring_series.rs_trunc(p1, x, prec)[source]

Truncate the series in the x variable with precision prec, that is, modulo O(x**prec)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_trunc
>>> R, x = ring('x', QQ)
>>> p = x**10 + x**5 + x + 1
>>> rs_trunc(p, x, 12)
x**10 + x**5 + x + 1
>>> rs_trunc(p, x, 10)
x**5 + x + 1
sympy.polys.ring_series.rs_subs(p, rules, x, prec)[source]

Substitution with truncation according to the mapping in rules.

Return a series with precision prec in the generator x

Note that substitutions are not done one after the other

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_subs
>>> R, x, y = ring('x, y', QQ)
>>> p = x**2 + y**2
>>> rs_subs(p, {x: x+ y, y: x+ 2*y}, x, 3)
2*x**2 + 6*x*y + 5*y**2
>>> (x + y)**2 + (x + 2*y)**2
2*x**2 + 6*x*y + 5*y**2

which differs from

>>> rs_subs(rs_subs(p, {x: x+ y}, x, 3), {y: x+ 2*y}, x, 3)
5*x**2 + 12*x*y + 8*y**2
Parameters

p : PolyElement Input series.

rules : dict with substitution mappings.

x : PolyElement in which the series truncation is to be done.

prec : Integer order of the series after truncation.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_subs
>>> R, x, y = ring('x, y', QQ)
>>> rs_subs(x**2+y**2, {y: (x+y)**2}, x, 3)
 6*x**2*y**2 + x**2 + 4*x*y**3 + y**4
sympy.polys.ring_series.rs_diff(p, x)[source]

Return partial derivative of p with respect to x.

Parameters

x : PolyElement with respect to which p is differentiated.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_diff
>>> R, x, y = ring('x, y', QQ)
>>> p = x + x**2*y**3
>>> rs_diff(p, x)
2*x*y**3 + 1
sympy.polys.ring_series.rs_integrate(p, x)[source]

Integrate p with respect to x.

Parameters

x : PolyElement with respect to which p is integrated.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_integrate
>>> R, x, y = ring('x, y', QQ)
>>> p = x + x**2*y**3
>>> rs_integrate(p, x)
1/3*x**3*y**3 + 1/2*x**2
sympy.polys.ring_series.rs_newton(p, x, prec)[source]

Compute the truncated Newton sum of the polynomial p

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_newton
>>> R, x = ring('x', QQ)
>>> p = x**2 - 2
>>> rs_newton(p, x, 5)
8*x**4 + 4*x**2 + 2
sympy.polys.ring_series.rs_compose_add(p1, p2)[source]

compute the composed sum prod(p2(x - beta) for beta root of p1)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_compose_add
>>> R, x = ring('x', QQ)
>>> f = x**2 - 2
>>> g = x**2 - 3
>>> rs_compose_add(f, g)
x**4 - 10*x**2 + 1

References

R568

A. Bostan, P. Flajolet, B. Salvy and E. Schost “Fast Computation with Two Algebraic Numbers”, (2002) Research Report 4579, Institut National de Recherche en Informatique et en Automatique

Utility functions

sympy.polys.ring_series.rs_is_puiseux(p, x)[source]

Test if p is Puiseux series in x.

Raise an exception if it has a negative power in x.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_is_puiseux
>>> R, x = ring('x', QQ)
>>> p = x**QQ(2,5) + x**QQ(2,3) + x
>>> rs_is_puiseux(p, x)
True
sympy.polys.ring_series.rs_puiseux(f, p, x, prec)[source]

Return the puiseux series for \(f(p, x, prec)\).

To be used when function f is implemented only for regular series.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_puiseux, rs_exp
>>> R, x = ring('x', QQ)
>>> p = x**QQ(2,5) + x**QQ(2,3) + x
>>> rs_puiseux(rs_exp,p, x, 1)
1/2*x**(4/5) + x**(2/3) + x**(2/5) + 1
sympy.polys.ring_series.rs_puiseux2(f, p, q, x, prec)[source]

Return the puiseux series for \(f(p, q, x, prec)\).

To be used when function f is implemented only for regular series.

sympy.polys.ring_series.rs_series_from_list(p, c, x, prec, concur=1)[source]

Return a series \(sum c[n]*p**n\) modulo \(O(x**prec)\).

It reduces the number of multiplications by summing concurrently.

\(ax = [1, p, p**2, .., p**(J - 1)]\) \(s = sum(c[i]*ax[i]\) for i in \(range(r, (r + 1)*J))*p**((K - 1)*J)\) with \(K >= (n + 1)/J\)

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_series_from_list, rs_trunc
>>> R, x = ring('x', QQ)
>>> p = x**2 + x + 1
>>> c = [1, 2, 3]
>>> rs_series_from_list(p, c, x, 4)
6*x**3 + 11*x**2 + 8*x + 6
>>> rs_trunc(1 + 2*p + 3*p**2, x, 4)
6*x**3 + 11*x**2 + 8*x + 6
>>> pc = R.from_list(list(reversed(c)))
>>> rs_trunc(pc.compose(x, p), x, 4)
6*x**3 + 11*x**2 + 8*x + 6

See also

sympy.polys.ring.compose

sympy.polys.ring_series.rs_fun(p, f, *args)[source]

Function of a multivariate series computed by substitution.

The case with f method name is used to compute \(rs\_tan\) and \(rs\_nth\_root\) of a multivariate series:

\(rs\_fun(p, tan, iv, prec)\)

tan series is first computed for a dummy variable _x, i.e, \(rs\_tan(\_x, iv, prec)\). Then we substitute _x with p to get the desired series

Parameters

p : PolyElement The multivariate series to be expanded.

f : \(ring\_series\) function to be applied on \(p\).

args[-2] : PolyElement with respect to which, the series is to be expanded.

args[-1] : Required order of the expanded series.

Examples

>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import rs_fun, _tan1
>>> R, x, y = ring('x, y', QQ)
>>> p = x + x*y + x**2*y + x**3*y**2
>>> rs_fun(p, _tan1, x, 4)
1/3*x**3*y**3 + 2*x**3*y**2 + x**3*y + 1/3*x**3 + x**2*y + x*y + x
sympy.polys.ring_series.mul_xin(p, i, n)[source]

Return \(p*x_i**n\).

\(x\_i\) is the ith variable in p.

sympy.polys.ring_series.pow_xin(p, i, n)[source]
>>> from sympy.polys.domains import QQ
>>> from sympy.polys.rings import ring
>>> from sympy.polys.ring_series import pow_xin
>>> R, x, y = ring('x, y', QQ)
>>> p = x**QQ(2,5) + x + x**QQ(2,3)
>>> index = p.ring.gens.index(x)
>>> pow_xin(p, index, 15)
x**15 + x**10 + x**6