Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/complex_field.py
4054 views
1
r"""
2
Field of Arbitrary Precision Complex Numbers
3
4
AUTHORS:
5
6
- William Stein (2006-01-26): complete rewrite
7
8
- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
9
10
"""
11
12
#################################################################################
13
# Copyright (C) 2006 William Stein <[email protected]>
14
#
15
# Distributed under the terms of the GNU General Public License (GPL)
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
20
import complex_number
21
import complex_double
22
import field
23
import integer
24
import real_mpfr
25
import weakref
26
from sage.misc.sage_eval import sage_eval
27
28
from sage.structure.parent import Parent
29
from sage.structure.parent_gens import ParentWithGens
30
31
NumberFieldElement_quadratic = None
32
AlgebraicNumber_base = None
33
AlgebraicNumber = None
34
AlgebraicReal = None
35
AA = None
36
QQbar = None
37
SR = None
38
CDF = CLF = RLF = None
39
def late_import():
40
global NumberFieldElement_quadratic
41
global AlgebraicNumber_base
42
global AlgebraicNumber
43
global AlgebraicReal
44
global AA, QQbar, SR
45
global CLF, RLF, CDF
46
if NumberFieldElement_quadratic is None:
47
import sage.rings.number_field.number_field_element_quadratic as nfeq
48
NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic
49
import sage.rings.qqbar
50
AlgebraicNumber_base = sage.rings.qqbar.AlgebraicNumber_base
51
AlgebraicNumber = sage.rings.qqbar.AlgebraicNumber
52
AlgebraicReal = sage.rings.qqbar.AlgebraicReal
53
AA = sage.rings.qqbar.AA
54
QQbar = sage.rings.qqbar.QQbar
55
import sage.symbolic.ring
56
SR = sage.symbolic.ring.SR
57
from real_lazy import CLF, RLF
58
from complex_double import CDF
59
60
def is_ComplexField(x):
61
return isinstance(x, ComplexField_class)
62
63
cache = {}
64
def ComplexField(prec=53, names=None):
65
"""
66
Return the complex field with real and imaginary parts having prec
67
*bits* of precision.
68
69
EXAMPLES::
70
71
sage: ComplexField()
72
Complex Field with 53 bits of precision
73
sage: ComplexField(100)
74
Complex Field with 100 bits of precision
75
sage: ComplexField(100).base_ring()
76
Real Field with 100 bits of precision
77
sage: i = ComplexField(200).gen()
78
sage: i^2
79
-1.0000000000000000000000000000000000000000000000000000000000
80
"""
81
global cache
82
if cache.has_key(prec):
83
X = cache[prec]
84
C = X()
85
if not C is None:
86
return C
87
C = ComplexField_class(prec)
88
cache[prec] = weakref.ref(C)
89
return C
90
91
92
class ComplexField_class(field.Field):
93
"""
94
An approximation to the field of complex numbers using floating
95
point numbers with any specified precision. Answers derived from
96
calculations in this approximation may differ from what they would
97
be if those calculations were performed in the true field of
98
complex numbers. This is due to the rounding errors inherent to
99
finite precision calculations.
100
101
EXAMPLES::
102
103
sage: C = ComplexField(); C
104
Complex Field with 53 bits of precision
105
sage: Q = RationalField()
106
sage: C(1/3)
107
0.333333333333333
108
sage: C(1/3, 2)
109
0.333333333333333 + 2.00000000000000*I
110
sage: C(RR.pi())
111
3.14159265358979
112
sage: C(RR.log2(), RR.pi())
113
0.693147180559945 + 3.14159265358979*I
114
115
We can also coerce rational numbers and integers into C, but
116
coercing a polynomial will raise an exception.
117
118
::
119
120
sage: Q = RationalField()
121
sage: C(1/3)
122
0.333333333333333
123
sage: S = PolynomialRing(Q, 'x')
124
sage: C(S.gen())
125
Traceback (most recent call last):
126
...
127
TypeError: unable to coerce to a ComplexNumber: <type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>
128
129
This illustrates precision.
130
131
::
132
133
sage: CC = ComplexField(10); CC(1/3, 2/3)
134
0.33 + 0.67*I
135
sage: CC
136
Complex Field with 10 bits of precision
137
sage: CC = ComplexField(100); CC
138
Complex Field with 100 bits of precision
139
sage: z = CC(1/3, 2/3); z
140
0.33333333333333333333333333333 + 0.66666666666666666666666666667*I
141
142
We can load and save complex numbers and the complex field.
143
144
::
145
146
sage: loads(z.dumps()) == z
147
True
148
sage: loads(CC.dumps()) == CC
149
True
150
sage: k = ComplexField(100)
151
sage: loads(dumps(k)) == k
152
True
153
154
This illustrates basic properties of a complex field.
155
156
::
157
158
sage: CC = ComplexField(200)
159
sage: CC.is_field()
160
True
161
sage: CC.characteristic()
162
0
163
sage: CC.precision()
164
200
165
sage: CC.variable_name()
166
'I'
167
sage: CC == ComplexField(200)
168
True
169
sage: CC == ComplexField(53)
170
False
171
sage: CC == 1.1
172
False
173
"""
174
def __init__(self, prec=53):
175
"""
176
TESTS::
177
178
sage: C = ComplexField(200)
179
sage: C.category()
180
Category of fields
181
sage: TestSuite(C).run()
182
"""
183
self._prec = int(prec)
184
from sage.categories.fields import Fields
185
ParentWithGens.__init__(self, self._real_field(), ('I',), False, category = Fields())
186
# self._populate_coercion_lists_()
187
self._populate_coercion_lists_(coerce_list=[complex_number.RRtoCC(self._real_field(), self)])
188
189
def __reduce__(self):
190
return ComplexField, (self._prec, )
191
192
def is_exact(self):
193
return False
194
195
def prec(self):
196
return self._prec
197
198
def _magma_init_(self, magma):
199
r"""
200
Return a string representation of self in the Magma language.
201
202
EXAMPLES::
203
204
sage: magma(ComplexField(200)) # optional - magma
205
Complex field of precision 60
206
sage: 10^60 < 2^200 < 10^61
207
True
208
sage: s = magma(ComplexField(200)).sage(); s # optional - magma
209
Complex Field with 200 bits of precision
210
sage: 2^199 < 10^60 < 2^200
211
True
212
sage: s is ComplexField(200) # optional - magma
213
True
214
"""
215
return "ComplexField(%s : Bits := true)" % self.prec()
216
217
precision = prec
218
219
def to_prec(self, prec):
220
"""
221
Returns the complex field to the specified precision.
222
223
EXAMPLES::
224
225
sage: CC.to_prec(10)
226
Complex Field with 10 bits of precision
227
sage: CC.to_prec(100)
228
Complex Field with 100 bits of precision
229
"""
230
return ComplexField(prec)
231
232
233
# very useful to cache this.
234
def _real_field(self):
235
try:
236
return self.__real_field
237
except AttributeError:
238
self.__real_field = real_mpfr.RealField(self._prec)
239
return self.__real_field
240
241
def __cmp__(self, other):
242
if not isinstance(other, ComplexField_class):
243
return cmp(type(self), type(other))
244
return cmp(self._prec, other._prec)
245
246
def __call__(self, x=None, im=None):
247
"""
248
EXAMPLES::
249
250
sage: CC(2)
251
2.00000000000000
252
sage: CC(CC.0)
253
1.00000000000000*I
254
sage: CC('1+I')
255
1.00000000000000 + 1.00000000000000*I
256
sage: CC(2,3)
257
2.00000000000000 + 3.00000000000000*I
258
sage: CC(QQ[I].gen())
259
1.00000000000000*I
260
sage: CC.gen() + QQ[I].gen()
261
Traceback (most recent call last):
262
...
263
TypeError: unsupported operand parent(s) for '+': 'Complex Field with 53 bits of precision' and 'Number Field in I with defining polynomial x^2 + 1'
264
265
In the absence of arguments we return zero::
266
267
sage: a = CC(); a
268
0.000000000000000
269
sage: a.parent()
270
Complex Field with 53 bits of precision
271
"""
272
if x is None:
273
return self.zero_element()
274
# we leave this here to handle the imaginary parameter
275
if im is not None:
276
x = x, im
277
return Parent.__call__(self, x)
278
279
def _element_constructor_(self, x):
280
"""
281
EXAMPLES::
282
283
sage: CC((1,2))
284
1.00000000000000 + 2.00000000000000*I
285
"""
286
if not isinstance(x, (real_mpfr.RealNumber, tuple)):
287
if isinstance(x, complex_double.ComplexDoubleElement):
288
return complex_number.ComplexNumber(self, x.real(), x.imag())
289
elif isinstance(x, str):
290
# TODO: this is probably not the best and most
291
# efficient way to do this. -- Martin Albrecht
292
return complex_number.ComplexNumber(self,
293
sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))
294
295
late_import()
296
if isinstance(x, NumberFieldElement_quadratic) and list(x.parent().polynomial()) == [1, 0, 1]:
297
(re, im) = list(x)
298
return complex_number.ComplexNumber(self, re, im)
299
300
try:
301
return self(x.sage())
302
except:
303
pass
304
try:
305
return x._complex_mpfr_field_( self )
306
except AttributeError:
307
pass
308
return complex_number.ComplexNumber(self, x)
309
310
def _coerce_map_from_(self, S):
311
"""
312
The rings that canonically coerce to the MPFR complex field are:
313
314
- This MPFR complex field, or any other of higher precision
315
316
- Anything that canonically coerces to the mpfr real field
317
with this prec
318
319
EXAMPLES::
320
321
sage: ComplexField(200)(1) + RealField(90)(1)
322
2.0000000000000000000000000
323
sage: parent(ComplexField(200)(1) + RealField(90)(1))
324
Complex Field with 90 bits of precision
325
sage: CC.0 + RLF(1/3)
326
0.333333333333333 + 1.00000000000000*I
327
sage: ComplexField(20).has_coerce_map_from(CDF)
328
True
329
sage: ComplexField(200).has_coerce_map_from(CDF)
330
False
331
"""
332
RR = self._real_field()
333
if RR.has_coerce_map_from(S):
334
return complex_number.RRtoCC(RR, self) * RR.coerce_map_from(S)
335
if is_ComplexField(S) and S._prec >= self._prec:
336
return self._generic_convert_map(S)
337
late_import()
338
if S in [AA, QQbar, CLF, RLF] or (S == CDF and self._prec <= 53):
339
return self._generic_convert_map(S)
340
return self._coerce_map_via([CLF], S)
341
342
def _repr_(self):
343
return "Complex Field with %s bits of precision"%self._prec
344
345
def _latex_(self):
346
return "\\Bold{C}"
347
348
def _sage_input_(self, sib, coerce):
349
r"""
350
Produce an expression which will reproduce this value when evaluated.
351
352
EXAMPLES:
353
sage: sage_input(CC, verify=True)
354
# Verified
355
CC
356
sage: sage_input(ComplexField(25), verify=True)
357
# Verified
358
ComplexField(25)
359
sage: k = (CC, ComplexField(75))
360
sage: sage_input(k, verify=True)
361
# Verified
362
(CC, ComplexField(75))
363
sage: sage_input((k, k), verify=True)
364
# Verified
365
CC75 = ComplexField(75)
366
((CC, CC75), (CC, CC75))
367
sage: from sage.misc.sage_input import SageInputBuilder
368
sage: ComplexField(99)._sage_input_(SageInputBuilder(), False)
369
{call: {atomic:ComplexField}({atomic:99})}
370
"""
371
if self.prec() == 53:
372
return sib.name('CC')
373
374
v = sib.name('ComplexField')(sib.int(self.prec()))
375
376
name = 'CC%d' % (self.prec())
377
sib.cache(self, v, name)
378
return v
379
380
def characteristic(self):
381
return integer.Integer(0)
382
383
def gen(self, n=0):
384
if n != 0:
385
raise IndexError, "n must be 0"
386
return complex_number.ComplexNumber(self, 0, 1)
387
388
def is_field(self, proof = True):
389
"""
390
Return True, since the complex numbers are a field.
391
392
EXAMPLES::
393
394
sage: CC.is_field()
395
True
396
"""
397
return True
398
399
def is_finite(self):
400
"""
401
Return False, since the complex numbers are infinite.
402
403
EXAMPLES::
404
405
sage: CC.is_finite()
406
False
407
"""
408
return False
409
410
def construction(self):
411
"""
412
Returns the functorial construction of self, namely, algebraic
413
closure of the real field with the same precision.
414
415
EXAMPLES::
416
417
sage: c, S = CC.construction(); S
418
Real Field with 53 bits of precision
419
sage: CC == c(S)
420
True
421
"""
422
from sage.categories.pushout import AlgebraicClosureFunctor
423
return (AlgebraicClosureFunctor(), self._real_field())
424
425
426
def random_element(self, component_max=1, *args, **kwds):
427
r"""
428
Returns a uniformly distributed random number inside a square
429
centered on the origin (by default, the square [-1,1]x[-1,1]).
430
Passes additional arguments and keywords to underlying real field.
431
432
EXAMPLES::
433
434
sage: [CC.random_element() for _ in range(5)]
435
[0.153636193785613 - 0.502987375247518*I,
436
0.609589964322241 - 0.948854594338216*I,
437
0.968393085385764 - 0.148483595843485*I,
438
-0.908976099636549 + 0.126219184235123*I,
439
0.461226845462901 - 0.0420335212948924*I]
440
sage: CC6 = ComplexField(6)
441
sage: [CC6.random_element(2^-20) for _ in range(5)]
442
[-5.4e-7 - 3.3e-7*I, 2.1e-7 + 8.0e-7*I, -4.8e-7 - 8.6e-7*I, -6.0e-8 + 2.7e-7*I, 6.0e-8 + 1.8e-7*I]
443
sage: [CC6.random_element(pi^20) for _ in range(5)]
444
[6.7e8 - 5.4e8*I, -9.4e8 + 5.0e9*I, 1.2e9 - 2.7e8*I, -2.3e9 - 4.0e9*I, 7.7e9 + 1.2e9*I]
445
446
Passes extra positional or keyword arguments through::
447
448
sage: [CC.random_element(distribution='1/n') for _ in range(5)]
449
[-0.900931453455899 - 0.932172283929307*I,
450
0.327862582226912 + 0.828104487111727*I,
451
0.246299162813240 + 0.588214960163442*I,
452
0.892970599589521 - 0.266744694790704*I,
453
0.878458776600692 - 0.905641181799996*I]
454
"""
455
size = self._real_field()(component_max)
456
re = self._real_field().random_element(-size, size, *args, **kwds)
457
im = self._real_field().random_element(-size, size, *args, **kwds)
458
return self(re, im)
459
460
def pi(self):
461
return self(self._real_field().pi())
462
463
def ngens(self):
464
return 1
465
466
def zeta(self, n=2):
467
"""
468
Return a primitive `n`-th root of unity.
469
470
INPUT:
471
472
473
- ``n`` - an integer (default: 2)
474
475
476
OUTPUT: a complex n-th root of unity.
477
"""
478
from integer import Integer
479
n = Integer(n)
480
if n == 1:
481
x = self(1)
482
elif n == 2:
483
x = self(-1)
484
elif n >= 3:
485
# Use De Moivre
486
# e^(2*pi*i/n) = cos(2pi/n) + i *sin(2pi/n)
487
RR = self._real_field()
488
pi = RR.pi()
489
z = 2*pi/n
490
x = complex_number.ComplexNumber(self, z.cos(), z.sin())
491
x._set_multiplicative_order( n )
492
return x
493
494
def scientific_notation(self, status=None):
495
return self._real_field().scientific_notation(status)
496
497
def algebraic_closure(self):
498
"""
499
Return the algebraic closure of self (which is itself).
500
501
EXAMPLES::
502
503
sage: CC
504
Complex Field with 53 bits of precision
505
sage: CC.algebraic_closure()
506
Complex Field with 53 bits of precision
507
sage: CC = ComplexField(1000)
508
sage: CC.algebraic_closure() is CC
509
True
510
"""
511
return self
512
513
514