Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/complex_interval_field.py
4057 views
1
r"""
2
Field of Arbitrary Precision Complex Intervals
3
4
AUTHORS:
5
6
- William Stein wrote complex_field.py.
7
-- William Stein (2006-01-26): complete rewrite
8
Then complex_field.py was copied to complex_interval_field.py and
9
heavily modified:
10
-- Carl Witty (2007-10-24): rewrite for intervals
11
12
-- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
13
14
"""
15
16
#################################################################################
17
# Copyright (C) 2006 William Stein <[email protected]>
18
#
19
# Distributed under the terms of the GNU General Public License (GPL)
20
#
21
# http://www.gnu.org/licenses/
22
#*****************************************************************************
23
24
import complex_double
25
import field
26
import integer
27
import weakref
28
import real_mpfi
29
import complex_interval
30
import complex_field
31
from sage.misc.sage_eval import sage_eval
32
33
from sage.structure.parent_gens import ParentWithGens
34
35
NumberFieldElement_quadratic = None
36
def late_import():
37
global NumberFieldElement_quadratic
38
if NumberFieldElement_quadratic is None:
39
import sage.rings.number_field.number_field_element_quadratic as nfeq
40
NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic
41
42
def is_ComplexIntervalField(x):
43
return isinstance(x, ComplexIntervalField_class)
44
45
cache = {}
46
def ComplexIntervalField(prec=53, names=None):
47
"""
48
Return the complex field with real and imaginary parts having prec
49
*bits* of precision.
50
51
EXAMPLES:
52
sage: ComplexIntervalField()
53
Complex Interval Field with 53 bits of precision
54
sage: ComplexIntervalField(100)
55
Complex Interval Field with 100 bits of precision
56
sage: ComplexIntervalField(100).base_ring()
57
Real Interval Field with 100 bits of precision
58
sage: i = ComplexIntervalField(200).gen()
59
sage: i^2
60
-1
61
sage: i^i
62
0.207879576350761908546955619834978770033877841631769608075136?
63
"""
64
global cache
65
if cache.has_key(prec):
66
X = cache[prec]
67
C = X()
68
if not C is None:
69
return C
70
C = ComplexIntervalField_class(prec)
71
cache[prec] = weakref.ref(C)
72
return C
73
74
75
class ComplexIntervalField_class(field.Field):
76
"""
77
The field of complex numbers.
78
79
EXAMPLES:
80
sage: C = ComplexIntervalField(); C
81
Complex Interval Field with 53 bits of precision
82
sage: Q = RationalField()
83
sage: C(1/3)
84
0.3333333333333334?
85
sage: C(1/3, 2)
86
0.3333333333333334? + 2*I
87
88
We can also coerce rational numbers and integers into C, but
89
coercing a polynomial will raise an exception.
90
91
sage: Q = RationalField()
92
sage: C(1/3)
93
0.3333333333333334?
94
sage: S = PolynomialRing(Q, 'x')
95
sage: C(S.gen())
96
Traceback (most recent call last):
97
...
98
TypeError: unable to coerce to a ComplexIntervalFieldElement
99
100
This illustrates precision.
101
sage: CIF = ComplexIntervalField(10); CIF(1/3, 2/3)
102
0.334? + 0.667?*I
103
sage: CIF
104
Complex Interval Field with 10 bits of precision
105
sage: CIF = ComplexIntervalField(100); CIF
106
Complex Interval Field with 100 bits of precision
107
sage: z = CIF(1/3, 2/3); z
108
0.333333333333333333333333333334? + 0.666666666666666666666666666667?*I
109
110
We can load and save complex numbers and the complex field.
111
sage: cmp(loads(z.dumps()), z)
112
0
113
sage: loads(CIF.dumps()) == CIF
114
True
115
sage: k = ComplexIntervalField(100)
116
sage: loads(dumps(k)) == k
117
True
118
119
This illustrates basic properties of a complex field.
120
sage: CIF = ComplexIntervalField(200)
121
sage: CIF.is_field()
122
True
123
sage: CIF.characteristic()
124
0
125
sage: CIF.precision()
126
200
127
sage: CIF.variable_name()
128
'I'
129
sage: CIF == ComplexIntervalField(200)
130
True
131
sage: CIF == ComplexIntervalField(53)
132
False
133
sage: CIF == 1.1
134
False
135
sage: CIF = ComplexIntervalField(53)
136
137
sage: CIF.category()
138
Category of fields
139
sage: TestSuite(CIF).run()
140
"""
141
def __init__(self, prec=53):
142
self._prec = int(prec)
143
from sage.categories.fields import Fields
144
ParentWithGens.__init__(self, self._real_field(), ('I',), False, category = Fields())
145
146
def __reduce__(self):
147
"""
148
Used for pickling.
149
150
TESTS::
151
loads(dumps(CIF)) == CIF
152
"""
153
return ComplexIntervalField, (self._prec, )
154
155
def is_exact(self):
156
"""
157
The complex interval field is not exact.
158
159
EXAMPLES::
160
161
sage: CIF.is_exact()
162
False
163
"""
164
return False
165
166
def prec(self):
167
"""
168
Returns the precision of self (in bits).
169
170
EXAMPLES::
171
172
sage: CIF.prec()
173
53
174
sage: ComplexIntervalField(200).prec()
175
200
176
"""
177
return self._prec
178
179
def to_prec(self, prec):
180
"""
181
Returns a complex interval field with the given precision.
182
183
EXAMPLES::
184
185
sage: CIF.to_prec(150)
186
Complex Interval Field with 150 bits of precision
187
sage: CIF.to_prec(15)
188
Complex Interval Field with 15 bits of precision
189
sage: CIF.to_prec(53) is CIF
190
True
191
"""
192
return ComplexIntervalField(prec)
193
194
def _magma_init_(self, magma):
195
r"""
196
Return a string representation of self in the Magma language.
197
198
EXAMPLES:
199
sage: magma(ComplexIntervalField(100)) # optional - magma
200
Complex field of precision 30
201
sage: floor(RR(log(2**100, 10)))
202
30
203
"""
204
return "ComplexField(%s : Bits := true)" % self.prec()
205
206
def _sage_input_(self, sib, coerce):
207
r"""
208
Produce an expression which will reproduce this value when evaluated.
209
210
EXAMPLES:
211
sage: sage_input(CIF, verify=True)
212
# Verified
213
CIF
214
sage: sage_input(ComplexIntervalField(25), verify=True)
215
# Verified
216
ComplexIntervalField(25)
217
sage: k = (CIF, ComplexIntervalField(37), ComplexIntervalField(1024))
218
sage: sage_input(k, verify=True)
219
# Verified
220
(CIF, ComplexIntervalField(37), ComplexIntervalField(1024))
221
sage: sage_input((k, k), verify=True)
222
# Verified
223
CIF37 = ComplexIntervalField(37)
224
CIF1024 = ComplexIntervalField(1024)
225
((CIF, CIF37, CIF1024), (CIF, CIF37, CIF1024))
226
sage: from sage.misc.sage_input import SageInputBuilder
227
sage: ComplexIntervalField(2)._sage_input_(SageInputBuilder(), False)
228
{call: {atomic:ComplexIntervalField}({atomic:2})}
229
"""
230
if self.prec() == 53:
231
return sib.name('CIF')
232
233
v = sib.name('ComplexIntervalField')(sib.int(self.prec()))
234
name = 'CIF%d' % self.prec()
235
sib.cache(self, v, name)
236
return v
237
238
precision = prec
239
240
241
# very useful to cache this.
242
def _real_field(self):
243
try:
244
return self.__real_field
245
except AttributeError:
246
self.__real_field = real_mpfi.RealIntervalField(self._prec)
247
return self.__real_field
248
249
def _middle_field(self):
250
try:
251
return self.__middle_field
252
except AttributeError:
253
self.__middle_field = complex_field.ComplexField(self._prec)
254
return self.__middle_field
255
256
def __cmp__(self, other):
257
if not isinstance(other, ComplexIntervalField_class):
258
return cmp(type(self), type(other))
259
return cmp(self._prec, other._prec)
260
261
def __call__(self, x, im=None):
262
"""
263
EXAMPLES:
264
sage: CIF(2)
265
2
266
sage: CIF(CIF.0)
267
1*I
268
sage: CIF('1+I')
269
1 + 1*I
270
sage: CIF(2,3)
271
2 + 3*I
272
sage: CIF(pi, e)
273
3.141592653589794? + 2.718281828459046?*I
274
"""
275
if im is None:
276
if isinstance(x, complex_interval.ComplexIntervalFieldElement) and x.parent() is self:
277
return x
278
elif isinstance(x, complex_double.ComplexDoubleElement):
279
return complex_interval.ComplexIntervalFieldElement(self, x.real(), x.imag())
280
elif isinstance(x, str):
281
# TODO: this is probably not the best and most
282
# efficient way to do this. -- Martin Albrecht
283
return complex_interval.ComplexIntervalFieldElement(self,
284
sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))
285
286
late_import()
287
if isinstance(x, NumberFieldElement_quadratic) and list(x.parent().polynomial()) == [1, 0, 1]:
288
(re, im) = list(x)
289
return complex_interval.ComplexIntervalFieldElement(self, re, im)
290
291
try:
292
return x._complex_mpfi_( self )
293
except AttributeError:
294
pass
295
try:
296
return x._complex_mpfr_field_( self )
297
except AttributeError:
298
pass
299
return complex_interval.ComplexIntervalFieldElement(self, x, im)
300
301
def _coerce_impl(self, x):
302
"""
303
Return the canonical coerce of x into this complex field, if it is defined,
304
otherwise raise a TypeError.
305
306
The rings that canonically coerce to the MPFI complex field are:
307
* this MPFI complex field, or any other of higher precision
308
* anything that canonically coerces to the mpfi real field with this prec
309
"""
310
try:
311
K = x.parent()
312
if is_ComplexIntervalField(K) and K._prec >= self._prec:
313
return self(x)
314
# elif complex_field.is_ComplexField(K) and K.prec() >= self._prec:
315
# return self(x)
316
except AttributeError:
317
pass
318
if hasattr(x, '_complex_mpfr_field_') or hasattr(x, '_complex_mpfi_'):
319
return self(x)
320
return self._coerce_try(x, self._real_field())
321
322
def _repr_(self):
323
return "Complex Interval Field with %s bits of precision"%self._prec
324
325
def _latex_(self):
326
return "\\Bold{C}"
327
328
def characteristic(self):
329
return integer.Integer(0)
330
331
def gen(self, n=0):
332
if n != 0:
333
raise IndexError, "n must be 0"
334
return complex_interval.ComplexIntervalFieldElement(self, 0, 1)
335
336
def random_element(self, *args, **kwds):
337
"""
338
Create a random element of self. Simply chooses the real and
339
imaginary part randomly, passing arguments and keywords to the
340
underlying real interval field.
341
342
EXAMPLES::
343
344
sage: CIF.random_element()
345
0.15363619378561300? - 0.50298737524751780?*I
346
sage: CIF.random_element(10, 20)
347
18.047949821611205? + 10.255727028308920?*I
348
349
Passes extra positional or keyword arguments through::
350
351
sage: CIF.random_element(max=0, min=-5)
352
-0.079017286535590259? - 2.8712089896087117?*I
353
"""
354
return self._real_field().random_element(*args, **kwds) \
355
+ self.gen() * self._real_field().random_element(*args, **kwds)
356
357
def is_field(self, proof = True):
358
"""
359
Return True, since the complex numbers are a field.
360
361
EXAMPLES:
362
sage: CIF.is_field()
363
True
364
"""
365
return True
366
367
def is_finite(self):
368
"""
369
Return False, since the complex numbers are infinite.
370
371
EXAMPLES:
372
sage: CIF.is_finite()
373
False
374
"""
375
return False
376
377
def pi(self):
378
return self(self._real_field().pi())
379
380
def ngens(self):
381
return 1
382
383
def zeta(self, n=2):
384
"""
385
Return a primitive $n$-th root of unity.
386
387
INPUT:
388
n -- an integer (default: 2)
389
390
OUTPUT:
391
a complex n-th root of unity.
392
"""
393
from integer import Integer
394
n = Integer(n)
395
if n == 1:
396
x = self(1)
397
elif n == 2:
398
x = self(-1)
399
elif n >= 3:
400
# Use De Moivre
401
# e^(2*pi*i/n) = cos(2pi/n) + i *sin(2pi/n)
402
RR = self._real_field()
403
pi = RR.pi()
404
z = 2*pi/n
405
x = complex_interval.ComplexIntervalFieldElement(self, z.cos(), z.sin())
406
x._set_multiplicative_order( n )
407
return x
408
409
def scientific_notation(self, status=None):
410
return self._real_field().scientific_notation(status)
411
412
413
414