Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/laurent_series_ring.py
4107 views
1
"""
2
Laurent Series Rings
3
4
EXAMPLES::
5
6
sage: R = LaurentSeriesRing(QQ, "x")
7
sage: R.base_ring()
8
Rational Field
9
sage: S = LaurentSeriesRing(GF(17)['x'], 'y')
10
sage: S
11
Laurent Series Ring in y over Univariate Polynomial Ring in x over
12
Finite Field of size 17
13
sage: S.base_ring()
14
Univariate Polynomial Ring in x over Finite Field of size 17
15
"""
16
17
import weakref
18
19
import laurent_series_ring_element
20
import power_series_ring
21
import polynomial
22
import commutative_ring
23
import integral_domain
24
import field
25
26
from sage.structure.parent_gens import ParentWithGens
27
from sage.libs.all import pari_gen
28
29
from sage.categories.fields import Fields
30
_Fields = Fields()
31
32
laurent_series = {}
33
def LaurentSeriesRing(base_ring, name=None, names=None, sparse=False):
34
"""
35
EXAMPLES::
36
37
sage: R = LaurentSeriesRing(QQ, 'x'); R
38
Laurent Series Ring in x over Rational Field
39
sage: x = R.0
40
sage: g = 1 - x + x^2 - x^4 +O(x^8); g
41
1 - x + x^2 - x^4 + O(x^8)
42
sage: g = 10*x^(-3) + 2006 - 19*x + x^2 - x^4 +O(x^8); g
43
10*x^-3 + 2006 - 19*x + x^2 - x^4 + O(x^8)
44
45
You can also use more mathematical notation when the base is a
46
field::
47
48
sage: Frac(QQ[['x']])
49
Laurent Series Ring in x over Rational Field
50
sage: Frac(GF(5)['y'])
51
Fraction Field of Univariate Polynomial Ring in y over Finite Field of size 5
52
53
Here the fraction field is not just the Laurent series ring, so you
54
can't use the ``Frac`` notation to make the Laurent
55
series ring.
56
57
::
58
59
sage: Frac(ZZ[['t']])
60
Fraction Field of Power Series Ring in t over Integer Ring
61
62
Laurent series rings are determined by their variable and the base
63
ring, and are globally unique.
64
65
::
66
67
sage: K = Qp(5, prec = 5)
68
sage: L = Qp(5, prec = 200)
69
sage: R.<x> = LaurentSeriesRing(K)
70
sage: S.<y> = LaurentSeriesRing(L)
71
sage: R is S
72
False
73
sage: T.<y> = LaurentSeriesRing(Qp(5,prec=200))
74
sage: S is T
75
True
76
sage: W.<y> = LaurentSeriesRing(Qp(5,prec=199))
77
sage: W is T
78
False
79
"""
80
if not names is None: name = names
81
if name is None:
82
raise TypeError, "You must specify the name of the indeterminate of the Laurent series ring."
83
84
global laurent_series
85
key = (base_ring, name, sparse)
86
if laurent_series.has_key(key):
87
x = laurent_series[key]()
88
if x != None: return x
89
90
if isinstance(base_ring, field.Field):
91
R = LaurentSeriesRing_field(base_ring, name, sparse)
92
elif isinstance(base_ring, integral_domain.IntegralDomain):
93
R = LaurentSeriesRing_domain(base_ring, name, sparse)
94
elif isinstance(base_ring, commutative_ring.CommutativeRing):
95
R = LaurentSeriesRing_generic(base_ring, name, sparse)
96
else:
97
raise TypeError, "base_ring must be a commutative ring"
98
laurent_series[key] = weakref.ref(R)
99
return R
100
101
def is_LaurentSeriesRing(x):
102
return isinstance(x, LaurentSeriesRing_generic)
103
104
class LaurentSeriesRing_generic(commutative_ring.CommutativeRing):
105
"""
106
Univariate Laurent Series Ring
107
108
EXAMPLES::
109
110
sage: K, q = LaurentSeriesRing(CC, 'q').objgen(); K
111
Laurent Series Ring in q over Complex Field with 53 bits of precision
112
sage: loads(K.dumps()) == K
113
True
114
sage: P = QQ[['x']]
115
sage: F = Frac(P)
116
sage: TestSuite(F).run()
117
118
"""
119
120
def __init__(self, base_ring, name=None, sparse=False):
121
commutative_ring.CommutativeRing.__init__(self, base_ring, names=name, category=_Fields)
122
self.__sparse = sparse
123
124
def base_extend(self, R):
125
"""
126
Returns the laurent series ring over R in the same variable as
127
self, assuming there is a canonical coerce map from the base ring
128
of self to R.
129
"""
130
if R.has_coerce_map_from(self.base_ring()):
131
return self.change_ring(R)
132
else:
133
raise TypeError, "no valid base extension defined"
134
135
def change_ring(self, R):
136
return LaurentSeriesRing(R, self.variable_name(), sparse=self.__sparse)
137
138
def is_sparse(self):
139
return self.__sparse
140
141
def is_field(self, proof = True):
142
return True
143
144
def is_dense(self):
145
return not self.__sparse
146
147
def __reduce__(self):
148
return self.__class__, (self.base_ring(), self.variable_name())
149
150
def __repr__(self):
151
s = "Laurent Series Ring in %s over %s"%(self.variable_name(), self.base_ring())
152
if self.is_sparse():
153
s = 'Sparse ' + s
154
return s
155
156
def __call__(self, x, n=0):
157
r"""
158
Coerces the element x into this Laurent series ring.
159
160
INPUT:
161
162
163
- ``x`` - the element to coerce
164
165
- ``n`` - the result of the coercion will be
166
multiplied by `t^n` (default: 0)
167
168
169
EXAMPLES::
170
171
sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
172
sage: S.<t> = LaurentSeriesRing(RationalField())
173
sage: print R(t + t^2 + O(t^3))
174
(1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)
175
176
Note that coercing an element into its own parent just produces
177
that element again (since Laurent series are immutable)::
178
179
sage: u is R(u)
180
True
181
182
Rational functions are accepted::
183
184
sage: I = sqrt(-1)
185
sage: K.<I> = QQ[I]
186
sage: P.<t> = PolynomialRing(K)
187
sage: L.<u> = LaurentSeriesRing(QQ[I])
188
sage: L((t*I)/(t^3+I*2*t))
189
1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
190
1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
191
1/1024*I*u^18 + O(u^20)
192
193
::
194
195
sage: L(t*I) / L(t^3+I*2*t)
196
1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
197
1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
198
1/1024*I*u^18 + O(u^20)
199
200
Various conversions from PARI (see also #2508)::
201
202
sage: L.<q> = LaurentSeriesRing(QQ)
203
sage: L.set_default_prec(10)
204
sage: L(pari('1/x'))
205
q^-1
206
sage: L(pari('poltchebi(5)'))
207
5*q - 20*q^3 + 16*q^5
208
sage: L(pari('poltchebi(5) - 1/x^4'))
209
-q^-4 + 5*q - 20*q^3 + 16*q^5
210
sage: L(pari('1/poltchebi(5)'))
211
1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
212
sage: L(pari('poltchebi(5) + O(x^40)'))
213
5*q - 20*q^3 + 16*q^5 + O(q^40)
214
sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
215
-q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
216
sage: L(pari('1/poltchebi(5) + O(x^10)'))
217
1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
218
sage: L(pari('1/poltchebi(5) + O(x^10)'), -10) # Multiply by q^-10
219
1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
220
sage: L(pari('O(x^-10)'))
221
O(q^-10)
222
"""
223
from sage.rings.fraction_field_element import is_FractionFieldElement
224
from sage.rings.polynomial.polynomial_element import is_Polynomial
225
from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
226
227
if isinstance(x, laurent_series_ring_element.LaurentSeries) and n==0 and self is x.parent():
228
return x # ok, since Laurent series are immutable (no need to make a copy)
229
elif isinstance(x, pari_gen):
230
t = x.type()
231
if t == "t_RFRAC": # Rational function
232
x = self(self.polynomial_ring()(x.numerator())) / \
233
self(self.polynomial_ring()(x.denominator()))
234
return (x << n)
235
elif t == "t_SER": # Laurent series
236
n += x._valp()
237
bigoh = n + x.length()
238
x = self(self.polynomial_ring()(x.Vec()))
239
return (x << n).add_bigoh(bigoh)
240
else: # General case, pretend to be a polynomial
241
return self(self.polynomial_ring()(x)) << n
242
elif is_FractionFieldElement(x) and \
243
(x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
244
(is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
245
x = self(x.numerator())/self(x.denominator())
246
return (x << n)
247
else:
248
return laurent_series_ring_element.LaurentSeries(self, x, n)
249
250
def _coerce_impl(self, x):
251
"""
252
Return canonical coercion of x into self.
253
254
Rings that canonically coerce to this power series ring R:
255
256
- R itself
257
258
- Any laurent series ring in the same variable whose base ring
259
canonically coerces to the base ring of R.
260
261
- Any ring that canonically coerces to the power series ring
262
over the base ring of R.
263
264
- Any ring that canonically coerces to the base ring of R
265
"""
266
try:
267
P = x.parent()
268
if is_LaurentSeriesRing(P):
269
if P.variable_name() == self.variable_name():
270
if self.has_coerce_map_from(P.base_ring()):
271
return self(x)
272
else:
273
raise TypeError, "no natural map between bases of power series rings"
274
except AttributeError:
275
pass
276
277
return self._coerce_try(x, [self.power_series_ring(), self.base_ring()])
278
279
def __cmp__(self, other):
280
if not isinstance(other, LaurentSeriesRing_generic):
281
return cmp(type(self),type(other))
282
c = cmp(self.base_ring(), other.base_ring())
283
if c: return c
284
c = cmp(self.variable_name(), other.variable_name())
285
if c: return c
286
return 0
287
288
289
def _is_valid_homomorphism_(self, codomain, im_gens):
290
## NOTE: There are no ring homomorphisms from the ring of
291
## all formal power series to most rings, e.g, the p-adic
292
## field, since you can always (mathematically!) construct
293
## some power series that doesn't converge.
294
## Note that 0 is not a *ring* homomorphism.
295
from power_series_ring import is_PowerSeriesRing
296
if is_PowerSeriesRing(codomain) or is_LaurentSeriesRing(codomain):
297
return im_gens[0].valuation() > 0
298
return False
299
300
def characteristic(self):
301
return self.base_ring().characteristic()
302
303
def set_default_prec(self, n):
304
self.power_series_ring().set_default_prec(n)
305
306
def default_prec(self):
307
return self.power_series_ring().default_prec()
308
309
def is_exact(self):
310
return False
311
312
def gen(self, n=0):
313
if n != 0:
314
raise IndexError, "Generator n not defined."
315
try:
316
return self.__generator
317
except AttributeError:
318
self.__generator = laurent_series_ring_element.LaurentSeries(self, [0,1])
319
return self.__generator
320
321
def ngens(self):
322
return 1
323
324
def polynomial_ring(self):
325
r"""
326
If this is the Laurent series ring `R((t))`, return the
327
polynomial ring `R[t]`.
328
329
EXAMPLES::
330
331
sage: R = LaurentSeriesRing(QQ, "x")
332
sage: R.polynomial_ring()
333
Univariate Polynomial Ring in x over Rational Field
334
"""
335
try:
336
return self.__polynomial_ring
337
except AttributeError:
338
self.__polynomial_ring = polynomial.polynomial_ring_constructor.PolynomialRing( \
339
self.base_ring(), self.variable_name(), sparse=self.is_sparse())
340
return self.__polynomial_ring
341
342
def power_series_ring(self):
343
r"""
344
If this is the Laurent series ring `R((t))`, return the
345
power series ring `R[[t]]`.
346
347
EXAMPLES::
348
349
sage: R = LaurentSeriesRing(QQ, "x")
350
sage: R.power_series_ring()
351
Power Series Ring in x over Rational Field
352
"""
353
try:
354
return self.__power_series_ring
355
except AttributeError:
356
self.__power_series_ring = power_series_ring.PowerSeriesRing(
357
self.base_ring(), self.variable_name(), sparse=self.is_sparse())
358
return self.__power_series_ring
359
360
class LaurentSeriesRing_domain(LaurentSeriesRing_generic, integral_domain.IntegralDomain):
361
def __init__(self, base_ring, name=None, sparse=False):
362
LaurentSeriesRing_generic.__init__(self, base_ring, name, sparse)
363
364
class LaurentSeriesRing_field(LaurentSeriesRing_generic, field.Field):
365
def __init__(self, base_ring, name=None, sparse=False):
366
LaurentSeriesRing_generic.__init__(self, base_ring, name, sparse)
367
368
369