# 28.1 Univariate Power Series Rings

Module: sage.rings.power_series_ring

Univariate Power Series Rings

Power series rings are constructed in the standard SAGE fashion.

sage: R.<t> = PowerSeriesRing(QQ)
sage: R.random_element(6)
-t - t^2 - t^3 - t^4 + O(t^6)


The default precision is specified at construction, but does not bound the precision of created elements.

sage: R.<t> = PowerSeriesRing(QQ, default_prec=5)
sage: R.random_element(6)
-t - t^2 - t^3 - t^4 + O(t^6)


sage: S = R([1, 3, 5, 7]); S  # XXX + O(t^5)
1 + 3*t + 5*t^2 + 7*t^3


sage: S.truncate(3)
5*t^2 + 3*t + 1


sage: S.<w> = PowerSeriesRing(QQ)
sage: S.base_ring()
Rational Field


An iterated example:

sage: R.<t> = PowerSeriesRing(ZZ)
sage: S.<t2> = PowerSeriesRing(R)
sage: S
Power Series Ring in t2 over Power Series Ring in t over Integer Ring
sage: S.base_ring()
Power Series Ring in t over Integer Ring


We compute with power series over the symbolic ring.

sage: K.<t> = PowerSeriesRing(SR, 5)
sage: a, b, c = var('a,b,c')
sage: f = a + b*t + c*t^2 + O(t^3)
sage: f*f
a^2 + ((b + a)^2 - b^2 - a^2)*t + ((c + b + a)^2 - (c + b)^2 - (b + a)^2 +
2*b^2)*t^2 + O(t^3)
sage: f = sqrt(2) + sqrt(3)*t + O(t^3)
sage: f^2
2 + ((sqrt(3) + sqrt(2))^2 - 5)*t + 3*t^2 + O(t^3)


Elements are first coerced to constants in base_ring, then coerced into the PowerSeriesRing:

sage: R.<t> = PowerSeriesRing(ZZ)
sage: f = Mod(2, 3) * t; (f, f.parent())
(2*t, Power Series Ring in t over Ring of integers modulo 3)


We make a sparse power series.

sage: R.<x> = PowerSeriesRing(QQ, sparse=True); R
Sparse Power Series Ring in x over Rational Field
sage: f = 1 + x^1000000
sage: g = f*f
sage: g.degree()
2000000


We make a sparse Laurent series from a power series generator:

sage: R.<t> = PowerSeriesRing(QQ, sparse=True)
sage: latex(-2/3*(1/t^3) + 1/t + 3/5*t^2 + O(t^5))
\frac{-\frac{2}{3}}{t^{3}} + \frac{1}{t} + \frac{3}{5}t^{2} +
O(\text{t}^{5})
sage: S = parent(1/t); S
Sparse Laurent Series Ring in t over Rational Field


Author Log:

• William Stein: the code
• Jeremy Cho (2006-05-17): some examples (above)

TESTS:

sage: R.<t> = PowerSeriesRing(QQ)
True


sage: R.<x> = PowerSeriesRing(QQ, sparse=True)
True


Module-level Functions

 PowerSeriesRing( base_ring, [name=None], [default_prec=20], [names=None], [sparse=False])
Create a power series ring.

INPUT:
base_ring -- a commutative ring
name -- name of the indeterminate
default_prec -- (efault: 20) the default precision used if an exact
object
must be changed to an approximate object in order to do an
arithmetic operation.
sparse -- (default: False) whether power series are represented as
sparse objects.


There is a unique power series ring over each base ring with given variable name. Two power series over the same base ring with different variable names are not equal or isomorphic.

sage: R = PowerSeriesRing(QQ, 'x'); R
Power Series Ring in x over Rational Field


sage: S = PowerSeriesRing(QQ, 'y'); S
Power Series Ring in y over Rational Field


sage: R = PowerSeriesRing(QQ, 10)
Traceback (most recent call last):
...
ValueError: first letter of variable name must be a letter


sage: S = PowerSeriesRing(QQ, 'x', default_prec = 15); S
Power Series Ring in x over Rational Field
sage: S.default_prec()
15


 is_PowerSeriesRing( R)
Return True if R is a power series ring.

sage: is_PowerSeriesRing(10)
False
sage: is_PowerSeriesRing(QQ[['x']])
True


 unpickle_power_series_ring_v0( base_ring, name, default_prec, sparse)

Class: PowerSeriesRing_domain

class PowerSeriesRing_domain

Class: PowerSeriesRing_generic

class PowerSeriesRing_generic
A power series ring.
 PowerSeriesRing_generic( self, base_ring, [name=None], [default_prec=20], [sparse=False], [use_lazy_mpoly_ring=False])
Initializes a power series ring.

