Power Series¶
Sage provides an implementation of dense and sparse power series over any Sage base ring. This is the base class of the implementations of univariate and multivariate power series ring elements in Sage (see also Power Series Methods, Multivariate Power Series).
AUTHORS:
William Stein
David Harvey (2006-09-11): added solve_linear_de() method
Robert Bradshaw (2007-04): sqrt, rmul, lmul, shifting
Robert Bradshaw (2007-04): Cython version
Simon King (2012-08): use category and coercion framework, Issue #13412
EXAMPLES:
sage: R.<x> = PowerSeriesRing(ZZ)
sage: TestSuite(R).run()
sage: R([1,2,3])
1 + 2*x + 3*x^2
sage: R([1,2,3], 10)
1 + 2*x + 3*x^2 + O(x^10)
sage: f = 1 + 2*x - 3*x^3 + O(x^4); f
1 + 2*x - 3*x^3 + O(x^4)
sage: f^10
1 + 20*x + 180*x^2 + 930*x^3 + O(x^4)
sage: g = 1/f; g
1 - 2*x + 4*x^2 - 5*x^3 + O(x^4)
sage: g * f
1 + O(x^4)
>>> from sage.all import *
>>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1)
>>> TestSuite(R).run()
>>> R([Integer(1),Integer(2),Integer(3)])
1 + 2*x + 3*x^2
>>> R([Integer(1),Integer(2),Integer(3)], Integer(10))
1 + 2*x + 3*x^2 + O(x^10)
>>> f = Integer(1) + Integer(2)*x - Integer(3)*x**Integer(3) + O(x**Integer(4)); f
1 + 2*x - 3*x^3 + O(x^4)
>>> f**Integer(10)
1 + 20*x + 180*x^2 + 930*x^3 + O(x^4)
>>> g = Integer(1)/f; g
1 - 2*x + 4*x^2 - 5*x^3 + O(x^4)
>>> g * f
1 + O(x^4)
R.<x> = PowerSeriesRing(ZZ) TestSuite(R).run() R([1,2,3]) R([1,2,3], 10) f = 1 + 2*x - 3*x^3 + O(x^4); f f^10 g = 1/f; g g * f
In Python (as opposed to Sage) create the power series ring and its generator as follows:
sage: R = PowerSeriesRing(ZZ, 'x')
sage: x = R.gen()
sage: parent(x)
Power Series Ring in x over Integer Ring
>>> from sage.all import *
>>> R = PowerSeriesRing(ZZ, 'x')
>>> x = R.gen()
>>> parent(x)
Power Series Ring in x over Integer Ring
R = PowerSeriesRing(ZZ, 'x') x = R.gen() parent(x)
EXAMPLES:
This example illustrates that coercion for power series rings is consistent with coercion for polynomial rings.
sage: poly_ring1.<gen1> = PolynomialRing(QQ)
sage: poly_ring2.<gen2> = PolynomialRing(QQ)
sage: huge_ring.<x> = PolynomialRing(poly_ring1)
>>> from sage.all import *
>>> poly_ring1 = PolynomialRing(QQ, names=('gen1',)); (gen1,) = poly_ring1._first_ngens(1)
>>> poly_ring2 = PolynomialRing(QQ, names=('gen2',)); (gen2,) = poly_ring2._first_ngens(1)
>>> huge_ring = PolynomialRing(poly_ring1, names=('x',)); (x,) = huge_ring._first_ngens(1)
poly_ring1.<gen1> = PolynomialRing(QQ) poly_ring2.<gen2> = PolynomialRing(QQ) huge_ring.<x> = PolynomialRing(poly_ring1)
The generator of the first ring gets coerced in as itself, since it is the base ring.
sage: huge_ring(gen1)
gen1
>>> from sage.all import *
>>> huge_ring(gen1)
gen1
huge_ring(gen1)
The generator of the second ring gets mapped via the natural map sending one generator to the other.
sage: huge_ring(gen2)
x
>>> from sage.all import *
>>> huge_ring(gen2)
x
huge_ring(gen2)
With power series the behavior is the same.
sage: power_ring1.<gen1> = PowerSeriesRing(QQ)
sage: power_ring2.<gen2> = PowerSeriesRing(QQ)
sage: huge_power_ring.<x> = PowerSeriesRing(power_ring1)
sage: huge_power_ring(gen1)
gen1
sage: huge_power_ring(gen2)
x
>>> from sage.all import *
>>> power_ring1 = PowerSeriesRing(QQ, names=('gen1',)); (gen1,) = power_ring1._first_ngens(1)
>>> power_ring2 = PowerSeriesRing(QQ, names=('gen2',)); (gen2,) = power_ring2._first_ngens(1)
>>> huge_power_ring = PowerSeriesRing(power_ring1, names=('x',)); (x,) = huge_power_ring._first_ngens(1)
>>> huge_power_ring(gen1)
gen1
>>> huge_power_ring(gen2)
x
power_ring1.<gen1> = PowerSeriesRing(QQ) power_ring2.<gen2> = PowerSeriesRing(QQ) huge_power_ring.<x> = PowerSeriesRing(power_ring1) huge_power_ring(gen1) huge_power_ring(gen2)
- class sage.rings.power_series_ring_element.PowerSeries[source]¶
Bases:
AlgebraElement
A power series. Base class of univariate and multivariate power series. The following methods are available with both types of objects.
- O(prec)[source]¶
Return this series plus \(O(x^\text{prec})\). Does not change
self
.EXAMPLES:
sage: R.<x> = PowerSeriesRing(ZZ) sage: p = 1 + x^2 + x^10; p 1 + x^2 + x^10 sage: p.O(15) 1 + x^2 + x^10 + O(x^15) sage: p.O(5) 1 + x^2 + O(x^5) sage: p.O(-5) Traceback (most recent call last): ... ValueError: prec (= -5) must be nonnegative
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> p = Integer(1) + x**Integer(2) + x**Integer(10); p 1 + x^2 + x^10 >>> p.O(Integer(15)) 1 + x^2 + x^10 + O(x^15) >>> p.O(Integer(5)) 1 + x^2 + O(x^5) >>> p.O(-Integer(5)) Traceback (most recent call last): ... ValueError: prec (= -5) must be nonnegative
R.<x> = PowerSeriesRing(ZZ) p = 1 + x^2 + x^10; p p.O(15) p.O(5) p.O(-5)
- V(n)[source]¶
If \(f = \sum a_m x^m\), then this function returns \(\sum a_m x^{nm}\).
EXAMPLES:
sage: R.<x> = PowerSeriesRing(ZZ) sage: p = 1 + x^2 + x^10; p 1 + x^2 + x^10 sage: p.V(3) 1 + x^6 + x^30 sage: (p + O(x^20)).V(3) 1 + x^6 + x^30 + O(x^60)
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> p = Integer(1) + x**Integer(2) + x**Integer(10); p 1 + x^2 + x^10 >>> p.V(Integer(3)) 1 + x^6 + x^30 >>> (p + O(x**Integer(20))).V(Integer(3)) 1 + x^6 + x^30 + O(x^60)
R.<x> = PowerSeriesRing(ZZ) p = 1 + x^2 + x^10; p p.V(3) (p + O(x^20)).V(3)
- add_bigoh(prec)[source]¶
Return the power series of precision at most
prec
got by adding \(O(q^\text{prec})\) to \(f\), where \(q\) is the variable.EXAMPLES:
sage: R.<A> = RDF[[]] sage: f = (1+A+O(A^5))^5; f 1.0 + 5.0*A + 10.0*A^2 + 10.0*A^3 + 5.0*A^4 + O(A^5) sage: f.add_bigoh(3) 1.0 + 5.0*A + 10.0*A^2 + O(A^3) sage: f.add_bigoh(5) 1.0 + 5.0*A + 10.0*A^2 + 10.0*A^3 + 5.0*A^4 + O(A^5)
>>> from sage.all import * >>> R = RDF[['A']]; (A,) = R._first_ngens(1) >>> f = (Integer(1)+A+O(A**Integer(5)))**Integer(5); f 1.0 + 5.0*A + 10.0*A^2 + 10.0*A^3 + 5.0*A^4 + O(A^5) >>> f.add_bigoh(Integer(3)) 1.0 + 5.0*A + 10.0*A^2 + O(A^3) >>> f.add_bigoh(Integer(5)) 1.0 + 5.0*A + 10.0*A^2 + 10.0*A^3 + 5.0*A^4 + O(A^5)
R.<A> = RDF[[]] f = (1+A+O(A^5))^5; f f.add_bigoh(3) f.add_bigoh(5)
- base_extend(R)[source]¶
Return a copy of this power series but with coefficients in R.
The following coercion uses
base_extend
implicitly:sage: R.<t> = ZZ[['t']] sage: (t - t^2) * Mod(1, 3) t + 2*t^2
>>> from sage.all import * >>> R = ZZ[['t']]; (t,) = R._first_ngens(1) >>> (t - t**Integer(2)) * Mod(Integer(1), Integer(3)) t + 2*t^2
R.<t> = ZZ[['t']] (t - t^2) * Mod(1, 3)
- base_ring()[source]¶
Return the base ring that this power series is defined over.
EXAMPLES:
sage: R.<t> = GF(49,'alpha')[[]] # needs sage.rings.finite_rings sage: (t^2 + O(t^3)).base_ring() # needs sage.rings.finite_rings Finite Field in alpha of size 7^2
>>> from sage.all import * >>> R = GF(Integer(49),'alpha')[['t']]; (t,) = R._first_ngens(1)# needs sage.rings.finite_rings >>> (t**Integer(2) + O(t**Integer(3))).base_ring() # needs sage.rings.finite_rings Finite Field in alpha of size 7^2
R.<t> = GF(49,'alpha')[[]] # needs sage.rings.finite_rings (t^2 + O(t^3)).base_ring() # needs sage.rings.finite_rings
- change_ring(R)[source]¶
Change if possible the coefficients of
self
to lie in R.EXAMPLES:
sage: R.<T> = QQ[[]]; R Power Series Ring in T over Rational Field sage: f = 1 - 1/2*T + 1/3*T^2 + O(T^3) sage: f.base_extend(GF(5)) Traceback (most recent call last): ... TypeError: no base extension defined sage: f.change_ring(GF(5)) 1 + 2*T + 2*T^2 + O(T^3) sage: f.change_ring(GF(3)) Traceback (most recent call last): ... ZeroDivisionError: inverse of Mod(0, 3) does not exist
>>> from sage.all import * >>> R = QQ[['T']]; (T,) = R._first_ngens(1); R Power Series Ring in T over Rational Field >>> f = Integer(1) - Integer(1)/Integer(2)*T + Integer(1)/Integer(3)*T**Integer(2) + O(T**Integer(3)) >>> f.base_extend(GF(Integer(5))) Traceback (most recent call last): ... TypeError: no base extension defined >>> f.change_ring(GF(Integer(5))) 1 + 2*T + 2*T^2 + O(T^3) >>> f.change_ring(GF(Integer(3))) Traceback (most recent call last): ... ZeroDivisionError: inverse of Mod(0, 3) does not exist
R.<T> = QQ[[]]; R f = 1 - 1/2*T + 1/3*T^2 + O(T^3) f.base_extend(GF(5)) f.change_ring(GF(5)) f.change_ring(GF(3))
We can only change the ring if there is a
__call__
coercion defined. The following succeeds becauseZZ(K(4))
is defined.sage: K.<a> = NumberField(cyclotomic_polynomial(3), 'a') # needs sage.rings.number_field sage: R.<t> = K[['t']] # needs sage.rings.number_field sage: (4*t).change_ring(ZZ) # needs sage.rings.number_field 4*t
>>> from sage.all import * >>> K = NumberField(cyclotomic_polynomial(Integer(3)), 'a', names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field >>> R = K[['t']]; (t,) = R._first_ngens(1)# needs sage.rings.number_field >>> (Integer(4)*t).change_ring(ZZ) # needs sage.rings.number_field 4*t
K.<a> = NumberField(cyclotomic_polynomial(3), 'a') # needs sage.rings.number_field R.<t> = K[['t']] # needs sage.rings.number_field (4*t).change_ring(ZZ) # needs sage.rings.number_field
This does not succeed because
ZZ(K(a+1))
is not defined.sage: K.<a> = NumberField(cyclotomic_polynomial(3), 'a') # needs sage.rings.number_field sage: R.<t> = K[['t']] # needs sage.rings.number_field sage: ((a+1)*t).change_ring(ZZ) # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: Unable to coerce a + 1 to an integer
>>> from sage.all import * >>> K = NumberField(cyclotomic_polynomial(Integer(3)), 'a', names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field >>> R = K[['t']]; (t,) = R._first_ngens(1)# needs sage.rings.number_field >>> ((a+Integer(1))*t).change_ring(ZZ) # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: Unable to coerce a + 1 to an integer
K.<a> = NumberField(cyclotomic_polynomial(3), 'a') # needs sage.rings.number_field R.<t> = K[['t']] # needs sage.rings.number_field ((a+1)*t).change_ring(ZZ) # needs sage.rings.number_field
- coefficients()[source]¶
Return the nonzero coefficients of
self
.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ) sage: f = t + t^2 - 10/3*t^3 sage: f.coefficients() [1, 1, -10/3]
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1) >>> f = t + t**Integer(2) - Integer(10)/Integer(3)*t**Integer(3) >>> f.coefficients() [1, 1, -10/3]
R.<t> = PowerSeriesRing(QQ) f = t + t^2 - 10/3*t^3 f.coefficients()
- common_prec(f)[source]¶
Return minimum precision of \(f\) and
self
.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ)
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1)
R.<t> = PowerSeriesRing(QQ)
sage: f = t + t^2 + O(t^3) sage: g = t + t^3 + t^4 + O(t^4) sage: f.common_prec(g) 3 sage: g.common_prec(f) 3
>>> from sage.all import * >>> f = t + t**Integer(2) + O(t**Integer(3)) >>> g = t + t**Integer(3) + t**Integer(4) + O(t**Integer(4)) >>> f.common_prec(g) 3 >>> g.common_prec(f) 3
f = t + t^2 + O(t^3) g = t + t^3 + t^4 + O(t^4) f.common_prec(g) g.common_prec(f)
>>> from sage.all import * >>> f = t + t**Integer(2) + O(t**Integer(3)) >>> g = t + t**Integer(3) + t**Integer(4) + O(t**Integer(4)) >>> f.common_prec(g) 3 >>> g.common_prec(f) 3
f = t + t^2 + O(t^3) g = t + t^3 + t^4 + O(t^4) f.common_prec(g) g.common_prec(f)
sage: f = t + t^2 + O(t^3) sage: g = t^2 sage: f.common_prec(g) 3 sage: g.common_prec(f) 3
>>> from sage.all import * >>> f = t + t**Integer(2) + O(t**Integer(3)) >>> g = t**Integer(2) >>> f.common_prec(g) 3 >>> g.common_prec(f) 3
f = t + t^2 + O(t^3) g = t^2 f.common_prec(g) g.common_prec(f)
>>> from sage.all import * >>> f = t + t**Integer(2) + O(t**Integer(3)) >>> g = t**Integer(2) >>> f.common_prec(g) 3 >>> g.common_prec(f) 3
f = t + t^2 + O(t^3) g = t^2 f.common_prec(g) g.common_prec(f)
sage: f = t + t^2 sage: f = t^2 sage: f.common_prec(g) +Infinity
>>> from sage.all import * >>> f = t + t**Integer(2) >>> f = t**Integer(2) >>> f.common_prec(g) +Infinity
f = t + t^2 f = t^2 f.common_prec(g)
>>> from sage.all import * >>> f = t + t**Integer(2) >>> f = t**Integer(2) >>> f.common_prec(g) +Infinity
f = t + t^2 f = t^2 f.common_prec(g)
- cos(prec='infinity')[source]¶
Apply cos to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: cos(f) 1 - 1/2*t^2 - t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> cos(f) 1 - 1/2*t^2 - t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) cos(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: cos(f) 1 - 1/2*a^2 - a*b - 1/2*b^2 + O(a, b)^3 sage: f.cos() 1 - 1/2*a^2 - a*b - 1/2*b^2 + O(a, b)^3 sage: f.cos(prec=2) 1 + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> cos(f) 1 - 1/2*a^2 - a*b - 1/2*b^2 + O(a, b)^3 >>> f.cos() 1 - 1/2*a^2 - a*b - 1/2*b^2 + O(a, b)^3 >>> f.cos(prec=Integer(2)) 1 + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) cos(f) f.cos() f.cos(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2+f sage: cos(g) Traceback (most recent call last): ... ValueError: can only apply cos to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2)+f >>> cos(g) Traceback (most recent call last): ... ValueError: can only apply cos to formal power series with zero constant term
g = 2+f cos(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: cos(a) 1 - 1/2*a^2 + 1/24*a^4 - 1/720*a^6 + 1/40320*a^8 - 1/3628800*a^10 + O(a, b)^12 sage: a.cos(prec=5) 1 - 1/2*a^2 + 1/24*a^4 + O(a, b)^5 sage: cos(a + T.O(5)) 1 - 1/2*a^2 + 1/24*a^4 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> cos(a) 1 - 1/2*a^2 + 1/24*a^4 - 1/720*a^6 + 1/40320*a^8 - 1/3628800*a^10 + O(a, b)^12 >>> a.cos(prec=Integer(5)) 1 - 1/2*a^2 + 1/24*a^4 + O(a, b)^5 >>> cos(a + T.O(Integer(5))) 1 - 1/2*a^2 + 1/24*a^4 + O(a, b)^5
T.default_prec() cos(a) a.cos(prec=5) cos(a + T.O(5))
- cosh(prec='infinity')[source]¶
Apply cosh to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: cosh(f) 1 + 1/2*t^2 + t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> cosh(f) 1 + 1/2*t^2 + t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) cosh(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: cosh(f) 1 + 1/2*a^2 + a*b + 1/2*b^2 + O(a, b)^3 sage: f.cosh() 1 + 1/2*a^2 + a*b + 1/2*b^2 + O(a, b)^3 sage: f.cosh(prec=2) 1 + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> cosh(f) 1 + 1/2*a^2 + a*b + 1/2*b^2 + O(a, b)^3 >>> f.cosh() 1 + 1/2*a^2 + a*b + 1/2*b^2 + O(a, b)^3 >>> f.cosh(prec=Integer(2)) 1 + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) cosh(f) f.cosh() f.cosh(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2 + f sage: cosh(g) Traceback (most recent call last): ... ValueError: can only apply cosh to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2) + f >>> cosh(g) Traceback (most recent call last): ... ValueError: can only apply cosh to formal power series with zero constant term
g = 2 + f cosh(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: cosh(a) 1 + 1/2*a^2 + 1/24*a^4 + 1/720*a^6 + 1/40320*a^8 + 1/3628800*a^10 + O(a, b)^12 sage: a.cosh(prec=5) 1 + 1/2*a^2 + 1/24*a^4 + O(a, b)^5 sage: cosh(a + T.O(5)) 1 + 1/2*a^2 + 1/24*a^4 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> cosh(a) 1 + 1/2*a^2 + 1/24*a^4 + 1/720*a^6 + 1/40320*a^8 + 1/3628800*a^10 + O(a, b)^12 >>> a.cosh(prec=Integer(5)) 1 + 1/2*a^2 + 1/24*a^4 + O(a, b)^5 >>> cosh(a + T.O(Integer(5))) 1 + 1/2*a^2 + 1/24*a^4 + O(a, b)^5
T.default_prec() cosh(a) a.cosh(prec=5) cosh(a + T.O(5))
- degree()[source]¶
Return the degree of this power series, which is by definition the degree of the underlying polynomial.
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ, sparse=True) sage: f = t^100000 + O(t^10000000) sage: f.degree() 100000
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> f = t**Integer(100000) + O(t**Integer(10000000)) >>> f.degree() 100000
R.<t> = PowerSeriesRing(QQ, sparse=True) f = t^100000 + O(t^10000000) f.degree()
- derivative(*args)[source]¶
The formal derivative of this power series, with respect to variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function for more details.
See also
_derivative()
EXAMPLES:
sage: R.<x> = PowerSeriesRing(QQ) sage: g = -x + x^2/2 - x^4 + O(x^6) sage: g.derivative() -1 + x - 4*x^3 + O(x^5) sage: g.derivative(x) -1 + x - 4*x^3 + O(x^5) sage: g.derivative(x, x) 1 - 12*x^2 + O(x^4) sage: g.derivative(x, 2) 1 - 12*x^2 + O(x^4)
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> g = -x + x**Integer(2)/Integer(2) - x**Integer(4) + O(x**Integer(6)) >>> g.derivative() -1 + x - 4*x^3 + O(x^5) >>> g.derivative(x) -1 + x - 4*x^3 + O(x^5) >>> g.derivative(x, x) 1 - 12*x^2 + O(x^4) >>> g.derivative(x, Integer(2)) 1 - 12*x^2 + O(x^4)
R.<x> = PowerSeriesRing(QQ) g = -x + x^2/2 - x^4 + O(x^6) g.derivative() g.derivative(x) g.derivative(x, x) g.derivative(x, 2)
- egf_to_ogf()[source]¶
Return the ordinary generating function power series, assuming
self
is an exponential generating function power series.This is a formal Laplace transform.
This function is known as pari:serlaplace in PARI/GP.
See also
ogf_to_egf()
for the inverse method.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ) sage: f = t + t^2/factorial(2) + 2*t^3/factorial(3) sage: f.egf_to_ogf() t + t^2 + 2*t^3
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1) >>> f = t + t**Integer(2)/factorial(Integer(2)) + Integer(2)*t**Integer(3)/factorial(Integer(3)) >>> f.egf_to_ogf() t + t^2 + 2*t^3
R.<t> = PowerSeriesRing(QQ) f = t + t^2/factorial(2) + 2*t^3/factorial(3) f.egf_to_ogf()
- exp(prec=None)[source]¶
Return exp of this power series to the indicated precision.
INPUT:
prec
– integer (default:self.parent().default_prec
)
ALGORITHM: See
solve_linear_de()
.Note
Screwy things can happen if the coefficient ring is not a field of characteristic zero. See
solve_linear_de()
.
AUTHORS:
David Harvey (2006-09-08): rewrote to use simplest possible “lazy” algorithm.
David Harvey (2006-09-10): rewrote to use divide-and-conquer strategy.
David Harvey (2006-09-11): factored functionality out to solve_linear_de().
Sourav Sen Gupta, David Harvey (2008-11): handle constant term
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ, default_prec=10)
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, default_prec=Integer(10), names=('t',)); (t,) = R._first_ngens(1)
R.<t> = PowerSeriesRing(QQ, default_prec=10)
Check that \(\exp(t)\) is, well, \(\exp(t)\):
sage: (t + O(t^10)).exp() 1 + t + 1/2*t^2 + 1/6*t^3 + 1/24*t^4 + 1/120*t^5 + 1/720*t^6 + 1/5040*t^7 + 1/40320*t^8 + 1/362880*t^9 + O(t^10)
>>> from sage.all import * >>> (t + O(t**Integer(10))).exp() 1 + t + 1/2*t^2 + 1/6*t^3 + 1/24*t^4 + 1/120*t^5 + 1/720*t^6 + 1/5040*t^7 + 1/40320*t^8 + 1/362880*t^9 + O(t^10)
(t + O(t^10)).exp()
Check that \(\exp(\log(1+t))\) is \(1+t\):
sage: (sum([-(-t)^n/n for n in range(1, 10)]) + O(t^10)).exp() 1 + t + O(t^10)
>>> from sage.all import * >>> (sum([-(-t)**n/n for n in range(Integer(1), Integer(10))]) + O(t**Integer(10))).exp() 1 + t + O(t^10)
(sum([-(-t)^n/n for n in range(1, 10)]) + O(t^10)).exp()
Check that \(\exp(2t + t^2 - t^5)\) is whatever it is:
sage: (2*t + t^2 - t^5 + O(t^10)).exp() 1 + 2*t + 3*t^2 + 10/3*t^3 + 19/6*t^4 + 8/5*t^5 - 7/90*t^6 - 538/315*t^7 - 425/168*t^8 - 30629/11340*t^9 + O(t^10)
>>> from sage.all import * >>> (Integer(2)*t + t**Integer(2) - t**Integer(5) + O(t**Integer(10))).exp() 1 + 2*t + 3*t^2 + 10/3*t^3 + 19/6*t^4 + 8/5*t^5 - 7/90*t^6 - 538/315*t^7 - 425/168*t^8 - 30629/11340*t^9 + O(t^10)
(2*t + t^2 - t^5 + O(t^10)).exp()
Check requesting lower precision:
sage: (t + t^2 - t^5 + O(t^10)).exp(5) 1 + t + 3/2*t^2 + 7/6*t^3 + 25/24*t^4 + O(t^5)
>>> from sage.all import * >>> (t + t**Integer(2) - t**Integer(5) + O(t**Integer(10))).exp(Integer(5)) 1 + t + 3/2*t^2 + 7/6*t^3 + 25/24*t^4 + O(t^5)
(t + t^2 - t^5 + O(t^10)).exp(5)
Can’t get more precision than the input:
sage: (t + t^2 + O(t^3)).exp(10) 1 + t + 3/2*t^2 + O(t^3)
>>> from sage.all import * >>> (t + t**Integer(2) + O(t**Integer(3))).exp(Integer(10)) 1 + t + 3/2*t^2 + O(t^3)
(t + t^2 + O(t^3)).exp(10)
Check some boundary cases:
sage: (t + O(t^2)).exp(1) 1 + O(t) sage: (t + O(t^2)).exp(0) O(t^0)
>>> from sage.all import * >>> (t + O(t**Integer(2))).exp(Integer(1)) 1 + O(t) >>> (t + O(t**Integer(2))).exp(Integer(0)) O(t^0)
(t + O(t^2)).exp(1) (t + O(t^2)).exp(0)
Handle nonzero constant term (fixes Issue #4477):
sage: # needs sage.rings.real_mpfr sage: R.<x> = PowerSeriesRing(RR) sage: (1 + x + x^2 + O(x^3)).exp() 2.71828182845905 + 2.71828182845905*x + 4.07742274268857*x^2 + O(x^3)
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> R = PowerSeriesRing(RR, names=('x',)); (x,) = R._first_ngens(1) >>> (Integer(1) + x + x**Integer(2) + O(x**Integer(3))).exp() 2.71828182845905 + 2.71828182845905*x + 4.07742274268857*x^2 + O(x^3)
# needs sage.rings.real_mpfr R.<x> = PowerSeriesRing(RR) (1 + x + x^2 + O(x^3)).exp()
sage: R.<x> = PowerSeriesRing(ZZ) sage: (1 + x + O(x^2)).exp() # needs sage.symbolic Traceback (most recent call last): ... ArithmeticError: exponential of constant term does not belong to coefficient ring (consider working in a larger ring)
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> (Integer(1) + x + O(x**Integer(2))).exp() # needs sage.symbolic Traceback (most recent call last): ... ArithmeticError: exponential of constant term does not belong to coefficient ring (consider working in a larger ring)
R.<x> = PowerSeriesRing(ZZ) (1 + x + O(x^2)).exp() # needs sage.symbolic
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> (Integer(1) + x + O(x**Integer(2))).exp() # needs sage.symbolic Traceback (most recent call last): ... ArithmeticError: exponential of constant term does not belong to coefficient ring (consider working in a larger ring)
R.<x> = PowerSeriesRing(ZZ) (1 + x + O(x^2)).exp() # needs sage.symbolic
sage: R.<x> = PowerSeriesRing(GF(5)) sage: (1 + x + O(x^2)).exp() Traceback (most recent call last): ... ArithmeticError: constant term of power series does not support exponentiation
>>> from sage.all import * >>> R = PowerSeriesRing(GF(Integer(5)), names=('x',)); (x,) = R._first_ngens(1) >>> (Integer(1) + x + O(x**Integer(2))).exp() Traceback (most recent call last): ... ArithmeticError: constant term of power series does not support exponentiation
R.<x> = PowerSeriesRing(GF(5)) (1 + x + O(x^2)).exp()
>>> from sage.all import * >>> R = PowerSeriesRing(GF(Integer(5)), names=('x',)); (x,) = R._first_ngens(1) >>> (Integer(1) + x + O(x**Integer(2))).exp() Traceback (most recent call last): ... ArithmeticError: constant term of power series does not support exponentiation
R.<x> = PowerSeriesRing(GF(5)) (1 + x + O(x^2)).exp()
- exponents()[source]¶
Return the exponents appearing in
self
with nonzero coefficients.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ) sage: f = t + t^2 - 10/3*t^3 sage: f.exponents() [1, 2, 3]
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1) >>> f = t + t**Integer(2) - Integer(10)/Integer(3)*t**Integer(3) >>> f.exponents() [1, 2, 3]
R.<t> = PowerSeriesRing(QQ) f = t + t^2 - 10/3*t^3 f.exponents()
- inverse()[source]¶
Return the inverse of self, i.e., self^(-1).
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ, sparse=True) sage: t.inverse() t^-1 sage: type(_) <class 'sage.rings.laurent_series_ring_element.LaurentSeries'> sage: (1-t).inverse() 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ...
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> t.inverse() t^-1 >>> type(_) <class 'sage.rings.laurent_series_ring_element.LaurentSeries'> >>> (Integer(1)-t).inverse() 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ...
R.<t> = PowerSeriesRing(QQ, sparse=True) t.inverse() type(_) (1-t).inverse()
- is_dense()[source]¶
EXAMPLES:
sage: R.<t> = PowerSeriesRing(ZZ) sage: t.is_dense() True sage: R.<t> = PowerSeriesRing(ZZ, sparse=True) sage: t.is_dense() False
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> t.is_dense() True >>> R = PowerSeriesRing(ZZ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> t.is_dense() False
R.<t> = PowerSeriesRing(ZZ) t.is_dense() R.<t> = PowerSeriesRing(ZZ, sparse=True) t.is_dense()
- is_gen()[source]¶
Return
True
if this is the generator (the variable) of the power series ring.EXAMPLES:
sage: R.<t> = QQ[[]] sage: t.is_gen() True sage: (1 + 2*t).is_gen() False
>>> from sage.all import * >>> R = QQ[['t']]; (t,) = R._first_ngens(1) >>> t.is_gen() True >>> (Integer(1) + Integer(2)*t).is_gen() False
R.<t> = QQ[[]] t.is_gen() (1 + 2*t).is_gen()
Note that this only returns
True
on the actual generator, not on something that happens to be equal to it.sage: (1*t).is_gen() False sage: 1*t == t True
>>> from sage.all import * >>> (Integer(1)*t).is_gen() False >>> Integer(1)*t == t True
(1*t).is_gen() 1*t == t
- is_monomial()[source]¶
Return
True
if this element is a monomial. That is, ifself
is \(x^n\) for some nonnegative integer \(n\).EXAMPLES:
sage: k.<z> = PowerSeriesRing(QQ, 'z') sage: z.is_monomial() True sage: k(1).is_monomial() True sage: (z+1).is_monomial() False sage: (z^2909).is_monomial() True sage: (3*z^2909).is_monomial() False
>>> from sage.all import * >>> k = PowerSeriesRing(QQ, 'z', names=('z',)); (z,) = k._first_ngens(1) >>> z.is_monomial() True >>> k(Integer(1)).is_monomial() True >>> (z+Integer(1)).is_monomial() False >>> (z**Integer(2909)).is_monomial() True >>> (Integer(3)*z**Integer(2909)).is_monomial() False
k.<z> = PowerSeriesRing(QQ, 'z') z.is_monomial() k(1).is_monomial() (z+1).is_monomial() (z^2909).is_monomial() (3*z^2909).is_monomial()
- is_sparse()[source]¶
EXAMPLES:
sage: R.<t> = PowerSeriesRing(ZZ) sage: t.is_sparse() False sage: R.<t> = PowerSeriesRing(ZZ, sparse=True) sage: t.is_sparse() True
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> t.is_sparse() False >>> R = PowerSeriesRing(ZZ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> t.is_sparse() True
R.<t> = PowerSeriesRing(ZZ) t.is_sparse() R.<t> = PowerSeriesRing(ZZ, sparse=True) t.is_sparse()
- is_square()[source]¶
Return
True
if this function has a square root in this ring, e.g., there is an element \(y\) inself.parent()
such that \(y^2\) equalsself
.ALGORITHM: If the base ring is a field, this is true whenever the power series has even valuation and the leading coefficient is a perfect square.
For an integral domain, it attempts the square root in the fraction field and tests whether or not the result lies in the original ring.
EXAMPLES:
sage: K.<t> = PowerSeriesRing(QQ, 't', 5) sage: (1+t).is_square() True sage: (2+t).is_square() False sage: (2+t.change_ring(RR)).is_square() True sage: t.is_square() False sage: K.<t> = PowerSeriesRing(ZZ, 't', 5) sage: (1+t).is_square() False sage: f = (1+t)^100 sage: f.is_square() True
>>> from sage.all import * >>> K = PowerSeriesRing(QQ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> (Integer(1)+t).is_square() True >>> (Integer(2)+t).is_square() False >>> (Integer(2)+t.change_ring(RR)).is_square() True >>> t.is_square() False >>> K = PowerSeriesRing(ZZ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> (Integer(1)+t).is_square() False >>> f = (Integer(1)+t)**Integer(100) >>> f.is_square() True
K.<t> = PowerSeriesRing(QQ, 't', 5) (1+t).is_square() (2+t).is_square() (2+t.change_ring(RR)).is_square() t.is_square() K.<t> = PowerSeriesRing(ZZ, 't', 5) (1+t).is_square() f = (1+t)^100 f.is_square()
- is_unit()[source]¶
Return
True
if this power series is invertible.A power series is invertible precisely when the constant term is invertible.
EXAMPLES:
sage: R.<t> = PowerSeriesRing(ZZ) sage: (-1 + t - t^5).is_unit() True sage: (3 + t - t^5).is_unit() False sage: O(t^0).is_unit() False
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> (-Integer(1) + t - t**Integer(5)).is_unit() True >>> (Integer(3) + t - t**Integer(5)).is_unit() False >>> O(t**Integer(0)).is_unit() False
R.<t> = PowerSeriesRing(ZZ) (-1 + t - t^5).is_unit() (3 + t - t^5).is_unit() O(t^0).is_unit()
AUTHORS:
David Harvey (2006-09-03)
- jacobi_continued_fraction()[source]¶
Return the Jacobi continued fraction of
self
.The J-fraction or Jacobi continued fraction of a power series is a continued fraction expansion with steps of size two. We use the following convention
\[1 / (1 + A_0 t + B_0 t^2 / (1 + A_1 t + B_1 t^2 / (1 + \cdots)))\]OUTPUT:
tuple of pairs \((A_n, B_n)\) for \(n \geq 0\)
The expansion is done as long as possible given the precision. Whenever the expansion is not well-defined, because it would require to divide by zero, an exception is raised.
See section 2.7 of [Kra1999det] for the close relationship of this kind of expansion with Hankel determinants and orthogonal polynomials.
EXAMPLES:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: s = sum(factorial(k) * t**k for k in range(12)).O(12) sage: s.jacobi_continued_fraction() ((-1, -1), (-3, -4), (-5, -9), (-7, -16), (-9, -25))
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> s = sum(factorial(k) * t**k for k in range(Integer(12))).O(Integer(12)) >>> s.jacobi_continued_fraction() ((-1, -1), (-3, -4), (-5, -9), (-7, -16), (-9, -25))
t = PowerSeriesRing(QQ, 't').gen() s = sum(factorial(k) * t**k for k in range(12)).O(12) s.jacobi_continued_fraction()
Another example:
sage: (log(1+t)/t).jacobi_continued_fraction() ((1/2, -1/12), (1/2, -1/15), (1/2, -9/140), (1/2, -4/63), (1/2, -25/396), (1/2, -9/143), (1/2, -49/780), (1/2, -16/255), (1/2, -81/1292))
>>> from sage.all import * >>> (log(Integer(1)+t)/t).jacobi_continued_fraction() ((1/2, -1/12), (1/2, -1/15), (1/2, -9/140), (1/2, -4/63), (1/2, -25/396), (1/2, -9/143), (1/2, -49/780), (1/2, -16/255), (1/2, -81/1292))
(log(1+t)/t).jacobi_continued_fraction()
- laurent_series()[source]¶
Return the Laurent series associated to this power series, i.e., this series considered as a Laurent series.
EXAMPLES:
sage: k.<w> = QQ[[]] sage: f = 1 + 17*w + 15*w^3 + O(w^5) sage: parent(f) Power Series Ring in w over Rational Field sage: g = f.laurent_series(); g 1 + 17*w + 15*w^3 + O(w^5)
>>> from sage.all import * >>> k = QQ[['w']]; (w,) = k._first_ngens(1) >>> f = Integer(1) + Integer(17)*w + Integer(15)*w**Integer(3) + O(w**Integer(5)) >>> parent(f) Power Series Ring in w over Rational Field >>> g = f.laurent_series(); g 1 + 17*w + 15*w^3 + O(w^5)
k.<w> = QQ[[]] f = 1 + 17*w + 15*w^3 + O(w^5) parent(f) g = f.laurent_series(); g
- lift_to_precision(absprec=None)[source]¶
Return a congruent power series with absolute precision at least
absprec
.INPUT:
absprec
– integer orNone
(default:None
); the absolute precision of the result. IfNone
, lifts to an exact element.
EXAMPLES:
sage: A.<t> = PowerSeriesRing(GF(5)) sage: x = t + t^2 + O(t^5) sage: x.lift_to_precision(10) t + t^2 + O(t^10) sage: x.lift_to_precision() t + t^2
>>> from sage.all import * >>> A = PowerSeriesRing(GF(Integer(5)), names=('t',)); (t,) = A._first_ngens(1) >>> x = t + t**Integer(2) + O(t**Integer(5)) >>> x.lift_to_precision(Integer(10)) t + t^2 + O(t^10) >>> x.lift_to_precision() t + t^2
A.<t> = PowerSeriesRing(GF(5)) x = t + t^2 + O(t^5) x.lift_to_precision(10) x.lift_to_precision()
- list()[source]¶
See this method in derived classes:
Implementations MUST override this in the derived class.
EXAMPLES:
sage: from sage.rings.power_series_ring_element import PowerSeries sage: R.<x> = PowerSeriesRing(ZZ) sage: PowerSeries.list(1 + x^2) Traceback (most recent call last): ... NotImplementedError
>>> from sage.all import * >>> from sage.rings.power_series_ring_element import PowerSeries >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> PowerSeries.list(Integer(1) + x**Integer(2)) Traceback (most recent call last): ... NotImplementedError
from sage.rings.power_series_ring_element import PowerSeries R.<x> = PowerSeriesRing(ZZ) PowerSeries.list(1 + x^2)
- log(prec=None)[source]¶
Return log of this power series to the indicated precision.
This works only if the constant term of the power series is 1 or the base ring can take the logarithm of the constant coefficient.
INPUT:
prec
– integer (default:self.parent().default_prec()
)
ALGORITHM: See
solve_linear_de()
.Warning
Screwy things can happen if the coefficient ring is not a field of characteristic zero. See
solve_linear_de()
.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ, default_prec=10) sage: (1 + t + O(t^10)).log() t - 1/2*t^2 + 1/3*t^3 - 1/4*t^4 + 1/5*t^5 - 1/6*t^6 + 1/7*t^7 - 1/8*t^8 + 1/9*t^9 + O(t^10) sage: t.exp().log() t + O(t^10) sage: (1 + t).log().exp() 1 + t + O(t^10) sage: (-1 + t + O(t^10)).log() Traceback (most recent call last): ... ArithmeticError: constant term of power series is not 1 sage: # needs sage.rings.real_mpfr sage: R.<t> = PowerSeriesRing(RR) sage: (2 + t).log().exp() 2.00000000000000 + 1.00000000000000*t + O(t^20)
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, default_prec=Integer(10), names=('t',)); (t,) = R._first_ngens(1) >>> (Integer(1) + t + O(t**Integer(10))).log() t - 1/2*t^2 + 1/3*t^3 - 1/4*t^4 + 1/5*t^5 - 1/6*t^6 + 1/7*t^7 - 1/8*t^8 + 1/9*t^9 + O(t^10) >>> t.exp().log() t + O(t^10) >>> (Integer(1) + t).log().exp() 1 + t + O(t^10) >>> (-Integer(1) + t + O(t**Integer(10))).log() Traceback (most recent call last): ... ArithmeticError: constant term of power series is not 1 >>> # needs sage.rings.real_mpfr >>> R = PowerSeriesRing(RR, names=('t',)); (t,) = R._first_ngens(1) >>> (Integer(2) + t).log().exp() 2.00000000000000 + 1.00000000000000*t + O(t^20)
R.<t> = PowerSeriesRing(QQ, default_prec=10) (1 + t + O(t^10)).log() t.exp().log() (1 + t).log().exp() (-1 + t + O(t^10)).log() # needs sage.rings.real_mpfr R.<t> = PowerSeriesRing(RR) (2 + t).log().exp()
- map_coefficients(f, new_base_ring=None)[source]¶
Return the series obtained by applying
f
to the nonzero coefficients ofself
.If
f
is asage.categories.map.Map
, then the resulting series will be defined over the codomain off
. Otherwise, the resulting polynomial will be over the same ring asself
. Setnew_base_ring
to override this behaviour.INPUT:
f
– a callable that will be applied to the coefficients ofself
new_base_ring
– (optional) if given, the resulting polynomial will be defined over this ring
EXAMPLES:
sage: R.<x> = SR[[]] # needs sage.symbolic sage: f = (1+I)*x^2 + 3*x - I # needs sage.symbolic sage: f.map_coefficients(lambda z: z.conjugate()) # needs sage.symbolic I + 3*x + (-I + 1)*x^2 sage: R.<x> = ZZ[[]] sage: f = x^2 + 2 sage: f.map_coefficients(lambda a: a + 42) 44 + 43*x^2
>>> from sage.all import * >>> R = SR[['x']]; (x,) = R._first_ngens(1)# needs sage.symbolic >>> f = (Integer(1)+I)*x**Integer(2) + Integer(3)*x - I # needs sage.symbolic >>> f.map_coefficients(lambda z: z.conjugate()) # needs sage.symbolic I + 3*x + (-I + 1)*x^2 >>> R = ZZ[['x']]; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(2) >>> f.map_coefficients(lambda a: a + Integer(42)) 44 + 43*x^2
R.<x> = SR[[]] # needs sage.symbolic f = (1+I)*x^2 + 3*x - I # needs sage.symbolic f.map_coefficients(lambda z: z.conjugate()) # needs sage.symbolic R.<x> = ZZ[[]] f = x^2 + 2 f.map_coefficients(lambda a: a + 42)
Examples with different base ring:
sage: R.<x> = ZZ[[]] sage: k = GF(2) sage: residue = lambda x: k(x) sage: f = 4*x^2+x+3 sage: g = f.map_coefficients(residue); g 1 + x sage: g.parent() Power Series Ring in x over Integer Ring sage: g = f.map_coefficients(residue, new_base_ring=k); g 1 + x sage: g.parent() Power Series Ring in x over Finite Field of size 2 sage: residue = k.coerce_map_from(ZZ) sage: g = f.map_coefficients(residue); g 1 + x sage: g.parent() Power Series Ring in x over Finite Field of size 2
>>> from sage.all import * >>> R = ZZ[['x']]; (x,) = R._first_ngens(1) >>> k = GF(Integer(2)) >>> residue = lambda x: k(x) >>> f = Integer(4)*x**Integer(2)+x+Integer(3) >>> g = f.map_coefficients(residue); g 1 + x >>> g.parent() Power Series Ring in x over Integer Ring >>> g = f.map_coefficients(residue, new_base_ring=k); g 1 + x >>> g.parent() Power Series Ring in x over Finite Field of size 2 >>> residue = k.coerce_map_from(ZZ) >>> g = f.map_coefficients(residue); g 1 + x >>> g.parent() Power Series Ring in x over Finite Field of size 2
R.<x> = ZZ[[]] k = GF(2) residue = lambda x: k(x) f = 4*x^2+x+3 g = f.map_coefficients(residue); g g.parent() g = f.map_coefficients(residue, new_base_ring=k); g g.parent() residue = k.coerce_map_from(ZZ) g = f.map_coefficients(residue); g g.parent()
Tests other implementations:
sage: # needs sage.libs.pari sage: R.<q> = PowerSeriesRing(GF(11), implementation='pari') sage: f = q - q^3 + O(q^10) sage: f.map_coefficients(lambda c: c - 2) 10*q + 8*q^3 + O(q^10)
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = PowerSeriesRing(GF(Integer(11)), implementation='pari', names=('q',)); (q,) = R._first_ngens(1) >>> f = q - q**Integer(3) + O(q**Integer(10)) >>> f.map_coefficients(lambda c: c - Integer(2)) 10*q + 8*q^3 + O(q^10)
# needs sage.libs.pari R.<q> = PowerSeriesRing(GF(11), implementation='pari') f = q - q^3 + O(q^10) f.map_coefficients(lambda c: c - 2)
- nth_root(n, prec=None)[source]¶
Return the
n
-th root of this power series.INPUT:
n
– integerprec
– integer (optional); precision of the result. Though, if this series has finite precision, then the result cannot have larger precision.
EXAMPLES:
sage: R.<x> = QQ[[]] sage: (1+x).nth_root(5) 1 + 1/5*x - 2/25*x^2 + ... + 12039376311816/2384185791015625*x^19 + O(x^20) sage: (1 + x + O(x^5)).nth_root(5) 1 + 1/5*x - 2/25*x^2 + 6/125*x^3 - 21/625*x^4 + O(x^5)
>>> from sage.all import * >>> R = QQ[['x']]; (x,) = R._first_ngens(1) >>> (Integer(1)+x).nth_root(Integer(5)) 1 + 1/5*x - 2/25*x^2 + ... + 12039376311816/2384185791015625*x^19 + O(x^20) >>> (Integer(1) + x + O(x**Integer(5))).nth_root(Integer(5)) 1 + 1/5*x - 2/25*x^2 + 6/125*x^3 - 21/625*x^4 + O(x^5)
R.<x> = QQ[[]] (1+x).nth_root(5) (1 + x + O(x^5)).nth_root(5)
Check that the results are consistent with taking log and exponential:
sage: R.<x> = PowerSeriesRing(QQ, default_prec=100) sage: p = (1 + 2*x - x^4)**200 sage: p1 = p.nth_root(1000, prec=100) sage: p2 = (p.log()/1000).exp() sage: p1.prec() == p2.prec() == 100 True sage: p1.polynomial() == p2.polynomial() True
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, default_prec=Integer(100), names=('x',)); (x,) = R._first_ngens(1) >>> p = (Integer(1) + Integer(2)*x - x**Integer(4))**Integer(200) >>> p1 = p.nth_root(Integer(1000), prec=Integer(100)) >>> p2 = (p.log()/Integer(1000)).exp() >>> p1.prec() == p2.prec() == Integer(100) True >>> p1.polynomial() == p2.polynomial() True
R.<x> = PowerSeriesRing(QQ, default_prec=100) p = (1 + 2*x - x^4)**200 p1 = p.nth_root(1000, prec=100) p2 = (p.log()/1000).exp() p1.prec() == p2.prec() == 100 p1.polynomial() == p2.polynomial()
Positive characteristic:
sage: R.<u> = GF(3)[[]] sage: p = 1 + 2 * u^2 sage: p.nth_root(4) 1 + 2*u^2 + u^6 + 2*u^8 + u^12 + 2*u^14 + O(u^20) sage: p.nth_root(4)**4 1 + 2*u^2 + O(u^20)
>>> from sage.all import * >>> R = GF(Integer(3))[['u']]; (u,) = R._first_ngens(1) >>> p = Integer(1) + Integer(2) * u**Integer(2) >>> p.nth_root(Integer(4)) 1 + 2*u^2 + u^6 + 2*u^8 + u^12 + 2*u^14 + O(u^20) >>> p.nth_root(Integer(4))**Integer(4) 1 + 2*u^2 + O(u^20)
R.<u> = GF(3)[[]] p = 1 + 2 * u^2 p.nth_root(4) p.nth_root(4)**4
- ogf_to_egf()[source]¶
Return the exponential generating function power series, assuming
self
is an ordinary generating function power series.This is a formal Borel transform.
This can also be computed as
serconvol(f,exp(t))
in PARI/GP.See also
egf_to_ogf()
for the inverse method.EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ) sage: f = t + t^2 + 2*t^3 sage: f.ogf_to_egf() t + 1/2*t^2 + 1/3*t^3
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1) >>> f = t + t**Integer(2) + Integer(2)*t**Integer(3) >>> f.ogf_to_egf() t + 1/2*t^2 + 1/3*t^3
R.<t> = PowerSeriesRing(QQ) f = t + t^2 + 2*t^3 f.ogf_to_egf()
- padded_list(n=None)[source]¶
Return a list of coefficients of
self
up to (but not including) \(q^n\).Includes 0s in the list on the right so that the list has length \(n\).
INPUT:
n
– (optional) an integer that is at least 0. Ifn
is not given, it will be taken to be the precision ofself
, unless this is+Infinity
, in which case we just returnself.list()
.
EXAMPLES:
sage: R.<q> = PowerSeriesRing(QQ) sage: f = 1 - 17*q + 13*q^2 + 10*q^4 + O(q^7) sage: f.list() [1, -17, 13, 0, 10] sage: f.padded_list(7) [1, -17, 13, 0, 10, 0, 0] sage: f.padded_list(10) [1, -17, 13, 0, 10, 0, 0, 0, 0, 0] sage: f.padded_list(3) [1, -17, 13] sage: f.padded_list() [1, -17, 13, 0, 10, 0, 0] sage: g = 1 - 17*q + 13*q^2 + 10*q^4 sage: g.list() [1, -17, 13, 0, 10] sage: g.padded_list() [1, -17, 13, 0, 10] sage: g.padded_list(10) [1, -17, 13, 0, 10, 0, 0, 0, 0, 0]
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('q',)); (q,) = R._first_ngens(1) >>> f = Integer(1) - Integer(17)*q + Integer(13)*q**Integer(2) + Integer(10)*q**Integer(4) + O(q**Integer(7)) >>> f.list() [1, -17, 13, 0, 10] >>> f.padded_list(Integer(7)) [1, -17, 13, 0, 10, 0, 0] >>> f.padded_list(Integer(10)) [1, -17, 13, 0, 10, 0, 0, 0, 0, 0] >>> f.padded_list(Integer(3)) [1, -17, 13] >>> f.padded_list() [1, -17, 13, 0, 10, 0, 0] >>> g = Integer(1) - Integer(17)*q + Integer(13)*q**Integer(2) + Integer(10)*q**Integer(4) >>> g.list() [1, -17, 13, 0, 10] >>> g.padded_list() [1, -17, 13, 0, 10] >>> g.padded_list(Integer(10)) [1, -17, 13, 0, 10, 0, 0, 0, 0, 0]
R.<q> = PowerSeriesRing(QQ) f = 1 - 17*q + 13*q^2 + 10*q^4 + O(q^7) f.list() f.padded_list(7) f.padded_list(10) f.padded_list(3) f.padded_list() g = 1 - 17*q + 13*q^2 + 10*q^4 g.list() g.padded_list() g.padded_list(10)
- polynomial()[source]¶
See this method in derived classes:
Implementations MUST override this in the derived class.
EXAMPLES:
sage: from sage.rings.power_series_ring_element import PowerSeries sage: R.<x> = PowerSeriesRing(ZZ) sage: PowerSeries.polynomial(1 + x^2) Traceback (most recent call last): ... NotImplementedError
>>> from sage.all import * >>> from sage.rings.power_series_ring_element import PowerSeries >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> PowerSeries.polynomial(Integer(1) + x**Integer(2)) Traceback (most recent call last): ... NotImplementedError
from sage.rings.power_series_ring_element import PowerSeries R.<x> = PowerSeriesRing(ZZ) PowerSeries.polynomial(1 + x^2)
- prec()[source]¶
The precision of \(...+O(x^r)\) is by definition \(r\).
EXAMPLES:
sage: R.<t> = ZZ[[]] sage: (t^2 + O(t^3)).prec() 3 sage: (1 - t^2 + O(t^100)).prec() 100
>>> from sage.all import * >>> R = ZZ[['t']]; (t,) = R._first_ngens(1) >>> (t**Integer(2) + O(t**Integer(3))).prec() 3 >>> (Integer(1) - t**Integer(2) + O(t**Integer(100))).prec() 100
R.<t> = ZZ[[]] (t^2 + O(t^3)).prec() (1 - t^2 + O(t^100)).prec()
- precision_absolute()[source]¶
Return the absolute precision of this series.
By definition, the absolute precision of \(...+O(x^r)\) is \(r\).
EXAMPLES:
sage: R.<t> = ZZ[[]] sage: (t^2 + O(t^3)).precision_absolute() 3 sage: (1 - t^2 + O(t^100)).precision_absolute() 100
>>> from sage.all import * >>> R = ZZ[['t']]; (t,) = R._first_ngens(1) >>> (t**Integer(2) + O(t**Integer(3))).precision_absolute() 3 >>> (Integer(1) - t**Integer(2) + O(t**Integer(100))).precision_absolute() 100
R.<t> = ZZ[[]] (t^2 + O(t^3)).precision_absolute() (1 - t^2 + O(t^100)).precision_absolute()
- precision_relative()[source]¶
Return the relative precision of this series, that is the difference between its absolute precision and its valuation.
By convention, the relative precision of \(0\) (or \(O(x^r)\) for any \(r\)) is \(0\).
EXAMPLES:
sage: R.<t> = ZZ[[]] sage: (t^2 + O(t^3)).precision_relative() 1 sage: (1 - t^2 + O(t^100)).precision_relative() 100 sage: O(t^4).precision_relative() 0
>>> from sage.all import * >>> R = ZZ[['t']]; (t,) = R._first_ngens(1) >>> (t**Integer(2) + O(t**Integer(3))).precision_relative() 1 >>> (Integer(1) - t**Integer(2) + O(t**Integer(100))).precision_relative() 100 >>> O(t**Integer(4)).precision_relative() 0
R.<t> = ZZ[[]] (t^2 + O(t^3)).precision_relative() (1 - t^2 + O(t^100)).precision_relative() O(t^4).precision_relative()
- shift(n)[source]¶
Return this power series multiplied by the power \(t^n\).
If \(n\) is negative, terms below \(t^{-n}\) are discarded.
This power series is left unchanged.
Note
Despite the fact that higher order terms are printed to the right in a power series, right shifting decreases the powers of \(t\), while left shifting increases them. This is to be consistent with polynomials, integers, etc.
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ['y'], 't', 5) sage: f = ~(1+t); f 1 - t + t^2 - t^3 + t^4 + O(t^5) sage: f.shift(3) t^3 - t^4 + t^5 - t^6 + t^7 + O(t^8) sage: f >> 2 1 - t + t^2 + O(t^3) sage: f << 10 t^10 - t^11 + t^12 - t^13 + t^14 + O(t^15) sage: t << 29 t^30
>>> from sage.all import * >>> R = PowerSeriesRing(QQ['y'], 't', Integer(5), names=('t',)); (t,) = R._first_ngens(1) >>> f = ~(Integer(1)+t); f 1 - t + t^2 - t^3 + t^4 + O(t^5) >>> f.shift(Integer(3)) t^3 - t^4 + t^5 - t^6 + t^7 + O(t^8) >>> f >> Integer(2) 1 - t + t^2 + O(t^3) >>> f << Integer(10) t^10 - t^11 + t^12 - t^13 + t^14 + O(t^15) >>> t << Integer(29) t^30
R.<t> = PowerSeriesRing(QQ['y'], 't', 5) f = ~(1+t); f f.shift(3) f >> 2 f << 10 t << 29
AUTHORS:
Robert Bradshaw (2007-04-18)
- sin(prec='infinity')[source]¶
Apply sin to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: sin(f) t + t^2 - 1/6*t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> sin(f) t + t^2 - 1/6*t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) sin(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: sin(f) a + b + a*b + O(a, b)^3 sage: f.sin() a + b + a*b + O(a, b)^3 sage: f.sin(prec=2) a + b + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> sin(f) a + b + a*b + O(a, b)^3 >>> f.sin() a + b + a*b + O(a, b)^3 >>> f.sin(prec=Integer(2)) a + b + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) sin(f) f.sin() f.sin(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2+f sage: sin(g) Traceback (most recent call last): ... ValueError: can only apply sin to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2)+f >>> sin(g) Traceback (most recent call last): ... ValueError: can only apply sin to formal power series with zero constant term
g = 2+f sin(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: sin(a) a - 1/6*a^3 + 1/120*a^5 - 1/5040*a^7 + 1/362880*a^9 - 1/39916800*a^11 + O(a, b)^12 sage: a.sin(prec=5) a - 1/6*a^3 + O(a, b)^5 sage: sin(a + T.O(5)) a - 1/6*a^3 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> sin(a) a - 1/6*a^3 + 1/120*a^5 - 1/5040*a^7 + 1/362880*a^9 - 1/39916800*a^11 + O(a, b)^12 >>> a.sin(prec=Integer(5)) a - 1/6*a^3 + O(a, b)^5 >>> sin(a + T.O(Integer(5))) a - 1/6*a^3 + O(a, b)^5
T.default_prec() sin(a) a.sin(prec=5) sin(a + T.O(5))
- sinh(prec='infinity')[source]¶
Apply sinh to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: sinh(f) t + t^2 + 1/6*t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> sinh(f) t + t^2 + 1/6*t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) sinh(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: sinh(f) a + b + a*b + O(a, b)^3 sage: f.sinh() a + b + a*b + O(a, b)^3 sage: f.sinh(prec=2) a + b + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> sinh(f) a + b + a*b + O(a, b)^3 >>> f.sinh() a + b + a*b + O(a, b)^3 >>> f.sinh(prec=Integer(2)) a + b + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) sinh(f) f.sinh() f.sinh(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2 + f sage: sinh(g) Traceback (most recent call last): ... ValueError: can only apply sinh to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2) + f >>> sinh(g) Traceback (most recent call last): ... ValueError: can only apply sinh to formal power series with zero constant term
g = 2 + f sinh(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: sinh(a) a + 1/6*a^3 + 1/120*a^5 + 1/5040*a^7 + 1/362880*a^9 + 1/39916800*a^11 + O(a, b)^12 sage: a.sinh(prec=5) a + 1/6*a^3 + O(a, b)^5 sage: sinh(a + T.O(5)) a + 1/6*a^3 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> sinh(a) a + 1/6*a^3 + 1/120*a^5 + 1/5040*a^7 + 1/362880*a^9 + 1/39916800*a^11 + O(a, b)^12 >>> a.sinh(prec=Integer(5)) a + 1/6*a^3 + O(a, b)^5 >>> sinh(a + T.O(Integer(5))) a + 1/6*a^3 + O(a, b)^5
T.default_prec() sinh(a) a.sinh(prec=5) sinh(a + T.O(5))
- solve_linear_de(prec='infinity', b=None, f0=None)[source]¶
Obtain a power series solution to an inhomogeneous linear differential equation of the form:
\[f'(t) = a(t) f(t) + b(t).\]INPUT:
self
– the power series \(a(t)\)b
– the power series \(b(t)\) (default: zero)f0
– the constant term of \(f\) (“initial condition”) (default: 1)prec
– desired precision of result (this will be reduced if either a or b have less precision available)
OUTPUT: the power series \(f\), to indicated precision
ALGORITHM: A divide-and-conquer strategy; see the source code. Running time is approximately \(M(n) \log n\), where \(M(n)\) is the time required for a polynomial multiplication of length \(n\) over the coefficient ring. (If you’re working over something like \(\QQ\), running time analysis can be a little complicated because the coefficients tend to explode.)
Note
If the coefficient ring is a field of characteristic zero, then the solution will exist and is unique.
For other coefficient rings, things are more complicated. A solution may not exist, and if it does it may not be unique. Generally, by the time the \(n\)-th term has been computed, the algorithm will have attempted divisions by \(n!\) in the coefficient ring. So if your coefficient ring has enough ‘precision’, and if your coefficient ring can perform divisions even when the answer is not unique, and if you know in advance that a solution exists, then this function will find a solution (otherwise it will probably crash).
AUTHORS:
David Harvey (2006-09-11): factored functionality out from exp() function, cleaned up precision tests a bit
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ, default_prec=10)
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, default_prec=Integer(10), names=('t',)); (t,) = R._first_ngens(1)
R.<t> = PowerSeriesRing(QQ, default_prec=10)
sage: a = 2 - 3*t + 4*t^2 + O(t^10) sage: b = 3 - 4*t^2 + O(t^7) sage: f = a.solve_linear_de(prec=5, b=b, f0=3/5) sage: f 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5) sage: f.derivative() - a*f - b O(t^4)
>>> from sage.all import * >>> a = Integer(2) - Integer(3)*t + Integer(4)*t**Integer(2) + O(t**Integer(10)) >>> b = Integer(3) - Integer(4)*t**Integer(2) + O(t**Integer(7)) >>> f = a.solve_linear_de(prec=Integer(5), b=b, f0=Integer(3)/Integer(5)) >>> f 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5) >>> f.derivative() - a*f - b O(t^4)
a = 2 - 3*t + 4*t^2 + O(t^10) b = 3 - 4*t^2 + O(t^7) f = a.solve_linear_de(prec=5, b=b, f0=3/5) f f.derivative() - a*f - b
>>> from sage.all import * >>> a = Integer(2) - Integer(3)*t + Integer(4)*t**Integer(2) + O(t**Integer(10)) >>> b = Integer(3) - Integer(4)*t**Integer(2) + O(t**Integer(7)) >>> f = a.solve_linear_de(prec=Integer(5), b=b, f0=Integer(3)/Integer(5)) >>> f 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5) >>> f.derivative() - a*f - b O(t^4)
a = 2 - 3*t + 4*t^2 + O(t^10) b = 3 - 4*t^2 + O(t^7) f = a.solve_linear_de(prec=5, b=b, f0=3/5) f f.derivative() - a*f - b
sage: a = 2 - 3*t + 4*t^2 sage: b = b = 3 - 4*t^2 sage: f = a.solve_linear_de(b=b, f0=3/5) Traceback (most recent call last): ... ValueError: cannot solve differential equation to infinite precision
>>> from sage.all import * >>> a = Integer(2) - Integer(3)*t + Integer(4)*t**Integer(2) >>> b = b = Integer(3) - Integer(4)*t**Integer(2) >>> f = a.solve_linear_de(b=b, f0=Integer(3)/Integer(5)) Traceback (most recent call last): ... ValueError: cannot solve differential equation to infinite precision
a = 2 - 3*t + 4*t^2 b = b = 3 - 4*t^2 f = a.solve_linear_de(b=b, f0=3/5)
>>> from sage.all import * >>> a = Integer(2) - Integer(3)*t + Integer(4)*t**Integer(2) >>> b = b = Integer(3) - Integer(4)*t**Integer(2) >>> f = a.solve_linear_de(b=b, f0=Integer(3)/Integer(5)) Traceback (most recent call last): ... ValueError: cannot solve differential equation to infinite precision
a = 2 - 3*t + 4*t^2 b = b = 3 - 4*t^2 f = a.solve_linear_de(b=b, f0=3/5)
sage: a.solve_linear_de(prec=5, b=b, f0=3/5) 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5)
>>> from sage.all import * >>> a.solve_linear_de(prec=Integer(5), b=b, f0=Integer(3)/Integer(5)) 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5)
a.solve_linear_de(prec=5, b=b, f0=3/5)
>>> from sage.all import * >>> a.solve_linear_de(prec=Integer(5), b=b, f0=Integer(3)/Integer(5)) 3/5 + 21/5*t + 33/10*t^2 - 38/15*t^3 + 11/24*t^4 + O(t^5)
a.solve_linear_de(prec=5, b=b, f0=3/5)
- sqrt(prec=None, extend=False, all=False, name=None)[source]¶
Return a square root of
self
.INPUT:
prec
– integer (default:None
); if notNone
and the series has infinite precision, truncates series at precisionprec
extend
– boolean (default:False
); ifTrue
, return a square root in an extension ring, if necessary. Otherwise, raise aValueError
if the square root is not in the base power series ring. For example, ifextend
isTrue
, the square root of a power series with odd degree leading coefficient is defined as an element of a formal extension ring.name
– string; ifextend
isTrue
, you must also specify the print name of the formal square rootall
– boolean (default:False
); ifTrue
, return all square roots ofself
, instead of just one
ALGORITHM: Newton’s method
\[x_{i+1} = \frac{1}{2}( x_i + \mathrm{self}/x_i )\]EXAMPLES:
sage: K.<t> = PowerSeriesRing(QQ, 't', 5) sage: sqrt(t^2) t sage: sqrt(1 + t) 1 + 1/2*t - 1/8*t^2 + 1/16*t^3 - 5/128*t^4 + O(t^5) sage: sqrt(4 + t) 2 + 1/4*t - 1/64*t^2 + 1/512*t^3 - 5/16384*t^4 + O(t^5) sage: u = sqrt(2 + t, prec=2, extend=True, name = 'alpha'); u alpha sage: u^2 2 + t sage: u.parent() Univariate Quotient Polynomial Ring in alpha over Power Series Ring in t over Rational Field with modulus x^2 - 2 - t sage: K.<t> = PowerSeriesRing(QQ, 't', 50) sage: sqrt(1 + 2*t + t^2) 1 + t sage: sqrt(t^2 + 2*t^4 + t^6) t + t^3 sage: sqrt(1 + t + t^2 + 7*t^3)^2 1 + t + t^2 + 7*t^3 + O(t^50) sage: sqrt(K(0)) 0 sage: sqrt(t^2) t
>>> from sage.all import * >>> K = PowerSeriesRing(QQ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> sqrt(t**Integer(2)) t >>> sqrt(Integer(1) + t) 1 + 1/2*t - 1/8*t^2 + 1/16*t^3 - 5/128*t^4 + O(t^5) >>> sqrt(Integer(4) + t) 2 + 1/4*t - 1/64*t^2 + 1/512*t^3 - 5/16384*t^4 + O(t^5) >>> u = sqrt(Integer(2) + t, prec=Integer(2), extend=True, name = 'alpha'); u alpha >>> u**Integer(2) 2 + t >>> u.parent() Univariate Quotient Polynomial Ring in alpha over Power Series Ring in t over Rational Field with modulus x^2 - 2 - t >>> K = PowerSeriesRing(QQ, 't', Integer(50), names=('t',)); (t,) = K._first_ngens(1) >>> sqrt(Integer(1) + Integer(2)*t + t**Integer(2)) 1 + t >>> sqrt(t**Integer(2) + Integer(2)*t**Integer(4) + t**Integer(6)) t + t^3 >>> sqrt(Integer(1) + t + t**Integer(2) + Integer(7)*t**Integer(3))**Integer(2) 1 + t + t^2 + 7*t^3 + O(t^50) >>> sqrt(K(Integer(0))) 0 >>> sqrt(t**Integer(2)) t
K.<t> = PowerSeriesRing(QQ, 't', 5) sqrt(t^2) sqrt(1 + t) sqrt(4 + t) u = sqrt(2 + t, prec=2, extend=True, name = 'alpha'); u u^2 u.parent() K.<t> = PowerSeriesRing(QQ, 't', 50) sqrt(1 + 2*t + t^2) sqrt(t^2 + 2*t^4 + t^6) sqrt(1 + t + t^2 + 7*t^3)^2 sqrt(K(0)) sqrt(t^2)
sage: # needs sage.rings.complex_double sage: K.<t> = PowerSeriesRing(CDF, 5) sage: v = sqrt(-1 + t + t^3, all=True); v [1.0*I - 0.5*I*t - 0.125*I*t^2 - 0.5625*I*t^3 - 0.2890625*I*t^4 + O(t^5), -1.0*I + 0.5*I*t + 0.125*I*t^2 + 0.5625*I*t^3 + 0.2890625*I*t^4 + O(t^5)] sage: [a^2 for a in v] [-1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5), -1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5)]
>>> from sage.all import * >>> # needs sage.rings.complex_double >>> K = PowerSeriesRing(CDF, Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> v = sqrt(-Integer(1) + t + t**Integer(3), all=True); v [1.0*I - 0.5*I*t - 0.125*I*t^2 - 0.5625*I*t^3 - 0.2890625*I*t^4 + O(t^5), -1.0*I + 0.5*I*t + 0.125*I*t^2 + 0.5625*I*t^3 + 0.2890625*I*t^4 + O(t^5)] >>> [a**Integer(2) for a in v] [-1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5), -1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5)]
# needs sage.rings.complex_double K.<t> = PowerSeriesRing(CDF, 5) v = sqrt(-1 + t + t^3, all=True); v [a^2 for a in v]
>>> from sage.all import * >>> # needs sage.rings.complex_double >>> K = PowerSeriesRing(CDF, Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> v = sqrt(-Integer(1) + t + t**Integer(3), all=True); v [1.0*I - 0.5*I*t - 0.125*I*t^2 - 0.5625*I*t^3 - 0.2890625*I*t^4 + O(t^5), -1.0*I + 0.5*I*t + 0.125*I*t^2 + 0.5625*I*t^3 + 0.2890625*I*t^4 + O(t^5)] >>> [a**Integer(2) for a in v] [-1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5), -1.0 + 1.0*t + 0.0*t^2 + 1.0*t^3 + O(t^5)]
# needs sage.rings.complex_double K.<t> = PowerSeriesRing(CDF, 5) v = sqrt(-1 + t + t^3, all=True); v [a^2 for a in v]
A formal square root:
sage: K.<t> = PowerSeriesRing(QQ, 5) sage: f = 2*t + t^3 + O(t^4) sage: s = f.sqrt(extend=True, name='sqrtf'); s sqrtf sage: s^2 2*t + t^3 + O(t^4) sage: parent(s) Univariate Quotient Polynomial Ring in sqrtf over Power Series Ring in t over Rational Field with modulus x^2 - 2*t - t^3 + O(t^4)
>>> from sage.all import * >>> K = PowerSeriesRing(QQ, Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> f = Integer(2)*t + t**Integer(3) + O(t**Integer(4)) >>> s = f.sqrt(extend=True, name='sqrtf'); s sqrtf >>> s**Integer(2) 2*t + t^3 + O(t^4) >>> parent(s) Univariate Quotient Polynomial Ring in sqrtf over Power Series Ring in t over Rational Field with modulus x^2 - 2*t - t^3 + O(t^4)
K.<t> = PowerSeriesRing(QQ, 5) f = 2*t + t^3 + O(t^4) s = f.sqrt(extend=True, name='sqrtf'); s s^2 parent(s)
AUTHORS:
Robert Bradshaw
William Stein
- square_root()[source]¶
Return the square root of
self
in this ring. If this cannot be done, then an error will be raised.This function succeeds if and only if
self
.is_square()
EXAMPLES:
sage: K.<t> = PowerSeriesRing(QQ, 't', 5) sage: (1 + t).square_root() 1 + 1/2*t - 1/8*t^2 + 1/16*t^3 - 5/128*t^4 + O(t^5) sage: (2 + t).square_root() Traceback (most recent call last): ... ValueError: Square root does not live in this ring. sage: (2 + t.change_ring(RR)).square_root() # needs sage.rings.real_mpfr 1.41421356237309 + 0.353553390593274*t - 0.0441941738241592*t^2 + 0.0110485434560398*t^3 - 0.00345266983001244*t^4 + O(t^5) sage: t.square_root() Traceback (most recent call last): ... ValueError: Square root not defined for power series of odd valuation. sage: K.<t> = PowerSeriesRing(ZZ, 't', 5) sage: f = (1+t)^20 sage: f.square_root() 1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5) sage: f = 1 + t sage: f.square_root() Traceback (most recent call last): ... ValueError: Square root does not live in this ring.
>>> from sage.all import * >>> K = PowerSeriesRing(QQ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> (Integer(1) + t).square_root() 1 + 1/2*t - 1/8*t^2 + 1/16*t^3 - 5/128*t^4 + O(t^5) >>> (Integer(2) + t).square_root() Traceback (most recent call last): ... ValueError: Square root does not live in this ring. >>> (Integer(2) + t.change_ring(RR)).square_root() # needs sage.rings.real_mpfr 1.41421356237309 + 0.353553390593274*t - 0.0441941738241592*t^2 + 0.0110485434560398*t^3 - 0.00345266983001244*t^4 + O(t^5) >>> t.square_root() Traceback (most recent call last): ... ValueError: Square root not defined for power series of odd valuation. >>> K = PowerSeriesRing(ZZ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1) >>> f = (Integer(1)+t)**Integer(20) >>> f.square_root() 1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5) >>> f = Integer(1) + t >>> f.square_root() Traceback (most recent call last): ... ValueError: Square root does not live in this ring.
K.<t> = PowerSeriesRing(QQ, 't', 5) (1 + t).square_root() (2 + t).square_root() (2 + t.change_ring(RR)).square_root() # needs sage.rings.real_mpfr t.square_root() K.<t> = PowerSeriesRing(ZZ, 't', 5) f = (1+t)^20 f.square_root() f = 1 + t f.square_root()
AUTHORS:
Robert Bradshaw
- stieltjes_continued_fraction()[source]¶
Return the Stieltjes continued fraction of
self
.The S-fraction or Stieltjes continued fraction of a power series is a continued fraction expansion with steps of size one. We use the following convention
\[1 / (1 - A_1 t / (1 - A_2 t / (1 - A_3 t / (1 - \cdots))))\]OUTPUT: \(A_n\) for \(n \geq 1\)
The expansion is done as long as possible given the precision. Whenever the expansion is not well-defined, because it would require to divide by zero, an exception is raised.
EXAMPLES:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: s = sum(catalan_number(k) * t**k for k in range(12)).O(12) sage: s.stieltjes_continued_fraction() (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> s = sum(catalan_number(k) * t**k for k in range(Integer(12))).O(Integer(12)) >>> s.stieltjes_continued_fraction() (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
t = PowerSeriesRing(QQ, 't').gen() s = sum(catalan_number(k) * t**k for k in range(12)).O(12) s.stieltjes_continued_fraction()
Another example:
sage: (exp(t)).stieltjes_continued_fraction() (1, -1/2, 1/6, -1/6, 1/10, -1/10, 1/14, -1/14, 1/18, -1/18, 1/22, -1/22, 1/26, -1/26, 1/30, -1/30, 1/34, -1/34, 1/38)
>>> from sage.all import * >>> (exp(t)).stieltjes_continued_fraction() (1, -1/2, 1/6, -1/6, 1/10, -1/10, 1/14, -1/14, 1/18, -1/18, 1/22, -1/22, 1/26, -1/26, 1/30, -1/30, 1/34, -1/34, 1/38)
(exp(t)).stieltjes_continued_fraction()
- tan(prec='infinity')[source]¶
Apply tan to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: tan(f) t + t^2 + 1/3*t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> tan(f) t + t^2 + 1/3*t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) tan(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: tan(f) a + b + a*b + O(a, b)^3 sage: f.tan() a + b + a*b + O(a, b)^3 sage: f.tan(prec=2) a + b + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> tan(f) a + b + a*b + O(a, b)^3 >>> f.tan() a + b + a*b + O(a, b)^3 >>> f.tan(prec=Integer(2)) a + b + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) tan(f) f.tan() f.tan(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2 + f sage: tan(g) Traceback (most recent call last): ... ValueError: can only apply tan to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2) + f >>> tan(g) Traceback (most recent call last): ... ValueError: can only apply tan to formal power series with zero constant term
g = 2 + f tan(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: tan(a) a + 1/3*a^3 + 2/15*a^5 + 17/315*a^7 + 62/2835*a^9 + 1382/155925*a^11 + O(a, b)^12 sage: a.tan(prec=5) a + 1/3*a^3 + O(a, b)^5 sage: tan(a + T.O(5)) a + 1/3*a^3 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> tan(a) a + 1/3*a^3 + 2/15*a^5 + 17/315*a^7 + 62/2835*a^9 + 1382/155925*a^11 + O(a, b)^12 >>> a.tan(prec=Integer(5)) a + 1/3*a^3 + O(a, b)^5 >>> tan(a + T.O(Integer(5))) a + 1/3*a^3 + O(a, b)^5
T.default_prec() tan(a) a.tan(prec=5) tan(a + T.O(5))
- tanh(prec='infinity')[source]¶
Apply tanh to the formal power series.
INPUT:
prec
– integer orinfinity
; the degree to truncate the result to
OUTPUT: a new power series
EXAMPLES:
For one variable:
sage: t = PowerSeriesRing(QQ, 't').gen() sage: f = (t + t**2).O(4) sage: tanh(f) t + t^2 - 1/3*t^3 + O(t^4)
>>> from sage.all import * >>> t = PowerSeriesRing(QQ, 't').gen() >>> f = (t + t**Integer(2)).O(Integer(4)) >>> tanh(f) t + t^2 - 1/3*t^3 + O(t^4)
t = PowerSeriesRing(QQ, 't').gen() f = (t + t**2).O(4) tanh(f)
For several variables:
sage: T.<a,b> = PowerSeriesRing(ZZ,2) sage: f = a + b + a*b + T.O(3) sage: tanh(f) a + b + a*b + O(a, b)^3 sage: f.tanh() a + b + a*b + O(a, b)^3 sage: f.tanh(prec=2) a + b + O(a, b)^2
>>> from sage.all import * >>> T = PowerSeriesRing(ZZ,Integer(2), names=('a', 'b',)); (a, b,) = T._first_ngens(2) >>> f = a + b + a*b + T.O(Integer(3)) >>> tanh(f) a + b + a*b + O(a, b)^3 >>> f.tanh() a + b + a*b + O(a, b)^3 >>> f.tanh(prec=Integer(2)) a + b + O(a, b)^2
T.<a,b> = PowerSeriesRing(ZZ,2) f = a + b + a*b + T.O(3) tanh(f) f.tanh() f.tanh(prec=2)
If the power series has a nonzero constant coefficient \(c\), one raises an error:
sage: g = 2 + f sage: tanh(g) Traceback (most recent call last): ... ValueError: can only apply tanh to formal power series with zero constant term
>>> from sage.all import * >>> g = Integer(2) + f >>> tanh(g) Traceback (most recent call last): ... ValueError: can only apply tanh to formal power series with zero constant term
g = 2 + f tanh(g)
If no precision is specified, the default precision is used:
sage: T.default_prec() 12 sage: tanh(a) a - 1/3*a^3 + 2/15*a^5 - 17/315*a^7 + 62/2835*a^9 - 1382/155925*a^11 + O(a, b)^12 sage: a.tanh(prec=5) a - 1/3*a^3 + O(a, b)^5 sage: tanh(a + T.O(5)) a - 1/3*a^3 + O(a, b)^5
>>> from sage.all import * >>> T.default_prec() 12 >>> tanh(a) a - 1/3*a^3 + 2/15*a^5 - 17/315*a^7 + 62/2835*a^9 - 1382/155925*a^11 + O(a, b)^12 >>> a.tanh(prec=Integer(5)) a - 1/3*a^3 + O(a, b)^5 >>> tanh(a + T.O(Integer(5))) a - 1/3*a^3 + O(a, b)^5
T.default_prec() tanh(a) a.tanh(prec=5) tanh(a + T.O(5))
- truncate(prec='infinity')[source]¶
The polynomial obtained from power series by truncation.
EXAMPLES:
sage: R.<I> = GF(2)[[]] sage: f = 1/(1+I+O(I^8)); f 1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8) sage: f.truncate(5) I^4 + I^3 + I^2 + I + 1
>>> from sage.all import * >>> R = GF(Integer(2))[['I']]; (I,) = R._first_ngens(1) >>> f = Integer(1)/(Integer(1)+I+O(I**Integer(8))); f 1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8) >>> f.truncate(Integer(5)) I^4 + I^3 + I^2 + I + 1
R.<I> = GF(2)[[]] f = 1/(1+I+O(I^8)); f f.truncate(5)
- valuation()[source]¶
Return the valuation of this power series.
This is equal to the valuation of the underlying polynomial.
EXAMPLES:
Sparse examples:
sage: R.<t> = PowerSeriesRing(QQ, sparse=True) sage: f = t^100000 + O(t^10000000) sage: f.valuation() 100000 sage: R(0).valuation() +Infinity
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> f = t**Integer(100000) + O(t**Integer(10000000)) >>> f.valuation() 100000 >>> R(Integer(0)).valuation() +Infinity
R.<t> = PowerSeriesRing(QQ, sparse=True) f = t^100000 + O(t^10000000) f.valuation() R(0).valuation()
Dense examples:
sage: R.<t> = PowerSeriesRing(ZZ) sage: f = 17*t^100 + O(t^110) sage: f.valuation() 100 sage: t.valuation() 1
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> f = Integer(17)*t**Integer(100) + O(t**Integer(110)) >>> f.valuation() 100 >>> t.valuation() 1
R.<t> = PowerSeriesRing(ZZ) f = 17*t^100 + O(t^110) f.valuation() t.valuation()
- valuation_zero_part()[source]¶
Factor
self
as \(q^n \cdot (a_0 + a_1 q + \cdots)\) with \(a_0\) nonzero. Then this function returns \(a_0 + a_1 q + \cdots\) .Note
This valuation zero part need not be a unit if, e.g., \(a_0\) is not invertible in the base ring.
EXAMPLES:
sage: R.<t> = PowerSeriesRing(QQ) sage: ((1/3)*t^5*(17-2/3*t^3)).valuation_zero_part() 17/3 - 2/9*t^3
>>> from sage.all import * >>> R = PowerSeriesRing(QQ, names=('t',)); (t,) = R._first_ngens(1) >>> ((Integer(1)/Integer(3))*t**Integer(5)*(Integer(17)-Integer(2)/Integer(3)*t**Integer(3))).valuation_zero_part() 17/3 - 2/9*t^3
R.<t> = PowerSeriesRing(QQ) ((1/3)*t^5*(17-2/3*t^3)).valuation_zero_part()
In this example the valuation 0 part is not a unit:
sage: R.<t> = PowerSeriesRing(ZZ, sparse=True) sage: u = (-2*t^5*(17-t^3)).valuation_zero_part(); u -34 + 2*t^3 sage: u.is_unit() False sage: u.valuation() 0
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, sparse=True, names=('t',)); (t,) = R._first_ngens(1) >>> u = (-Integer(2)*t**Integer(5)*(Integer(17)-t**Integer(3))).valuation_zero_part(); u -34 + 2*t^3 >>> u.is_unit() False >>> u.valuation() 0
R.<t> = PowerSeriesRing(ZZ, sparse=True) u = (-2*t^5*(17-t^3)).valuation_zero_part(); u u.is_unit() u.valuation()
- variable()[source]¶
Return a string with the name of the variable of this power series.
EXAMPLES:
sage: R.<x> = PowerSeriesRing(Rationals()) sage: f = x^2 + 3*x^4 + O(x^7) sage: f.variable() 'x'
>>> from sage.all import * >>> R = PowerSeriesRing(Rationals(), names=('x',)); (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(3)*x**Integer(4) + O(x**Integer(7)) >>> f.variable() 'x'
R.<x> = PowerSeriesRing(Rationals()) f = x^2 + 3*x^4 + O(x^7) f.variable()
AUTHORS:
David Harvey (2006-08-08)
- sage.rings.power_series_ring_element.is_PowerSeries(x)[source]¶
Return
True
ifx
is an instance of a univariate or multivariate power series.EXAMPLES:
sage: R.<x> = PowerSeriesRing(ZZ) sage: from sage.rings.power_series_ring_element import is_PowerSeries sage: is_PowerSeries(1 + x^2) doctest:warning... DeprecationWarning: The function is_PowerSeries is deprecated; use 'isinstance(..., PowerSeries)' instead. See https://github.com/sagemath/sage/issues/38266 for details. True sage: is_PowerSeries(x - x) True sage: is_PowerSeries(0) False sage: var('x') # needs sage.symbolic x sage: is_PowerSeries(1 + x^2) # needs sage.symbolic False
>>> from sage.all import * >>> R = PowerSeriesRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> from sage.rings.power_series_ring_element import is_PowerSeries >>> is_PowerSeries(Integer(1) + x**Integer(2)) doctest:warning... DeprecationWarning: The function is_PowerSeries is deprecated; use 'isinstance(..., PowerSeries)' instead. See https://github.com/sagemath/sage/issues/38266 for details. True >>> is_PowerSeries(x - x) True >>> is_PowerSeries(Integer(0)) False >>> var('x') # needs sage.symbolic x >>> is_PowerSeries(Integer(1) + x**Integer(2)) # needs sage.symbolic False
R.<x> = PowerSeriesRing(ZZ) from sage.rings.power_series_ring_element import is_PowerSeries is_PowerSeries(1 + x^2) is_PowerSeries(x - x) is_PowerSeries(0) var('x') # needs sage.symbolic is_PowerSeries(1 + x^2) # needs sage.symbolic