Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/complex_interval_field.py
8817 views
1
r"""
2
Field of Arbitrary Precision Complex Intervals
3
4
AUTHORS:
5
6
- William Stein wrote complex_field.py.
7
8
- William Stein (2006-01-26): complete rewrite
9
10
Then ``complex_field.py`` was copied to ``complex_interval_field.py`` and
11
heavily modified:
12
13
- Carl Witty (2007-10-24): rewrite for intervals
14
15
- Niles Johnson (2010-08): :Trac:`3893`: ``random_element()``
16
should pass on ``*args`` and ``**kwds``.
17
18
- Travis Scrimshaw (2012-10-18): Added documentation to get full coverage.
19
20
.. NOTE::
21
22
The :class:`ComplexIntervalField` differs from :class:`ComplexField` in
23
that :class:`ComplexIntervalField` only gives the digits with exact
24
precision, then a ``?`` signifying that that digit can have an error of
25
``+/-1``.
26
"""
27
28
#################################################################################
29
# Copyright (C) 2006 William Stein <[email protected]>
30
#
31
# Distributed under the terms of the GNU General Public License (GPL)
32
#
33
# http://www.gnu.org/licenses/
34
#*****************************************************************************
35
36
import complex_double
37
import field
38
import integer
39
import weakref
40
import real_mpfi
41
import complex_interval
42
import complex_field
43
from sage.misc.sage_eval import sage_eval
44
45
from sage.structure.parent_gens import ParentWithGens
46
47
NumberFieldElement_quadratic = None
48
def late_import():
49
"""
50
Import the objects/modules after build (when needed).
51
52
TESTS::
53
54
sage: sage.rings.complex_interval_field.late_import()
55
"""
56
global NumberFieldElement_quadratic
57
if NumberFieldElement_quadratic is None:
58
import sage.rings.number_field.number_field_element_quadratic as nfeq
59
NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic
60
61
def is_ComplexIntervalField(x):
62
"""
63
Check if ``x`` is a :class:`ComplexIntervalField`.
64
65
EXAMPLES::
66
67
sage: from sage.rings.complex_interval_field import is_ComplexIntervalField as is_CIF
68
sage: is_CIF(CIF)
69
True
70
sage: is_CIF(CC)
71
False
72
"""
73
return isinstance(x, ComplexIntervalField_class)
74
75
cache = {}
76
def ComplexIntervalField(prec=53, names=None):
77
"""
78
Return the complex interval field with real and imaginary parts having
79
``prec`` *bits* of precision.
80
81
EXAMPLES::
82
83
sage: ComplexIntervalField()
84
Complex Interval Field with 53 bits of precision
85
sage: ComplexIntervalField(100)
86
Complex Interval Field with 100 bits of precision
87
sage: ComplexIntervalField(100).base_ring()
88
Real Interval Field with 100 bits of precision
89
sage: i = ComplexIntervalField(200).gen()
90
sage: i^2
91
-1
92
sage: i^i
93
0.207879576350761908546955619834978770033877841631769608075136?
94
"""
95
global cache
96
if cache.has_key(prec):
97
X = cache[prec]
98
C = X()
99
if not C is None:
100
return C
101
C = ComplexIntervalField_class(prec)
102
cache[prec] = weakref.ref(C)
103
return C
104
105
106
class ComplexIntervalField_class(field.Field):
107
"""
108
The field of complex (interval) numbers.
109
110
EXAMPLES::
111
112
sage: C = ComplexIntervalField(); C
113
Complex Interval Field with 53 bits of precision
114
sage: Q = RationalField()
115
sage: C(1/3)
116
0.3333333333333334?
117
sage: C(1/3, 2)
118
0.3333333333333334? + 2*I
119
120
We can also coerce rational numbers and integers into ``C``, but
121
coercing a polynomial will raise an exception::
122
123
sage: Q = RationalField()
124
sage: C(1/3)
125
0.3333333333333334?
126
sage: S = PolynomialRing(Q, 'x')
127
sage: C(S.gen())
128
Traceback (most recent call last):
129
...
130
TypeError: unable to coerce to a ComplexIntervalFieldElement
131
132
This illustrates precision::
133
134
sage: CIF = ComplexIntervalField(10); CIF(1/3, 2/3)
135
0.334? + 0.667?*I
136
sage: CIF
137
Complex Interval Field with 10 bits of precision
138
sage: CIF = ComplexIntervalField(100); CIF
139
Complex Interval Field with 100 bits of precision
140
sage: z = CIF(1/3, 2/3); z
141
0.333333333333333333333333333334? + 0.666666666666666666666666666667?*I
142
143
We can load and save complex numbers and the complex interval field::
144
145
sage: cmp(loads(z.dumps()), z)
146
0
147
sage: loads(CIF.dumps()) == CIF
148
True
149
sage: k = ComplexIntervalField(100)
150
sage: loads(dumps(k)) == k
151
True
152
153
This illustrates basic properties of a complex (interval) field::
154
155
sage: CIF = ComplexIntervalField(200)
156
sage: CIF.is_field()
157
True
158
sage: CIF.characteristic()
159
0
160
sage: CIF.precision()
161
200
162
sage: CIF.variable_name()
163
'I'
164
sage: CIF == ComplexIntervalField(200)
165
True
166
sage: CIF == ComplexIntervalField(53)
167
False
168
sage: CIF == 1.1
169
False
170
sage: CIF = ComplexIntervalField(53)
171
172
sage: CIF.category()
173
Category of fields
174
sage: TestSuite(CIF).run()
175
"""
176
def __init__(self, prec=53):
177
"""
178
Initialize ``self``.
179
180
EXAMPLES::
181
sage: ComplexIntervalField()
182
Complex Interval Field with 53 bits of precision
183
sage: ComplexIntervalField(200)
184
Complex Interval Field with 200 bits of precision
185
"""
186
self._prec = int(prec)
187
from sage.categories.fields import Fields
188
ParentWithGens.__init__(self, self._real_field(), ('I',), False, category = Fields())
189
190
def __reduce__(self):
191
"""
192
Used for pickling.
193
194
TESTS::
195
196
sage: loads(dumps(CIF)) == CIF
197
True
198
"""
199
return ComplexIntervalField, (self._prec, )
200
201
def is_exact(self):
202
"""
203
The complex interval field is not exact.
204
205
EXAMPLES::
206
207
sage: CIF.is_exact()
208
False
209
"""
210
return False
211
212
def prec(self):
213
"""
214
Returns the precision of ``self`` (in bits).
215
216
EXAMPLES::
217
218
sage: CIF.prec()
219
53
220
sage: ComplexIntervalField(200).prec()
221
200
222
"""
223
return self._prec
224
225
def to_prec(self, prec):
226
"""
227
Returns a complex interval field with the given precision.
228
229
EXAMPLES::
230
231
sage: CIF.to_prec(150)
232
Complex Interval Field with 150 bits of precision
233
sage: CIF.to_prec(15)
234
Complex Interval Field with 15 bits of precision
235
sage: CIF.to_prec(53) is CIF
236
True
237
"""
238
return ComplexIntervalField(prec)
239
240
def _magma_init_(self, magma):
241
r"""
242
Return a string representation of ``self`` in the Magma language.
243
244
EXAMPLES::
245
246
sage: magma(ComplexIntervalField(100)) # optional - magma # indirect doctest
247
Complex field of precision 30
248
sage: floor(RR(log(2**100, 10)))
249
30
250
"""
251
return "ComplexField(%s : Bits := true)" % self.prec()
252
253
def _sage_input_(self, sib, coerce):
254
r"""
255
Produce an expression which will reproduce this value when evaluated.
256
257
EXAMPLES::
258
259
sage: sage_input(CIF, verify=True)
260
# Verified
261
CIF
262
sage: sage_input(ComplexIntervalField(25), verify=True)
263
# Verified
264
ComplexIntervalField(25)
265
sage: k = (CIF, ComplexIntervalField(37), ComplexIntervalField(1024))
266
sage: sage_input(k, verify=True)
267
# Verified
268
(CIF, ComplexIntervalField(37), ComplexIntervalField(1024))
269
sage: sage_input((k, k), verify=True)
270
# Verified
271
CIF37 = ComplexIntervalField(37)
272
CIF1024 = ComplexIntervalField(1024)
273
((CIF, CIF37, CIF1024), (CIF, CIF37, CIF1024))
274
sage: from sage.misc.sage_input import SageInputBuilder
275
sage: ComplexIntervalField(2)._sage_input_(SageInputBuilder(), False)
276
{call: {atomic:ComplexIntervalField}({atomic:2})}
277
"""
278
if self.prec() == 53:
279
return sib.name('CIF')
280
281
v = sib.name('ComplexIntervalField')(sib.int(self.prec()))
282
name = 'CIF%d' % self.prec()
283
sib.cache(self, v, name)
284
return v
285
286
precision = prec
287
288
# very useful to cache this.
289
def _real_field(self):
290
"""
291
Return the underlying :class:`RealIntervalField`.
292
293
EXAMPLES::
294
295
sage: R = CIF._real_field(); R
296
Real Interval Field with 53 bits of precision
297
sage: ComplexIntervalField(200)._real_field()
298
Real Interval Field with 200 bits of precision
299
sage: CIF._real_field() is R
300
True
301
"""
302
try:
303
return self.__real_field
304
except AttributeError:
305
self.__real_field = real_mpfi.RealIntervalField(self._prec)
306
return self.__real_field
307
308
def _middle_field(self):
309
"""
310
Return the corresponding :class:`ComplexField` with the same precision
311
as ``self``.
312
313
EXAMPLES::
314
315
sage: CIF._middle_field()
316
Complex Field with 53 bits of precision
317
sage: ComplexIntervalField(200)._middle_field()
318
Complex Field with 200 bits of precision
319
"""
320
try:
321
return self.__middle_field
322
except AttributeError:
323
self.__middle_field = complex_field.ComplexField(self._prec)
324
return self.__middle_field
325
326
def __cmp__(self, other):
327
"""
328
Compare ``other`` to ``self``.
329
330
If ``other`` is not a :class:`ComplexIntervalField_class`, compare by
331
type, otherwise compare by precision.
332
333
EXAMPLES::
334
335
sage: cmp(CIF, ComplexIntervalField(200))
336
-1
337
sage: cmp(CIF, CC) != 0
338
True
339
sage: cmp(CIF, CIF)
340
0
341
"""
342
if not isinstance(other, ComplexIntervalField_class):
343
return cmp(type(self), type(other))
344
return cmp(self._prec, other._prec)
345
346
def __call__(self, x, im=None):
347
"""
348
Construct an element.
349
350
EXAMPLES::
351
352
sage: CIF(2) # indirect doctest
353
2
354
sage: CIF(CIF.0)
355
1*I
356
sage: CIF('1+I')
357
1 + 1*I
358
sage: CIF(2,3)
359
2 + 3*I
360
sage: CIF(pi, e)
361
3.141592653589794? + 2.718281828459046?*I
362
"""
363
if im is None:
364
if isinstance(x, complex_interval.ComplexIntervalFieldElement) and x.parent() is self:
365
return x
366
elif isinstance(x, complex_double.ComplexDoubleElement):
367
return complex_interval.ComplexIntervalFieldElement(self, x.real(), x.imag())
368
elif isinstance(x, str):
369
# TODO: this is probably not the best and most
370
# efficient way to do this. -- Martin Albrecht
371
return complex_interval.ComplexIntervalFieldElement(self,
372
sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))
373
374
late_import()
375
if isinstance(x, NumberFieldElement_quadratic) and list(x.parent().polynomial()) == [1, 0, 1]:
376
(re, im) = list(x)
377
return complex_interval.ComplexIntervalFieldElement(self, re, im)
378
379
try:
380
return x._complex_mpfi_( self )
381
except AttributeError:
382
pass
383
try:
384
return x._complex_mpfr_field_( self )
385
except AttributeError:
386
pass
387
return complex_interval.ComplexIntervalFieldElement(self, x, im)
388
389
def _coerce_impl(self, x):
390
"""
391
Return the canonical coerce of ``x`` into this complex field, if it is
392
defined, otherwise raise a ``TypeError``.
393
394
The rings that canonically coerce to the MPFI complex field are:
395
396
* this MPFI complex field, or any other of higher precision
397
398
* anything that canonically coerces to the mpfi real field with this
399
precision
400
401
EXAMPLES::
402
403
sage: CIF((2,1)) + 2 + I # indirect doctest
404
4 + 2*I
405
sage: x = ComplexField(25)(2)
406
sage: x
407
2.000000
408
sage: CIF((2,1)) + x
409
Traceback (most recent call last):
410
...
411
TypeError: unsupported operand parent(s) for '+': 'Complex Interval
412
Field with 53 bits of precision' and 'Complex Field with 25 bits of precision'
413
"""
414
try:
415
K = x.parent()
416
if is_ComplexIntervalField(K) and K._prec >= self._prec:
417
return self(x)
418
# elif complex_field.is_ComplexField(K) and K.prec() >= self._prec:
419
# return self(x)
420
except AttributeError:
421
pass
422
if hasattr(x, '_complex_mpfr_field_') or hasattr(x, '_complex_mpfi_'):
423
return self(x)
424
return self._coerce_try(x, self._real_field())
425
426
def _repr_(self):
427
"""
428
Return a string representation of ``self``.
429
430
EXAMPLES::
431
432
sage: ComplexIntervalField() # indirect doctest
433
Complex Interval Field with 53 bits of precision
434
sage: ComplexIntervalField(100) # indirect doctest
435
Complex Interval Field with 100 bits of precision
436
"""
437
return "Complex Interval Field with %s bits of precision"%self._prec
438
439
def _latex_(self):
440
r"""
441
Return a latex representation of ``self``.
442
443
EXAMPLES::
444
445
sage: latex(ComplexIntervalField()) # indirect doctest
446
\Bold{C}
447
"""
448
return "\\Bold{C}"
449
450
def characteristic(self):
451
"""
452
Return the characteristic of the complex (interval) field, which is 0.
453
454
EXAMPLES::
455
456
sage: CIF.characteristic()
457
0
458
"""
459
return integer.Integer(0)
460
461
def gen(self, n=0):
462
"""
463
Return the generator of the complex (interval) field.
464
465
EXAMPLES::
466
467
sage: CIF.0
468
1*I
469
sage: CIF.gen(0)
470
1*I
471
"""
472
if n != 0:
473
raise IndexError, "n must be 0"
474
return complex_interval.ComplexIntervalFieldElement(self, 0, 1)
475
476
def random_element(self, *args, **kwds):
477
"""
478
Create a random element of ``self``.
479
480
This simply chooses the real and imaginary part randomly, passing
481
arguments and keywords to the underlying real interval field.
482
483
EXAMPLES::
484
485
sage: CIF.random_element()
486
0.15363619378561300? - 0.50298737524751780?*I
487
sage: CIF.random_element(10, 20)
488
18.047949821611205? + 10.255727028308920?*I
489
490
Passes extra positional or keyword arguments through::
491
492
sage: CIF.random_element(max=0, min=-5)
493
-0.079017286535590259? - 2.8712089896087117?*I
494
"""
495
return self._real_field().random_element(*args, **kwds) \
496
+ self.gen() * self._real_field().random_element(*args, **kwds)
497
498
def is_field(self, proof = True):
499
"""
500
Return ``True``, since the complex numbers are a field.
501
502
EXAMPLES::
503
504
sage: CIF.is_field()
505
True
506
"""
507
return True
508
509
def is_finite(self):
510
"""
511
Return ``False``, since the complex numbers are infinite.
512
513
EXAMPLES::
514
515
sage: CIF.is_finite()
516
False
517
"""
518
return False
519
520
def pi(self):
521
r"""
522
Returns `\pi` as an element in the complex (interval) field.
523
524
EXAMPLES::
525
526
sage: ComplexIntervalField(100).pi()
527
3.14159265358979323846264338328?
528
"""
529
return self(self._real_field().pi())
530
531
def ngens(self):
532
r"""
533
The number of generators of this complex (interval) field as an
534
`\RR`-algebra.
535
536
There is one generator, namely ``sqrt(-1)``.
537
538
EXAMPLES::
539
540
sage: CIF.ngens()
541
1
542
"""
543
return 1
544
545
def zeta(self, n=2):
546
r"""
547
Return a primitive `n`-th root of unity.
548
549
.. TODO::
550
551
Implement :class:`ComplexIntervalFieldElement` multiplicative order
552
and set this output to have multiplicative order ``n``.
553
554
INPUT:
555
556
- ``n`` -- an integer (default: 2)
557
558
OUTPUT:
559
560
A complex `n`-th root of unity.
561
562
EXAMPLES::
563
564
sage: CIF.zeta(2)
565
-1
566
sage: CIF.zeta(5)
567
0.309016994374948? + 0.9510565162951536?*I
568
"""
569
from integer import Integer
570
n = Integer(n)
571
if n == 1:
572
x = self(1)
573
elif n == 2:
574
x = self(-1)
575
elif n >= 3:
576
# Use De Moivre
577
# e^(2*pi*i/n) = cos(2pi/n) + i *sin(2pi/n)
578
RR = self._real_field()
579
pi = RR.pi()
580
z = 2*pi/n
581
x = complex_interval.ComplexIntervalFieldElement(self, z.cos(), z.sin())
582
# Uncomment after implemented
583
#x._set_multiplicative_order( n )
584
return x
585
586
def scientific_notation(self, status=None):
587
"""
588
Set or return the scientific notation printing flag.
589
590
If this flag is ``True`` then complex numbers with this space as parent
591
print using scientific notation.
592
593
EXAMPLES::
594
595
sage: CIF((0.025, 2))
596
0.025000000000000002? + 2*I
597
sage: CIF.scientific_notation(True)
598
sage: CIF((0.025, 2))
599
2.5000000000000002?e-2 + 2*I
600
sage: CIF.scientific_notation(False)
601
sage: CIF((0.025, 2))
602
0.025000000000000002? + 2*I
603
"""
604
return self._real_field().scientific_notation(status)
605
606
607
608