INPUT:
base_ring -- a commutative ring
name -- name of the indeterminate
default_prec -- the default precision
sparse -- whether or not power series are sparse


use_lazy_mpoly_ring - if base ring is a poly ring compute with multivariate polynomials instead of a univariate poly over the base ring. Only use this for dense power series where you won't do too much arithmetic, but the arithmetic you do must be fast. You must explicitly call f.do_truncation() on an element for it to truncate away higher order terms (this is called automatically before printing).

Functions: base_extend, change_ring, characteristic, construction, gen, is_atomic_repr, is_dense, is_exact, is_field, is_finite, is_sparse, laurent_series_ring, ngens, random_element

 base_extend( self, R)
Returns the power series ring over R in the same variable as self, assuming there is a canonical coerce map from the base ring of self to R.

sage: R.<T> = GF(7)[[]]; R
Power Series Ring in T over Finite Field of size 7
sage: R.change_ring(ZZ)
Power Series Ring in T over Integer Ring
sage: R.base_extend(ZZ)
Traceback (most recent call last):
...
TypeError: no base extension defined


 change_ring( self, R)
Returns the power series ring over R in the same variable as self.

sage: R.<T> = QQ[[]]; R
Power Series Ring in T over Rational Field
sage: R.change_ring(GF(7))
Power Series Ring in T over Finite Field of size 7
sage: R.base_extend(GF(7))
Traceback (most recent call last):
...
TypeError: no base extension defined
Power Series Ring in T over Number Field in a with defining polynomial x^2
- 3


 characteristic( self)
Return the characteristic of this power series ring, which is the same as the characteristic of the base ring of the power series ring.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R.characteristic()
0
sage: R.<w> = Integers(2^50)[[]]; R
Power Series Ring in w over Ring of integers modulo 1125899906842624
sage: R.characteristic()
1125899906842624


 construction( self)
Returns the functorial construction of self, namely, completion of the univariate polynomial ring with respect to the indeterminate (to a given precision).

sage: R = PowerSeriesRing(ZZ, 'x')
sage: c, S = R.construction(); S
Univariate Polynomial Ring in x over Integer Ring
sage: R == c(S)
True


 gen( self, [n=0])
Return the generator of this power series ring.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R.gen()
t
sage: R.gen(3)
Traceback (most recent call last):
...
IndexError: generator n>0 not defined


 is_atomic_repr( self)
Return False since power objects do not appear atomically, i.e., they have plus and spaces.

 is_field( self)
Return False since the ring of power series over any ring is never a field.

 is_finite( self)
Return False since the ring of power series over any ring is never finite.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R.is_finite()
False


 laurent_series_ring( self)
If this is the power series ring , this function returns the Laurent series ring .

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R.laurent_series_ring()
Laurent Series Ring in t over Integer Ring


 ngens( self)
Return the number of generators of this power series ring.

This is always 1.

sage: R.<t> = ZZ[[]]
sage: R.ngens()
1


 random_element( self, prec, [bound=None])
Return a random power series.

INPUT:
prec -- an integer
bound -- an integer (default: None, which tries to spread choice across
ring, if implemented)

OUTPUT:
power series -- a power series such that the coefficient
of x^i, for i up to degree, are coercions to the base
ring of random integers between -bound and bound.


IMPLEMENTATION: Call the random_element method on the underlying polynomial ring.

sage: R.<t> = PowerSeriesRing(QQ)
sage: R.random_element(5)
-1 - t - t^2 - t^3 - t^4 + O(t^5)
sage: R.random_element(5,20)
4 - 17*t - 20*t^2 - 16*t^3 - 3*t^4 + O(t^5)


Special Functions: __call__, __cmp__, __contains__, __reduce__, _coerce_impl, _is_valid_homomorphism_, _latex_, _mpoly_ring, _poly_ring, _repr_

 __call__( self, f, [prec=+Infinity], [check=True])
Coerce object to this power series ring.

Returns a new instance unless the parent of f is self, in which case f is returned (since f is immutable).

INPUT:
f -- object, e.g., a power series ring element
prec -- (default: infinity); truncation precision for coercion
check -- bool (default: True), whether to verify that the
coefficients,
etc., coerce in correctly.


sage: R.<t> = PowerSeriesRing(ZZ)
sage: R(t+O(t^5))
t + O(t^5)
sage: R(13)
13
sage: R(2/3)
Traceback (most recent call last):
...
TypeError: no coercion of this rational to integer
sage: R([1,2,3])
1 + 2*t + 3*t^2
sage: S.<w> = PowerSeriesRing(QQ)
sage: R(w + 3*w^2 + O(w^3))
t + 3*t^2 + O(t^3)
sage: x = polygen(QQ,'x')
sage: R(x + x^2 + x^3 + x^5, 3)
t + t^2 + O(t^3)


 __cmp__( self, other)
