Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/complex_interval.pyx
8817 views
1
"""
2
Arbitrary Precision Complex Intervals
3
4
This is a simple complex interval package, using intervals which are
5
axis-aligned rectangles in the complex plane. It has very few special
6
functions, and it does not use any special tricks to keep the size of
7
the intervals down.
8
9
AUTHORS:
10
11
These authors wrote ``complex_number.pyx``:
12
13
- William Stein (2006-01-26): complete rewrite
14
- Joel B. Mohler (2006-12-16): naive rewrite into pyrex
15
- William Stein(2007-01): rewrite of Mohler's rewrite
16
17
Then ``complex_number.pyx`` was copied to ``complex_interval.pyx`` and
18
heavily modified:
19
20
- Carl Witty (2007-10-24): rewrite to become a complex interval package
21
22
- Travis Scrimshaw (2012-10-18): Added documentation to get full coverage.
23
24
.. TODO::
25
26
Implement :class:`ComplexIntervalFieldElement` multiplicative
27
order similar to :class:`ComplexNumber` multiplicative
28
order with ``_set_multiplicative_order(n)`` and
29
:meth:`ComplexNumber.multiplicative_order()` methods.
30
"""
31
32
#################################################################################
33
# Copyright (C) 2006 William Stein <[email protected]>
34
#
35
# Distributed under the terms of the GNU General Public License (GPL)
36
#
37
# http://www.gnu.org/licenses/
38
#*****************************************************************************
39
40
import math
41
import operator
42
43
from sage.structure.element cimport FieldElement, RingElement, Element, ModuleElement
44
from complex_number cimport ComplexNumber
45
46
import complex_interval_field
47
from complex_field import ComplexField
48
import sage.misc.misc
49
import integer
50
import infinity
51
import real_mpfi
52
import real_mpfr
53
cimport real_mpfr
54
55
include "sage/ext/stdsage.pxi"
56
57
cdef double LOG_TEN_TWO_PLUS_EPSILON = 3.321928094887363 # a small overestimate of log(10,2)
58
59
def is_ComplexIntervalFieldElement(x):
60
"""
61
Check if ``x`` is a :class:`ComplexIntervalFieldElement`.
62
63
EXAMPLES::
64
65
sage: from sage.rings.complex_interval import is_ComplexIntervalFieldElement as is_CIFE
66
sage: is_CIFE(CIF(2))
67
True
68
sage: is_CIFE(CC(2))
69
False
70
"""
71
return isinstance(x, ComplexIntervalFieldElement)
72
73
cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement):
74
"""
75
A complex interval.
76
77
EXAMPLES::
78
79
sage: I = CIF.gen()
80
sage: b = 1.5 + 2.5*I
81
sage: TestSuite(b).run()
82
"""
83
cdef ComplexIntervalFieldElement _new(self):
84
"""
85
Quickly creates a new initialized complex interval with the
86
same parent as ``self``.
87
"""
88
cdef ComplexIntervalFieldElement x
89
x = PY_NEW(ComplexIntervalFieldElement)
90
x._parent = self._parent
91
x._prec = self._prec
92
mpfi_init2(x.__re, self._prec)
93
mpfi_init2(x.__im, self._prec)
94
return x
95
96
def __init__(self, parent, real, imag=None):
97
"""
98
Initialize a complex number (interval).
99
100
EXAMPLES::
101
102
sage: CIF(1.5, 2.5)
103
1.5000000000000000? + 2.5000000000000000?*I
104
sage: CIF((1.5, 2.5))
105
1.5000000000000000? + 2.5000000000000000?*I
106
sage: CIF(1.5 + 2.5*I)
107
1.5000000000000000? + 2.5000000000000000?*I
108
"""
109
cdef real_mpfi.RealIntervalFieldElement rr, ii
110
self._parent = parent
111
self._prec = self._parent._prec
112
mpfi_init2(self.__re, self._prec)
113
mpfi_init2(self.__im, self._prec)
114
115
if imag is None:
116
if PY_TYPE_CHECK(real, ComplexNumber):
117
real, imag = (<ComplexNumber>real).real(), (<ComplexNumber>real).imag()
118
elif PY_TYPE_CHECK(real, ComplexIntervalFieldElement):
119
real, imag = (<ComplexIntervalFieldElement>real).real(), (<ComplexIntervalFieldElement>real).imag()
120
elif isinstance(real, sage.libs.pari.all.pari_gen):
121
real, imag = real.real(), real.imag()
122
elif isinstance(real, list) or isinstance(real, tuple):
123
re, imag = real
124
real = re
125
elif isinstance(real, complex):
126
real, imag = real.real, real.imag
127
else:
128
imag = 0
129
try:
130
R = parent._real_field()
131
rr = R(real)
132
ii = R(imag)
133
mpfi_set(self.__re, rr.value)
134
mpfi_set(self.__im, ii.value)
135
except TypeError:
136
raise TypeError, "unable to coerce to a ComplexIntervalFieldElement"
137
138
139
def __dealloc__(self):
140
mpfi_clear(self.__re)
141
mpfi_clear(self.__im)
142
143
def _repr_(self):
144
"""
145
Return a string representation of ``self``.
146
147
EXAMPLES::
148
149
sage: CIF(1.5) # indirect doctest
150
1.5000000000000000?
151
sage: CIF(1.5, 2.5) # indirect doctest
152
1.5000000000000000? + 2.5000000000000000?*I
153
"""
154
return self.str(10)
155
156
def __hash__(self):
157
"""
158
Return the hash value of ``self``.
159
160
EXAMPLES::
161
162
sage: hash(CIF(1.5)) # indirect doctest
163
1517890078 # 32-bit
164
-3314089385045448162 # 64-bit
165
sage: hash(CIF(1.5, 2.5)) # indirect doctest
166
-1103102080 # 32-bit
167
3834538979630251904 # 64-bit
168
"""
169
return hash(self.str())
170
171
def __getitem__(self, i):
172
"""
173
Returns either the real or imaginary component of ``self`` depending
174
on the choice of ``i``: real (``i=0``), imaginary (``i=1``)
175
176
INPUTS:
177
178
- ``i`` - 0 or 1
179
180
- ``0`` -- will return the real component of ``self``
181
- ``1`` -- will return the imaginary component of ``self``
182
183
EXAMPLES::
184
185
sage: z = CIF(1.5, 2.5)
186
sage: z[0]
187
1.5000000000000000?
188
sage: z[1]
189
2.5000000000000000?
190
"""
191
if i == 0:
192
return self.real()
193
elif i == 1:
194
return self.imag()
195
raise IndexError, "i must be between 0 and 1."
196
197
def __reduce__( self ):
198
"""
199
Pickling support.
200
201
TESTS::
202
203
sage: a = CIF(1 + I)
204
sage: loads(dumps(a)) == a
205
True
206
"""
207
# TODO: This is potentially slow -- make a 1 version that
208
# is native and much faster -- doesn't use .real()/.imag()
209
return (make_ComplexIntervalFieldElement0, (self._parent, self.real(), self.imag()))
210
211
def str(self, base=10, style=None):
212
"""
213
Returns a string representation of ``self``.
214
215
EXAMPLES::
216
217
sage: CIF(1.5).str()
218
'1.5000000000000000?'
219
sage: CIF(1.5, 2.5).str()
220
'1.5000000000000000? + 2.5000000000000000?*I'
221
sage: CIF(1.5, -2.5).str()
222
'1.5000000000000000? - 2.5000000000000000?*I'
223
sage: CIF(0, -2.5).str()
224
'-2.5000000000000000?*I'
225
sage: CIF(1.5).str(base=3)
226
'1.1111111111111111111111111111111112?'
227
sage: CIF(1, pi).str(style='brackets')
228
'[1.0000000000000000 .. 1.0000000000000000] + [3.1415926535897931 .. 3.1415926535897936]*I'
229
230
.. SEEALSO::
231
232
- :meth:`RealIntervalFieldElement.str`
233
"""
234
s = ""
235
if not self.real().is_zero():
236
s = self.real().str(base=base, style=style)
237
if not self.imag().is_zero():
238
y = self.imag()
239
if s!="":
240
if y < 0:
241
s = s+" - "
242
y = -y
243
else:
244
s = s+" + "
245
s = s+"%s*I"%y.str(base=base, style=style)
246
if len(s) == 0:
247
s = "0"
248
return s
249
250
def plot(self, pointsize=10, **kwds):
251
r"""
252
Plot a complex interval as a rectangle.
253
254
EXAMPLES::
255
256
sage: sum(plot(CIF(RIF(1/k, 1/k), RIF(-k, k))) for k in [1..10])
257
258
Exact and nearly exact points are still visible::
259
260
sage: plot(CIF(pi, 1), color='red') + plot(CIF(1, e), color='purple') + plot(CIF(-1, -1))
261
262
A demonstration that `z \mapsto z^2` acts chaotically on `|z|=1`::
263
264
sage: z = CIF(0, 2*pi/1000).exp()
265
sage: g = Graphics()
266
sage: for i in range(40):
267
... z = z^2
268
... g += z.plot(color=(1./(40-i), 0, 1))
269
...
270
sage: g
271
"""
272
from sage.plot.polygon import polygon2d
273
x, y = self.real(), self.imag()
274
x0, y0 = x.lower(), y.lower()
275
x1, y1 = x.upper(), y.upper()
276
g = polygon2d([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)],
277
thickness=pointsize/4, **kwds)
278
# Nearly empty polygons don't show up.
279
g += self.center().plot(pointsize= pointsize, **kwds)
280
return g
281
282
def _latex_(self):
283
"""
284
Returns a latex representation of ``self``.
285
286
EXAMPLES::
287
288
sage: latex(CIF(1.5, -2.5)) # indirect doctest
289
1.5000000000000000? - 2.5000000000000000?i
290
sage: latex(CIF(0, 3e200)) # indirect doctest
291
3.0000000000000000? \times 10^{200}i
292
"""
293
import re
294
s = self.str().replace('*I', 'i')
295
return re.sub(r"e(-?\d+)", r" \\times 10^{\1}", s)
296
297
def bisection(self):
298
"""
299
Returns the bisection of ``self`` into four intervals whose union is
300
``self`` and intersection is :meth:`center()`.
301
302
EXAMPLES::
303
304
sage: z = CIF(RIF(2, 3), RIF(-5, -4))
305
sage: z.bisection()
306
(3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I)
307
sage: for z in z.bisection():
308
... print z.real().endpoints(), z.imag().endpoints()
309
(2.00000000000000, 2.50000000000000) (-5.00000000000000, -4.50000000000000)
310
(2.50000000000000, 3.00000000000000) (-5.00000000000000, -4.50000000000000)
311
(2.00000000000000, 2.50000000000000) (-4.50000000000000, -4.00000000000000)
312
(2.50000000000000, 3.00000000000000) (-4.50000000000000, -4.00000000000000)
313
314
sage: z = CIF(RIF(sqrt(2), sqrt(3)), RIF(e, pi))
315
sage: a, b, c, d = z.bisection()
316
sage: a.intersection(b).intersection(c).intersection(d) == CIF(z.center())
317
True
318
319
sage: zz = a.union(b).union(c).union(c)
320
sage: zz.real().endpoints() == z.real().endpoints()
321
True
322
sage: zz.imag().endpoints() == z.imag().endpoints()
323
True
324
"""
325
cdef ComplexIntervalFieldElement a00 = self._new()
326
mpfr_set(&a00.__re.left, &self.__re.left, GMP_RNDN)
327
mpfi_mid(&a00.__re.right, self.__re)
328
mpfr_set(&a00.__im.left, &self.__im.left, GMP_RNDN)
329
mpfi_mid(&a00.__im.right, self.__im)
330
331
cdef ComplexIntervalFieldElement a01 = self._new()
332
mpfr_set(&a01.__re.left, &a00.__re.right, GMP_RNDN)
333
mpfr_set(&a01.__re.right, &self.__re.right, GMP_RNDN)
334
mpfi_set(a01.__im, a00.__im)
335
336
cdef ComplexIntervalFieldElement a10 = self._new()
337
mpfi_set(a10.__re, a00.__re)
338
mpfi_mid(&a10.__im.left, self.__im)
339
mpfr_set(&a10.__im.right, &self.__im.right, GMP_RNDN)
340
341
cdef ComplexIntervalFieldElement a11 = self._new()
342
mpfi_set(a11.__re, a01.__re)
343
mpfi_set(a11.__im, a10.__im)
344
345
return a00, a01, a10, a11
346
347
def is_exact(self):
348
"""
349
Returns whether this complex interval is exact (i.e. contains exactly
350
one complex value).
351
352
EXAMPLES::
353
354
sage: CIF(3).is_exact()
355
True
356
sage: CIF(0, 2).is_exact()
357
True
358
sage: CIF(-4, 0).sqrt().is_exact()
359
True
360
sage: CIF(-5, 0).sqrt().is_exact()
361
False
362
sage: CIF(0, 2*pi).is_exact()
363
False
364
sage: CIF(e).is_exact()
365
False
366
sage: CIF(1e100).is_exact()
367
True
368
sage: (CIF(1e100) + 1).is_exact()
369
False
370
"""
371
return mpfr_equal_p(&self.__re.left, &self.__re.right) and \
372
mpfr_equal_p(&self.__im.left, &self.__im.right)
373
374
def diameter(self):
375
"""
376
Returns a somewhat-arbitrarily defined "diameter" for this interval.
377
378
The diameter of an interval is the maximum of the diameter of the real
379
and imaginary components, where diameter on a real interval is defined
380
as absolute diameter if the interval contains zero, and relative
381
diameter otherwise.
382
383
EXAMPLES::
384
385
sage: CIF(RIF(-1, 1), RIF(13, 17)).diameter()
386
2.00000000000000
387
sage: CIF(RIF(-0.1, 0.1), RIF(13, 17)).diameter()
388
0.266666666666667
389
sage: CIF(RIF(-1, 1), 15).diameter()
390
2.00000000000000
391
"""
392
cdef real_mpfr.RealNumber diam
393
diam = real_mpfr.RealNumber(self._parent._real_field()._middle_field(), None)
394
cdef mpfr_t tmp
395
mpfr_init2(tmp, self.prec())
396
mpfi_diam(diam.value, self.__re)
397
mpfi_diam(tmp, self.__im)
398
mpfr_max(diam.value, diam.value, tmp, GMP_RNDU)
399
mpfr_clear(tmp)
400
return diam
401
402
def overlaps(self, ComplexIntervalFieldElement other):
403
"""
404
Returns ``True`` if ``self`` and other are intervals with at least
405
one value in common.
406
407
EXAMPLES::
408
409
sage: CIF(0).overlaps(CIF(RIF(0, 1), RIF(-1, 0)))
410
True
411
sage: CIF(1).overlaps(CIF(1, 1))
412
False
413
"""
414
return mpfr_greaterequal_p(&self.__re.right, &other.__re.left) \
415
and mpfr_greaterequal_p(&other.__re.right, &self.__re.left) \
416
and mpfr_greaterequal_p(&self.__im.right, &other.__im.left) \
417
and mpfr_greaterequal_p(&other.__im.right, &self.__im.left)
418
419
def intersection(self, other):
420
"""
421
Returns the intersection of the two complex intervals ``self`` and
422
``other``.
423
424
EXAMPLES::
425
426
sage: CIF(RIF(1, 3), RIF(1, 3)).intersection(CIF(RIF(2, 4), RIF(2, 4))).str(style='brackets')
427
'[2.0000000000000000 .. 3.0000000000000000] + [2.0000000000000000 .. 3.0000000000000000]*I'
428
sage: CIF(RIF(1, 2), RIF(1, 3)).intersection(CIF(RIF(3, 4), RIF(2, 4)))
429
Traceback (most recent call last):
430
...
431
ValueError: intersection of non-overlapping intervals
432
"""
433
434
cdef ComplexIntervalFieldElement x = self._new()
435
cdef ComplexIntervalFieldElement other_intv
436
if PY_TYPE_CHECK(other, ComplexIntervalFieldElement):
437
other_intv = other
438
else:
439
# Let type errors from _coerce_ propagate...
440
other_intv = self._parent(other)
441
442
mpfi_intersect(x.__re, self.__re, other_intv.__re)
443
mpfi_intersect(x.__im, self.__im, other_intv.__im)
444
if mpfr_less_p(&x.__re.right, &x.__re.left) \
445
or mpfr_less_p(&x.__im.right, &x.__im.left):
446
raise ValueError, "intersection of non-overlapping intervals"
447
448
return x
449
450
def union(self, other):
451
"""
452
Returns the smallest complex interval including the
453
two complex intervals ``self`` and ``other``.
454
455
EXAMPLES::
456
457
sage: CIF(0).union(CIF(5, 5)).str(style='brackets')
458
'[0.00000000000000000 .. 5.0000000000000000] + [0.00000000000000000 .. 5.0000000000000000]*I'
459
"""
460
cdef ComplexIntervalFieldElement x = self._new()
461
cdef ComplexIntervalFieldElement other_intv
462
if PY_TYPE_CHECK(other, ComplexIntervalFieldElement):
463
other_intv = other
464
else:
465
# Let type errors from _coerce_ propagate...
466
other_intv = self._parent(other)
467
468
mpfi_union(x.__re, self.__re, other_intv.__re)
469
mpfi_union(x.__im, self.__im, other_intv.__im)
470
return x
471
472
def center(self):
473
"""
474
Returns the closest floating-point approximation to the center
475
of the interval.
476
477
EXAMPLES::
478
479
sage: CIF(RIF(1, 2), RIF(3, 4)).center()
480
1.50000000000000 + 3.50000000000000*I
481
"""
482
cdef complex_number.ComplexNumber center
483
center = complex_number.ComplexNumber(self._parent._middle_field(), None)
484
mpfi_mid(center.__re, self.__re)
485
mpfi_mid(center.__im, self.__im)
486
487
return center
488
489
def __contains__(self, other):
490
"""
491
Test whether ``other`` is totally contained in ``self``.
492
493
EXAMPLES::
494
495
sage: CIF(1, 1) in CIF(RIF(1, 2), RIF(1, 2))
496
True
497
"""
498
# This could be more efficient (and support more types for "other").
499
return (other.real() in self.real()) and (other.imag() in self.imag())
500
501
def contains_zero(self):
502
"""
503
Returns ``True`` if ``self`` is an interval containing zero.
504
505
EXAMPLES::
506
507
sage: CIF(0).contains_zero()
508
True
509
sage: CIF(RIF(-1, 1), 1).contains_zero()
510
False
511
"""
512
return mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im)
513
514
cpdef ModuleElement _add_(self, ModuleElement right):
515
"""
516
Add ``self`` and ``right``.
517
518
EXAMPLES::
519
520
sage: CIF(2,-3)._add_(CIF(1,-2))
521
3 - 5*I
522
"""
523
cdef ComplexIntervalFieldElement x
524
x = self._new()
525
mpfi_add(x.__re, self.__re, (<ComplexIntervalFieldElement>right).__re)
526
mpfi_add(x.__im, self.__im, (<ComplexIntervalFieldElement>right).__im)
527
return x
528
529
cpdef ModuleElement _sub_(self, ModuleElement right):
530
"""
531
Subtract ``self`` by ``right``.
532
533
EXAMPLES::
534
535
sage: CIF(2,-3)._sub_(CIF(1,-2))
536
1 - 1*I
537
"""
538
cdef ComplexIntervalFieldElement x
539
x = self._new()
540
mpfi_sub(x.__re, self.__re, (<ComplexIntervalFieldElement>right).__re)
541
mpfi_sub(x.__im, self.__im, (<ComplexIntervalFieldElement>right).__im)
542
return x
543
544
cpdef RingElement _mul_(self, RingElement right):
545
"""
546
Multiply ``self`` and ``right``.
547
548
EXAMPLES::
549
550
sage: CIF(2,-3)._mul_(CIF(1,-2))
551
-4 - 7*I
552
"""
553
cdef ComplexIntervalFieldElement x
554
x = self._new()
555
cdef mpfi_t t0, t1
556
mpfi_init2(t0, self._prec)
557
mpfi_init2(t1, self._prec)
558
mpfi_mul(t0, self.__re, (<ComplexIntervalFieldElement>right).__re)
559
mpfi_mul(t1, self.__im, (<ComplexIntervalFieldElement>right).__im)
560
mpfi_sub(x.__re, t0, t1)
561
mpfi_mul(t0, self.__re, (<ComplexIntervalFieldElement>right).__im)
562
mpfi_mul(t1, self.__im, (<ComplexIntervalFieldElement>right).__re)
563
mpfi_add(x.__im, t0, t1)
564
mpfi_clear(t0)
565
mpfi_clear(t1)
566
return x
567
568
def norm(self):
569
"""
570
Returns the norm of this complex number.
571
572
If `c = a + bi` is a complex number, then the norm of `c` is defined as
573
the product of `c` and its complex conjugate:
574
575
.. MATH::
576
577
\text{norm}(c)
578
=
579
\text{norm}(a + bi)
580
=
581
c \cdot \overline{c}
582
=
583
a^2 + b^2.
584
585
The norm of a complex number is different from its absolute value.
586
The absolute value of a complex number is defined to be the square
587
root of its norm. A typical use of the complex norm is in the
588
integral domain `\ZZ[i]` of Gaussian integers, where the norm of
589
each Gaussian integer `c = a + bi` is defined as its complex norm.
590
591
.. SEEALSO::
592
593
- :meth:`sage.rings.complex_double.ComplexDoubleElement.norm`
594
595
EXAMPLES::
596
597
sage: CIF(2, 1).norm()
598
5
599
sage: CIF(1, -2).norm()
600
5
601
"""
602
return self.norm_c()
603
604
cdef real_mpfi.RealIntervalFieldElement norm_c(ComplexIntervalFieldElement self):
605
cdef real_mpfi.RealIntervalFieldElement x
606
x = real_mpfi.RealIntervalFieldElement(self._parent._real_field(), None)
607
608
cdef mpfi_t t0, t1
609
mpfi_init2(t0, self._prec)
610
mpfi_init2(t1, self._prec)
611
612
mpfi_sqr(t0, self.__re)
613
mpfi_sqr(t1, self.__im)
614
615
mpfi_add(x.value, t0, t1)
616
617
mpfi_clear(t0)
618
mpfi_clear(t1)
619
return x
620
621
cdef real_mpfi.RealIntervalFieldElement abs_c(ComplexIntervalFieldElement self):
622
cdef real_mpfi.RealIntervalFieldElement x
623
x = real_mpfi.RealIntervalFieldElement(self._parent._real_field(), None)
624
625
cdef mpfi_t t0, t1
626
mpfi_init2(t0, self._prec)
627
mpfi_init2(t1, self._prec)
628
629
mpfi_sqr(t0, self.__re)
630
mpfi_sqr(t1, self.__im)
631
632
mpfi_add(x.value, t0, t1)
633
mpfi_sqrt(x.value, x.value)
634
635
mpfi_clear(t0)
636
mpfi_clear(t1)
637
return x
638
639
cpdef RingElement _div_(self, RingElement right):
640
"""
641
Divide ``self`` by ``right``.
642
643
EXAMPLES::
644
645
sage: CIF(2,-3)._div_(CIF(1,-2))
646
1.600000000000000? + 0.200000000000000?*I
647
"""
648
cdef ComplexIntervalFieldElement x
649
x = self._new()
650
cdef mpfi_t a, b, t0, t1, right_nm
651
mpfi_init2(t0, self._prec)
652
mpfi_init2(t1, self._prec)
653
mpfi_init2(a, self._prec)
654
mpfi_init2(b, self._prec)
655
mpfi_init2(right_nm, self._prec)
656
657
mpfi_sqr(t0, (<ComplexIntervalFieldElement>right).__re)
658
mpfi_sqr(t1, (<ComplexIntervalFieldElement>right).__im)
659
mpfi_add(right_nm, t0, t1)
660
661
mpfi_div(a, (<ComplexIntervalFieldElement>right).__re, right_nm)
662
mpfi_div(b, (<ComplexIntervalFieldElement>right).__im, right_nm)
663
664
## Do this: x.__re = a * self.__re + b * self.__im
665
mpfi_mul(t0, a, self.__re)
666
mpfi_mul(t1, b, self.__im)
667
mpfi_add(x.__re, t0, t1)
668
669
## Do this: x.__im = a * self.__im - b * self.__re
670
mpfi_mul(t0, a, self.__im)
671
mpfi_mul(t1, b, self.__re)
672
mpfi_sub(x.__im, t0, t1)
673
mpfi_clear(t0)
674
mpfi_clear(t1)
675
mpfi_clear(a)
676
mpfi_clear(b)
677
mpfi_clear(right_nm)
678
return x
679
680
def __rdiv__(self, left):
681
"""
682
Divide ``left`` by ``self``.
683
684
EXAMPLES::
685
686
sage: CIF(2,-3).__rdiv__(CIF(1,-2))
687
0.6153846153846154? - 0.0769230769230769?*I
688
"""
689
return ComplexIntervalFieldElement(self._parent, left)/self
690
691
def __pow__(self, right, modulus):
692
r"""
693
Compute `x^y`.
694
695
If `y` is an integer, uses multiplication;
696
otherwise, uses the standard definition `\exp(\log(x) \cdot y)`.
697
698
.. WARNING::
699
700
If the interval `x` crosses the negative real axis, then we use a
701
non-standard definition of `\log()` (see the docstring for
702
:meth:`argument()` for more details). This means that we will not
703
select the principal value of the power, for part of the input
704
interval (and that we violate the interval guarantees).
705
706
EXAMPLES::
707
708
sage: C.<i> = ComplexIntervalField(20)
709
sage: a = i^2; a
710
-1
711
sage: a.parent()
712
Complex Interval Field with 20 bits of precision
713
sage: a = (1+i)^7; a
714
8 - 8*I
715
sage: (1+i)^(1+i)
716
0.27396? + 0.58370?*I
717
sage: a.parent()
718
Complex Interval Field with 20 bits of precision
719
sage: (2+i)^(-39)
720
1.688?e-14 + 1.628?e-14*I
721
722
If the interval crosses the negative real axis, then we don't use the
723
standard branch cut (and we violate the interval guarantees)::
724
725
sage: (CIF(-7, RIF(-1, 1)) ^ CIF(0.3)).str(style='brackets')
726
'[0.99109735947126309 .. 1.1179269966896264] + [1.4042388462787560 .. 1.4984624123369835]*I'
727
sage: CIF(-7, -1) ^ CIF(0.3)
728
1.117926996689626? - 1.408500714575360?*I
729
"""
730
if isinstance(right, (int, long, integer.Integer)):
731
return sage.rings.ring_element.RingElement.__pow__(self, right)
732
return (self.log() * self.parent()(right)).exp()
733
734
def _magma_init_(self, magma):
735
r"""
736
Return a string representation of ``self`` in the Magma language.
737
738
EXAMPLES::
739
740
sage: t = CIF((1, 1.1), 2.5); t
741
1.1? + 2.5000000000000000?*I
742
sage: magma(t) # optional - magma # indirect doctest
743
1.05000000000000 + 2.50000000000000*$.1
744
sage: t = ComplexIntervalField(100)((1, 4/3), 2.5); t
745
2.? + 2.5000000000000000000000000000000?*I
746
sage: magma(t) # optional - magma
747
1.16666666666666666666666666670 + 2.50000000000000000000000000000*$.1
748
"""
749
return "%s![%s, %s]" % (self.parent()._magma_init_(magma), self.center().real(), self.center().imag())
750
751
def _interface_init_(self, I=None):
752
"""
753
Raise a ``TypeError``.
754
755
This function would return the string representation of ``self``
756
that makes sense as a default representation of a complex
757
interval in other computer algebra systems. But, most other
758
computer algebra systems do not support interval arithmetic,
759
so instead we just raise a ``TypeError``.
760
761
Define the appropriate ``_cas_init_`` function if there is a
762
computer algebra system you would like to support.
763
764
EXAMPLES::
765
766
sage: n = CIF(1.3939494594)
767
sage: n._interface_init_()
768
Traceback (most recent call last):
769
...
770
TypeError
771
772
Here a conversion to Maxima happens, which results in a ``TypeError``::
773
774
sage: a = CIF(2.3)
775
sage: maxima(a)
776
Traceback (most recent call last):
777
...
778
TypeError
779
"""
780
raise TypeError
781
782
783
def _sage_input_(self, sib, coerce):
784
r"""
785
Produce an expression which will reproduce this value when evaluated.
786
787
EXAMPLES::
788
789
sage: sage_input(CIF(RIF(e, pi), RIF(sqrt(2), sqrt(3))), verify=True)
790
# Verified
791
CIF(RIF(RR(2.7182818284590451), RR(3.1415926535897936)), RIF(RR(1.4142135623730949), RR(1.7320508075688774)))
792
sage: sage_input(ComplexIntervalField(64)(2)^I, preparse=False, verify=True)
793
# Verified
794
RIF64 = RealIntervalField(64)
795
RR64 = RealField(64)
796
ComplexIntervalField(64)(RIF64(RR64('0.769238901363972126565'), RR64('0.769238901363972126619')), RIF64(RR64('0.638961276313634801076'), RR64('0.638961276313634801184')))
797
sage: from sage.misc.sage_input import SageInputBuilder
798
sage: sib = SageInputBuilder()
799
sage: ComplexIntervalField(15)(3+I).log()._sage_input_(sib, False)
800
{call: {call: {atomic:ComplexIntervalField}({atomic:15})}({call: {call: {atomic:RealIntervalField}({atomic:15})}({call: {call: {atomic:RealField}({atomic:15})}({atomic:1.15125})}, {call: {call: {atomic:RealField}({atomic:15})}({atomic:1.15137})})}, {call: {call: {atomic:RealIntervalField}({atomic:15})}({call: {call: {atomic:RealField}({atomic:15})}({atomic:0.321655})}, {call: {call: {atomic:RealField}({atomic:15})}({atomic:0.321777})})})}
801
"""
802
# Interval printing could often be much prettier,
803
# but I'm feeling lazy :)
804
return sib(self.parent())(sib(self.real()), sib(self.imag()))
805
806
def prec(self):
807
"""
808
Return precision of this complex number.
809
810
EXAMPLES::
811
812
sage: i = ComplexIntervalField(2000).0
813
sage: i.prec()
814
2000
815
"""
816
return self._parent.prec()
817
818
def real(self):
819
"""
820
Return real part of ``self``.
821
822
EXAMPLES::
823
824
sage: i = ComplexIntervalField(100).0
825
sage: z = 2 + 3*i
826
sage: x = z.real(); x
827
2
828
sage: x.parent()
829
Real Interval Field with 100 bits of precision
830
"""
831
cdef real_mpfi.RealIntervalFieldElement x
832
x = real_mpfi.RealIntervalFieldElement(self._parent._real_field(), None)
833
mpfi_set(x.value, self.__re)
834
return x
835
836
def imag(self):
837
"""
838
Return imaginary part of ``self``.
839
840
EXAMPLES::
841
842
sage: i = ComplexIntervalField(100).0
843
sage: z = 2 + 3*i
844
sage: x = z.imag(); x
845
3
846
sage: x.parent()
847
Real Interval Field with 100 bits of precision
848
"""
849
cdef real_mpfi.RealIntervalFieldElement x
850
x = real_mpfi.RealIntervalFieldElement(self._parent._real_field(), None)
851
mpfi_set(x.value, self.__im)
852
return x
853
854
def __neg__(self):
855
"""
856
Return the negation of ``self``.
857
858
EXAMPLES::
859
860
sage: CIF(1.5, 2.5).__neg__()
861
-1.5000000000000000? - 2.5000000000000000?*I
862
"""
863
cdef ComplexIntervalFieldElement x
864
x = self._new()
865
mpfi_neg(x.__re, self.__re)
866
mpfi_neg(x.__im, self.__im)
867
return x
868
869
def __pos__(self):
870
"""
871
Return the "positive" of ``self``, which is just ``self``.
872
873
EXAMPLES::
874
875
sage: CIF(1.5, 2.5).__pos__()
876
1.5000000000000000? + 2.5000000000000000?*I
877
"""
878
return self
879
880
def __abs__(self):
881
"""
882
Return the absolute value of ``self``.
883
884
EXAMPLES::
885
886
sage: CIF(1.5, 2.5).__abs__()
887
2.915475947422650?
888
"""
889
return self.abs_c()
890
891
def __invert__(self):
892
"""
893
Return the multiplicative inverse of ``self``.
894
895
EXAMPLES::
896
897
sage: I = CIF.0
898
sage: a = ~(5+I) # indirect doctest
899
sage: a * (5+I)
900
1.000000000000000? + 0.?e-16*I
901
"""
902
cdef ComplexIntervalFieldElement x
903
x = self._new()
904
905
cdef mpfi_t t0, t1
906
mpfi_init2(t0, self._prec)
907
mpfi_init2(t1, self._prec)
908
909
mpfi_sqr(t0, self.__re)
910
mpfi_sqr(t1, self.__im)
911
912
mpfi_add(t0, t0, t1) # now t0 is the norm
913
mpfi_div(x.__re, self.__re, t0) # x.__re = self.__re/norm
914
915
mpfi_neg(t1, self.__im)
916
mpfi_div(x.__im, t1, t0) # x.__im = -self.__im/norm
917
918
mpfi_clear(t0)
919
mpfi_clear(t1)
920
921
return x
922
923
def __int__(self):
924
"""
925
Convert ``self`` to an ``int``.
926
927
EXAMPLES::
928
929
sage: int(CIF(1,1))
930
Traceback (most recent call last):
931
...
932
TypeError: can't convert complex interval to int
933
"""
934
raise TypeError, "can't convert complex interval to int"
935
936
def __long__(self):
937
"""
938
Convert ``self`` to a ``lon``.
939
940
EXAMPLES::
941
942
sage: long(CIF(1,1))
943
Traceback (most recent call last):
944
...
945
TypeError: can't convert complex interval to long
946
"""
947
raise TypeError, "can't convert complex interval to long"
948
949
def __float__(self):
950
"""
951
Convert ``self`` to a ``float``.
952
953
EXAMPLES::
954
955
sage: float(CIF(1,1))
956
Traceback (most recent call last):
957
...
958
TypeError: can't convert complex interval to float
959
"""
960
raise TypeError, "can't convert complex interval to float"
961
962
def __complex__(self):
963
"""
964
Convert ``self`` to a ``complex``.
965
966
EXAMPLES::
967
968
sage: complex(CIF(1,1))
969
Traceback (most recent call last):
970
...
971
TypeError: can't convert complex interval to complex
972
"""
973
raise TypeError, "can't convert complex interval to complex"
974
975
def __richcmp__(left, right, int op):
976
r"""
977
As with the real interval fields this never returns false positives.
978
Thus, `a == b` is ``True`` iff both `a` and `b` represent the same
979
one-point interval. Likewise `a != b` is ``True`` iff `x != y` for all
980
`x \in a, y \in b`.
981
982
EXAMPLES::
983
984
sage: CIF(0) == CIF(0)
985
True
986
sage: CIF(0) == CIF(1)
987
False
988
sage: CIF.gen() == CIF.gen()
989
True
990
sage: CIF(0) == CIF.gen()
991
False
992
sage: CIF(0) != CIF(1)
993
True
994
sage: -CIF(-3).sqrt() != CIF(-3).sqrt()
995
True
996
997
These intervals overlap, but contain unequal points::
998
999
sage: CIF(3).sqrt() == CIF(3).sqrt()
1000
False
1001
sage: CIF(3).sqrt() != CIF(3).sqrt()
1002
False
1003
1004
In the future, complex interval elements may be unordered,
1005
but or backwards compatibility we order them lexicographically::
1006
1007
sage: CDF(-1) < -CDF.gen() < CDF.gen() < CDF(1)
1008
True
1009
sage: CDF(1) >= CDF(1) >= CDF.gen() >= CDF.gen() >= 0 >= -CDF.gen() >= CDF(-1)
1010
True
1011
"""
1012
return (<Element>left)._richcmp(right, op)
1013
1014
cdef _richcmp_c_impl(left, Element right, int op):
1015
cdef ComplexIntervalFieldElement lt, rt
1016
lt = left
1017
rt = right
1018
if op == 2: #==
1019
# intervals a == b iff a<=b and b <= a
1020
# (this gives a result with two comparisons, where the
1021
# obvious approach would use three)
1022
return mpfr_lessequal_p(&lt.__re.right, &rt.__re.left) \
1023
and mpfr_lessequal_p(&rt.__re.right, &lt.__re.left) \
1024
and mpfr_lessequal_p(&lt.__im.right, &rt.__im.left) \
1025
and mpfr_lessequal_p(&rt.__im.right, &lt.__im.left)
1026
elif op == 3: #!=
1027
return mpfr_less_p(&lt.__re.right, &rt.__re.left) \
1028
or mpfr_less_p(&rt.__re.right, &lt.__re.left) \
1029
or mpfr_less_p(&lt.__im.right, &rt.__im.left) \
1030
or mpfr_less_p(&rt.__im.right, &lt.__im.left)
1031
else:
1032
# Eventually we probably want to disable comparison of complex
1033
# intervals, just like python complexes will be unordered.
1034
## raise TypeError, "no ordering relation is defined for complex numbers"
1035
diff = left - right
1036
real_diff = diff.real()
1037
imag_diff = diff.imag()
1038
if op == 0: #<
1039
return real_diff < 0 or (real_diff == 0 and imag_diff < 0)
1040
elif op == 1: #<=
1041
return real_diff < 0 or (real_diff == 0 and imag_diff <= 0)
1042
elif op == 4: #>
1043
return real_diff > 0 or (real_diff == 0 and imag_diff > 0)
1044
elif op == 5: #>=
1045
return real_diff > 0 or (real_diff == 0 and imag_diff >= 0)
1046
1047
def __cmp__(left, right):
1048
"""
1049
Intervals are compared lexicographically on the 4-tuple:
1050
``(x.real().lower(), x.real().upper(),
1051
x.imag().lower(), x.imag().upper())``
1052
1053
EXAMPLES::
1054
1055
sage: a = CIF(RIF(0,1), RIF(0,1))
1056
sage: b = CIF(RIF(0,1), RIF(0,2))
1057
sage: c = CIF(RIF(0,2), RIF(0,2))
1058
sage: cmp(a, b)
1059
-1
1060
sage: cmp(b, c)
1061
-1
1062
sage: cmp(a, c)
1063
-1
1064
sage: cmp(a, a)
1065
0
1066
sage: cmp(b, a)
1067
1
1068
"""
1069
return (<Element>left)._cmp(right)
1070
1071
1072
cdef int _cmp_c_impl(left, sage.structure.element.Element right) except -2:
1073
"""
1074
Intervals are compared lexicographically on the 4-tuple:
1075
``(x.real().lower(), x.real().upper(),
1076
x.imag().lower(), x.imag().upper())``
1077
1078
TESTS::
1079
1080
sage: tests = []
1081
sage: for rl in (0, 1):
1082
... for ru in (rl, rl + 1):
1083
... for il in (0, 1):
1084
... for iu in (il, il + 1):
1085
... tests.append((CIF(RIF(rl, ru), RIF(il, iu)), (rl, ru, il, iu)))
1086
sage: for (i1, t1) in tests:
1087
... for (i2, t2) in tests:
1088
... assert(cmp(i1, i2) == cmp(t1, t2))
1089
"""
1090
cdef int a, b
1091
a = mpfi_nan_p(left.__re)
1092
b = mpfi_nan_p((<ComplexIntervalFieldElement>right).__re)
1093
if a != b:
1094
return -1
1095
1096
cdef int i
1097
i = mpfr_cmp(&left.__re.left, &(<ComplexIntervalFieldElement>right).__re.left)
1098
if i < 0:
1099
return -1
1100
elif i > 0:
1101
return 1
1102
i = mpfr_cmp(&left.__re.right, &(<ComplexIntervalFieldElement>right).__re.right)
1103
if i < 0:
1104
return -1
1105
elif i > 0:
1106
return 1
1107
i = mpfr_cmp(&left.__im.left, &(<ComplexIntervalFieldElement>right).__im.left)
1108
if i < 0:
1109
return -1
1110
elif i > 0:
1111
return 1
1112
i = mpfr_cmp(&left.__im.right, &(<ComplexIntervalFieldElement>right).__im.right)
1113
if i < 0:
1114
return -1
1115
elif i > 0:
1116
return 1
1117
return 0
1118
1119
########################################################################
1120
# Transcendental (and other) functions
1121
########################################################################
1122
1123
def argument(self):
1124
r"""
1125
The argument (angle) of the complex number, normalized
1126
so that `-\pi < \theta.lower() \leq \pi`.
1127
1128
We raise a ``ValueError`` if the interval strictly contains 0,
1129
or if the interval contains only 0.
1130
1131
.. WARNING::
1132
1133
We do not always use the standard branch cut for
1134
argument! If the interval crosses the negative real axis,
1135
then the argument will be an interval whose lower bound is
1136
less than `\pi` and whose upper bound is more than `\pi`; in
1137
effect, we move the branch cut away from the interval.
1138
1139
EXAMPLES::
1140
1141
sage: i = CIF.0
1142
sage: (i^2).argument()
1143
3.141592653589794?
1144
sage: (1+i).argument()
1145
0.785398163397449?
1146
sage: i.argument()
1147
1.570796326794897?
1148
sage: (-i).argument()
1149
-1.570796326794897?
1150
sage: (RR('-0.001') - i).argument()
1151
-1.571796326461564?
1152
sage: CIF(2).argument()
1153
0
1154
sage: CIF(-2).argument()
1155
3.141592653589794?
1156
1157
Here we see that if the interval crosses the negative real
1158
axis, then the argument can exceed `\pi`, and we
1159
we violate the standard interval guarantees in the process::
1160
1161
sage: CIF(-2, RIF(-0.1, 0.1)).argument().str(style='brackets')
1162
'[3.0916342578678501 .. 3.1915510493117365]'
1163
sage: CIF(-2, -0.1).argument()
1164
-3.091634257867851?
1165
"""
1166
if mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im):
1167
1168
if mpfi_is_zero(self.__re) and mpfi_is_zero(self.__im):
1169
raise ValueError, "Can't take the argument of complex zero"
1170
if not mpfi_is_nonpos(self.__re) and not mpfi_is_nonneg(self.__re) \
1171
and not mpfi_is_nonpos(self.__im) and not mpfi_is_nonneg(self.__im):
1172
raise ValueError, "Can't take the argument of interval strictly containing zero"
1173
1174
# Now if we exclude zero from the interval, we know that the
1175
# argument of the remaining points is bounded. Check which
1176
# axes the interval extends along (we can deduce information
1177
# about the quadrants from information about the axes).
1178
1179
which_axes = [False, False, False, False]
1180
if not mpfi_is_nonpos(self.__re):
1181
which_axes[0] = True
1182
if not mpfi_is_nonpos(self.__im):
1183
which_axes[1] = True
1184
if not mpfi_is_nonneg(self.__re):
1185
which_axes[2] = True
1186
if not mpfi_is_nonneg(self.__im):
1187
which_axes[3] = True
1188
1189
lower = None
1190
for i in range(-1, 3):
1191
if which_axes[i % 4] and not which_axes[(i - 1) % 4]:
1192
if lower is not None:
1193
raise ValueError, "Can't take the argument of line-segment interval strictly containing zero"
1194
lower = i
1195
1196
for i in range(lower, lower+4):
1197
if which_axes[i % 4] and not which_axes[(i + 1) % 4]:
1198
upper = i
1199
break
1200
1201
fld = self.parent()._real_field()
1202
return fld.pi() * fld(lower, upper) * fld(0.5)
1203
1204
else:
1205
1206
# OK, we know that the interval is bounded away from zero
1207
# in either the real or the imaginary direction (or both).
1208
# We'll handle the "bounded away in the imaginary direction"
1209
# case first.
1210
1211
fld = self.parent()._real_field()
1212
1213
if mpfi_is_strictly_pos(self.__im):
1214
return (-self.real() / self.imag()).arctan() + fld.pi()/2
1215
if mpfi_is_strictly_neg(self.__im):
1216
return (-self.real() / self.imag()).arctan() - fld.pi()/2
1217
1218
if mpfi_is_strictly_pos(self.__re):
1219
return (self.imag() / self.real()).arctan()
1220
1221
# The only remaining case is that self.__re is strictly
1222
# negative and self.__im contains 0. In that case, we
1223
# return an interval containing pi.
1224
1225
return (self.imag() / self.real()).arctan() + fld.pi()
1226
1227
def arg(self):
1228
"""
1229
Same as :meth:`argument()`.
1230
1231
EXAMPLES::
1232
1233
sage: i = CIF.0
1234
sage: (i^2).arg()
1235
3.141592653589794?
1236
"""
1237
return self.argument()
1238
1239
def crosses_log_branch_cut(self):
1240
"""
1241
Returns ``True`` if this interval crosses the standard branch cut
1242
for :meth:`log()` (and hence for exponentiation) and for argument.
1243
(Recall that this branch cut is infinitesimally below the
1244
negative portion of the real axis.)
1245
1246
EXAMPLES::
1247
1248
sage: z = CIF(1.5, 2.5) - CIF(0, 2.50000000000000001); z
1249
1.5000000000000000? + -1.?e-15*I
1250
sage: z.crosses_log_branch_cut()
1251
False
1252
sage: CIF(-2, RIF(-0.1, 0.1)).crosses_log_branch_cut()
1253
True
1254
"""
1255
1256
if mpfi_is_nonneg(self.__re):
1257
return False
1258
if mpfi_is_nonneg(self.__im):
1259
return False
1260
if mpfi_is_neg(self.__im):
1261
return False
1262
return True
1263
1264
def conjugate(self):
1265
"""
1266
Return the complex conjugate of this complex number.
1267
1268
EXAMPLES::
1269
1270
sage: i = CIF.0
1271
sage: (1+i).conjugate()
1272
1 - 1*I
1273
"""
1274
cdef ComplexIntervalFieldElement x
1275
x = self._new()
1276
1277
mpfi_set(x.__re, self.__re)
1278
mpfi_neg(x.__im, self.__im)
1279
return x
1280
1281
def exp(self):
1282
r"""
1283
Compute `e^z` or `\exp(z)` where `z` is the complex number ``self``.
1284
1285
EXAMPLES::
1286
1287
sage: i = ComplexIntervalField(300).0
1288
sage: z = 1 + i
1289
sage: z.exp()
1290
1.46869393991588515713896759732660426132695673662900872279767567631093696585951213872272450? + 2.28735528717884239120817190670050180895558625666835568093865811410364716018934540926734485?*I
1291
"""
1292
mag = self.real().exp()
1293
theta = self.imag()
1294
re = theta.cos() * mag
1295
im = theta.sin() * mag
1296
return ComplexIntervalFieldElement(self._parent, re, im)
1297
1298
def log(self,base=None):
1299
"""
1300
Complex logarithm of `z`.
1301
1302
.. WARNING::
1303
1304
This does always not use the standard branch cut for complex log!
1305
See the docstring for :meth:`argument()` to see what we do instead.
1306
1307
EXAMPLES::
1308
1309
sage: a = CIF(RIF(3, 4), RIF(13, 14))
1310
sage: a.log().str(style='brackets')
1311
'[2.5908917751460420 .. 2.6782931373360067] + [1.2722973952087170 .. 1.3597029935721503]*I'
1312
sage: a.log().exp().str(style='brackets')
1313
'[2.7954667135098274 .. 4.2819545928390213] + [12.751682453911920 .. 14.237018048974635]*I'
1314
sage: a in a.log().exp()
1315
True
1316
1317
If the interval crosses the negative real axis, then we don't
1318
use the standard branch cut (and we violate the interval guarantees)::
1319
1320
sage: CIF(-3, RIF(-1/4, 1/4)).log().str(style='brackets')
1321
'[1.0986122886681095 .. 1.1020725100903968] + [3.0584514217013518 .. 3.2247338854782349]*I'
1322
sage: CIF(-3, -1/4).log()
1323
1.102072510090397? - 3.058451421701352?*I
1324
1325
Usually if an interval contains zero, we raise an exception::
1326
1327
sage: CIF(RIF(-1,1),RIF(-1,1)).log()
1328
Traceback (most recent call last):
1329
...
1330
ValueError: Can't take the argument of interval strictly containing zero
1331
1332
But we allow the exact input zero::
1333
1334
sage: CIF(0).log()
1335
[-infinity .. -infinity]
1336
1337
If a base is passed from another function, we can accommodate this::
1338
1339
sage: CIF(-1,1).log(2)
1340
0.500000000000000? + 3.399270106370396?*I
1341
"""
1342
if self == 0:
1343
from real_mpfi import RIF
1344
return RIF(0).log()
1345
theta = self.argument()
1346
rho = abs(self)
1347
if base is None or base is 'e':
1348
return ComplexIntervalFieldElement(self._parent, rho.log(), theta)
1349
else:
1350
from real_mpfr import RealNumber, RealField
1351
return ComplexIntervalFieldElement(self._parent, rho.log()/RealNumber(RealField(self.prec()),base).log(), theta/RealNumber(RealField(self.prec()),base).log())
1352
1353
def sqrt(self, bint all=False, **kwds):
1354
"""
1355
The square root function.
1356
1357
.. WARNING::
1358
1359
We approximate the standard branch cut along the negative real
1360
axis, with ``sqrt(-r^2) = i*r`` for positive real ``r``; but if
1361
the interval crosses the negative real axis, we pick the root with
1362
positive imaginary component for the entire interval.
1363
1364
INPUT:
1365
1366
- ``all`` -- bool (default: ``False``); if ``True``, return a list
1367
of all square roots.
1368
1369
EXAMPLES::
1370
1371
sage: CIF(-1).sqrt()^2
1372
-1
1373
sage: sqrt(CIF(2))
1374
1.414213562373095?
1375
sage: sqrt(CIF(-1))
1376
1*I
1377
sage: sqrt(CIF(2-I))^2
1378
2.00000000000000? - 1.00000000000000?*I
1379
sage: CC(-2-I).sqrt()^2
1380
-2.00000000000000 - 1.00000000000000*I
1381
1382
Here, we select a non-principal root for part of the interval, and
1383
violate the standard interval guarantees::
1384
1385
sage: CIF(-5, RIF(-1, 1)).sqrt().str(style='brackets')
1386
'[-0.22250788030178321 .. 0.22250788030178296] + [2.2251857651053086 .. 2.2581008643532262]*I'
1387
sage: CIF(-5, -1).sqrt()
1388
0.222507880301783? - 2.247111425095870?*I
1389
"""
1390
if self.is_zero():
1391
return [self] if all else self
1392
if mpfi_is_zero(self.__im) and not mpfi_has_zero(self.__re):
1393
if mpfr_sgn(&self.__re.left) > 0:
1394
x = ComplexIntervalFieldElement(self._parent, self.real().sqrt(), 0)
1395
else:
1396
x = ComplexIntervalFieldElement(self._parent, 0, (-self.real()).sqrt())
1397
else:
1398
theta = self.argument()/2
1399
rho = abs(self).sqrt()
1400
x = ComplexIntervalFieldElement(self._parent, rho*theta.cos(), rho*theta.sin())
1401
if all:
1402
return [x, -x]
1403
else:
1404
return x
1405
1406
1407
def is_square(self):
1408
r"""
1409
This function always returns ``True`` as `\CC` is algebraically closed.
1410
1411
EXAMPLES::
1412
1413
sage: CIF(2, 1).is_square()
1414
True
1415
"""
1416
return True
1417
1418
# def algdep(self, n, **kwds):
1419
# """
1420
# Returns a polynomial of degree at most $n$ which is approximately
1421
# satisfied by this complex number. Note that the returned polynomial
1422
# need not be irreducible, and indeed usually won't be if $z$ is a good
1423
# approximation to an algebraic number of degree less than $n$.
1424
1425
# ALGORITHM: Uses the PARI C-library algdep command.
1426
1427
# INPUT: Type algdep? at the top level prompt. All additional
1428
# parameters are passed onto the top-level algdep command.
1429
1430
# EXAMPLES::
1431
#
1432
# sage: C = ComplexIntervalField()
1433
# sage: z = (1/2)*(1 + sqrt(3.0) *C.0); z
1434
# 0.500000000000000 + 0.866025403784439*I
1435
# sage: p = z.algdep(5); p
1436
# x^5 + x^2
1437
# sage: p.factor()
1438
# (x + 1) * x^2 * (x^2 - x + 1)
1439
# sage: z^2 - z + 1
1440
# 0.000000000000000111022302462516
1441
# """
1442
# import sage.rings.arith
1443
# return sage.rings.arith.algdep(self,n, **kwds)
1444
1445
# def algebraic_dependancy( self, n ):
1446
# return self.algdep( n )
1447
1448
def make_ComplexIntervalFieldElement0( fld, re, im ):
1449
"""
1450
Construct a :class:`ComplexIntervalFieldElement` for pickling.
1451
1452
TESTS::
1453
1454
sage: a = CIF(1 + I)
1455
sage: loads(dumps(a)) == a # indirect doctest
1456
True
1457
"""
1458
x = ComplexIntervalFieldElement( fld, re, im )
1459
return x
1460
1461
1462
1463
def create_ComplexIntervalFieldElement(s_real, s_imag=None, int pad=0, min_prec=53):
1464
r"""
1465
Return the complex number defined by the strings ``s_real`` and ``s_imag``
1466
as an element of ``ComplexIntervalField(prec=n)``, where `n` potentially
1467
has slightly more (controlled by pad) bits than given by `s`.
1468
1469
INPUT:
1470
1471
- ``s_real`` -- a string that defines a real number (or something whose
1472
string representation defines a number)
1473
1474
- ``s_imag`` -- a string that defines a real number (or something whose
1475
string representation defines a number)
1476
1477
- ``pad`` -- an integer at least 0.
1478
1479
- ``min_prec`` -- number will have at least this many bits of precision,
1480
no matter what.
1481
1482
EXAMPLES::
1483
1484
sage: ComplexIntervalFieldElement('2.3')
1485
2.300000000000000?
1486
sage: ComplexIntervalFieldElement('2.3','1.1')
1487
2.300000000000000? + 1.100000000000000?*I
1488
sage: ComplexIntervalFieldElement(10)
1489
10
1490
sage: ComplexIntervalFieldElement(10,10)
1491
10 + 10*I
1492
sage: ComplexIntervalFieldElement(1.000000000000000000000000000,2)
1493
1 + 2*I
1494
sage: ComplexIntervalFieldElement(1,2.000000000000000000000)
1495
1 + 2*I
1496
sage: ComplexIntervalFieldElement(1.234567890123456789012345, 5.4321098654321987654321)
1497
1.234567890123456789012350? + 5.432109865432198765432000?*I
1498
1499
TESTS:
1500
1501
Make sure we've rounded up ``log(10,2)`` enough to guarantee
1502
sufficient precision (:trac:`10164`). This is a little tricky
1503
because at the time of writing, we don't support intervals long
1504
enough to trip the error. However, at least we can make sure that
1505
we either do it correctly or fail noisily::
1506
1507
sage: c_CIFE = sage.rings.complex_interval.create_ComplexIntervalFieldElement
1508
sage: for kp in range(2,6):
1509
... s = '1.' + '0'*10**kp + '1'
1510
... try:
1511
... assert c_CIFE(s,0).real()-1 != 0
1512
... assert c_CIFE(0,s).imag()-1 != 0
1513
... except TypeError:
1514
... pass
1515
1516
"""
1517
if s_imag is None:
1518
s_imag = 0
1519
1520
if not isinstance(s_real, str):
1521
s_real = str(s_real).strip()
1522
if not isinstance(s_imag, str):
1523
s_imag = str(s_imag).strip()
1524
#if base == 10:
1525
bits = max(int(LOG_TEN_TWO_PLUS_EPSILON*len(s_real)),
1526
int(LOG_TEN_TWO_PLUS_EPSILON*len(s_imag)))
1527
#else:
1528
# bits = max(int(math.log(base,2)*len(s_imag)),int(math.log(base,2)*len(s_imag)))
1529
1530
C = complex_interval_field.ComplexIntervalField(prec=max(bits+pad, min_prec))
1531
return ComplexIntervalFieldElement(C, s_real, s_imag)
1532
1533