Compare this power series ring to something else.

Power series rings are considered equal if the base ring, variable names, and default truncation precision are the same.

First the base rings are compared, then the variable names, then the default precision.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: S.<t> = PowerSeriesRing(ZZ)
sage: R is S
True
sage: R == S
True
sage: S.<t> = PowerSeriesRing(ZZ, default_prec=10)
sage: R == S
False
sage: PowerSeriesRing(QQ,'t') == PowerSeriesRing(ZZ,'t')
False
sage: PowerSeriesRing(QQ,'t') == 5
False


 __contains__( self, x)
Returns true if x is an element of this power series ring or canonically coerces to this ring.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: t + t^2 in R
True
sage: 1/t in R
False
sage: 5 in R
True
sage: 1/3 in R
False
sage: S.<s> = PowerSeriesRing(ZZ)
sage: s in R
False


 __reduce__( self)
TESTS:
sage: R.<t> = PowerSeriesRing(ZZ)
Power Series Ring in t over Integer Ring
sage: type(S)
<class 'sage.rings.power_series_ring.PowerSeriesRing_domain'>
sage: R.<t> = PowerSeriesRing(QQ, default_prec=10, sparse=True); R
Sparse Power Series Ring in t over Rational Field
Sparse Power Series Ring in t over Rational Field
sage: type(S)
<class 'sage.rings.power_series_ring.PowerSeriesRing_over_field'>


 _coerce_impl( self, x)
Return canonical coercion of x into self.

Rings that canonically coerce to this power series ring R:

* R itself * Any power series ring in the same variable whose base ring canonically coerces to the base ring of R. * Any ring that canonically coerces to the polynomial ring over the base ring of R. * Any ring that canonically coerces to the base ring of R

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R._coerce_(t + t^2)
t + t^2
sage: R._coerce_(1/t)
Traceback (most recent call last):
...
TypeError: no canonical coercion of element into self
sage: R._coerce_(5)
5
sage: tt = PolynomialRing(ZZ,'t').gen()
sage: R._coerce_(tt^2 + tt - 1)
-1 + t + t^2
sage: R._coerce_(1/2)
Traceback (most recent call last):
...
TypeError: no canonical coercion of element into self
sage: S.<s> = PowerSeriesRing(ZZ)
sage: R._coerce_(s)
Traceback (most recent call last):
...
TypeError: no canonical coercion of element into self


We illustrate canonical coercion between power series rings with compatible base rings:

sage: R.<t> = PowerSeriesRing(GF(7)['w'])
sage: S = PowerSeriesRing(ZZ, 't')
sage: f = S([1,2,3,4]); f
1 + 2*t + 3*t^2 + 4*t^3
sage: g = R._coerce_(f); g
1 + 2*t + 3*t^2 + 4*t^3
sage: parent(g)
Power Series Ring in t over Univariate Polynomial Ring in w over Finite
Field of size 7
sage: S._coerce_(g)
Traceback (most recent call last):
...
TypeError: no natural map between bases of power series rings


 _is_valid_homomorphism_( self, codomain, im_gens)
This gets called implicitly when one constructs a ring homomorphism from a power series ring.

sage: S = RationalField(); R.<t>=PowerSeriesRing(S)
sage: f = R.hom([0])
sage: f(3)
3
sage: g = R.hom([t^2])
sage: g(-1 + 3/5 * t)
-1 + 3/5*t^2


NOTE: There are no ring homomorphisms from the ring of all formal power series to most rings, e.g, the p-adic field, since you can always (mathematically!) construct some power series that doesn't converge. Note that 0 is not a ring homomorphism.

 _latex_( self)
Display latex representation of this power series ring.

sage: R = GF(17)[['y']]
sage: latex(R)
\mathbf{F}_{17}[[y]]


 _poly_ring( self)
Return the underlying polynomial ring used to represent elements of this power series ring.

sage: R.<t> = PowerSeriesRing(ZZ)
sage: R._poly_ring()
Univariate Polynomial Ring in t over Integer Ring


 _repr_( self)
Prints out a power series ring.

sage: R = GF(17)[['y']]
sage: R
Power Series Ring in y over Finite Field of size 17
sage: R.__repr__()
'Power Series Ring in y over Finite Field of size 17'
sage: R.rename('my power series ring')
sage: R
my power series ring


Class: PowerSeriesRing_over_field

class PowerSeriesRing_over_field

Functions: fraction_field

 fraction_field( self)
Return the fraction field of this power series ring, which is defined since this is over a field.

This fraction field is just the Laurent series ring over the base field.

sage: R.<t> = PowerSeriesRing(GF(7))
sage: R.fraction_field()
Laurent Series Ring in t over Finite Field of size 7
sage: Frac(R)
Laurent Series Ring in t over Finite Field of size 7