Arbitrary Precision Complex Intervals
This is a simple complex interval package, using intervals which are axis-aligned rectangles in the complex plane. It has very few special functions, and it does not use any special tricks to keep the size of the intervals down.
AUTHORS:
These authors wrote complex_number.pyx:
Then complex_number.pyx was copied to complex_interval.pyx and heavily modified:
Todo
Implement ComplexIntervalFieldElement multiplicative order similar to ComplexNumber multiplicative order with _set_multiplicative_order(n) and ComplexNumber.multiplicative_order() methods.
Bases: sage.structure.element.FieldElement
A complex interval.
EXAMPLES:
sage: I = CIF.gen()
sage: b = 1.5 + 2.5*I
sage: TestSuite(b).run()
Same as argument().
EXAMPLES:
sage: i = CIF.0
sage: (i^2).arg()
3.141592653589794?
The argument (angle) of the complex number, normalized
so that .
We raise a ValueError if the interval strictly contains 0, or if the interval contains only 0.
Warning
We do not always use the standard branch cut for
argument! If the interval crosses the negative real axis,
then the argument will be an interval whose lower bound is
less than and whose upper bound is more than
; in
effect, we move the branch cut away from the interval.
EXAMPLES:
sage: i = CIF.0
sage: (i^2).argument()
3.141592653589794?
sage: (1+i).argument()
0.785398163397449?
sage: i.argument()
1.570796326794897?
sage: (-i).argument()
-1.570796326794897?
sage: (RR('-0.001') - i).argument()
-1.571796326461564?
sage: CIF(2).argument()
0
sage: CIF(-2).argument()
3.141592653589794?
Here we see that if the interval crosses the negative real
axis, then the argument can exceed , and we
we violate the standard interval guarantees in the process:
sage: CIF(-2, RIF(-0.1, 0.1)).argument().str(style='brackets')
'[3.0916342578678501 .. 3.1915510493117365]'
sage: CIF(-2, -0.1).argument()
-3.091634257867851?
Returns the bisection of self into four intervals whose union is self and intersection is center().
EXAMPLES:
sage: z = CIF(RIF(2, 3), RIF(-5, -4))
sage: z.bisection()
(3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I, 3.? - 5.?*I)
sage: for z in z.bisection():
... print z.real().endpoints(), z.imag().endpoints()
(2.00000000000000, 2.50000000000000) (-5.00000000000000, -4.50000000000000)
(2.50000000000000, 3.00000000000000) (-5.00000000000000, -4.50000000000000)
(2.00000000000000, 2.50000000000000) (-4.50000000000000, -4.00000000000000)
(2.50000000000000, 3.00000000000000) (-4.50000000000000, -4.00000000000000)
sage: z = CIF(RIF(sqrt(2), sqrt(3)), RIF(e, pi))
sage: a, b, c, d = z.bisection()
sage: a.intersection(b).intersection(c).intersection(d) == CIF(z.center())
True
sage: zz = a.union(b).union(c).union(c)
sage: zz.real().endpoints() == z.real().endpoints()
True
sage: zz.imag().endpoints() == z.imag().endpoints()
True
Returns the closest floating-point approximation to the center of the interval.
EXAMPLES:
sage: CIF(RIF(1, 2), RIF(3, 4)).center()
1.50000000000000 + 3.50000000000000*I
Return the complex conjugate of this complex number.
EXAMPLES:
sage: i = CIF.0
sage: (1+i).conjugate()
1 - 1*I
Returns True if self is an interval containing zero.
EXAMPLES:
sage: CIF(0).contains_zero()
True
sage: CIF(RIF(-1, 1), 1).contains_zero()
False
Returns True if this interval crosses the standard branch cut for log() (and hence for exponentiation) and for argument. (Recall that this branch cut is infinitesimally below the negative portion of the real axis.)
EXAMPLES:
sage: z = CIF(1.5, 2.5) - CIF(0, 2.50000000000000001); z
1.5000000000000000? + -1.?e-15*I
sage: z.crosses_log_branch_cut()
False
sage: CIF(-2, RIF(-0.1, 0.1)).crosses_log_branch_cut()
True
Returns a somewhat-arbitrarily defined “diameter” for this interval.
The diameter of an interval is the maximum of the diameter of the real and imaginary components, where diameter on a real interval is defined as absolute diameter if the interval contains zero, and relative diameter otherwise.
EXAMPLES:
sage: CIF(RIF(-1, 1), RIF(13, 17)).diameter()
2.00000000000000
sage: CIF(RIF(-0.1, 0.1), RIF(13, 17)).diameter()
0.266666666666667
sage: CIF(RIF(-1, 1), 15).diameter()
2.00000000000000
Compute or
where
is the complex number self.
EXAMPLES:
sage: i = ComplexIntervalField(300).0
sage: z = 1 + i
sage: z.exp()
1.46869393991588515713896759732660426132695673662900872279767567631093696585951213872272450? + 2.28735528717884239120817190670050180895558625666835568093865811410364716018934540926734485?*I
Return imaginary part of self.
EXAMPLES:
sage: i = ComplexIntervalField(100).0
sage: z = 2 + 3*i
sage: x = z.imag(); x
3
sage: x.parent()
Real Interval Field with 100 bits of precision
Returns the intersection of the two complex intervals self and other.
EXAMPLES:
sage: CIF(RIF(1, 3), RIF(1, 3)).intersection(CIF(RIF(2, 4), RIF(2, 4))).str(style='brackets')
'[2.0000000000000000 .. 3.0000000000000000] + [2.0000000000000000 .. 3.0000000000000000]*I'
sage: CIF(RIF(1, 2), RIF(1, 3)).intersection(CIF(RIF(3, 4), RIF(2, 4)))
Traceback (most recent call last):
...
ValueError: intersection of non-overlapping intervals
Returns whether this complex interval is exact (i.e. contains exactly one complex value).
EXAMPLES:
sage: CIF(3).is_exact()
True
sage: CIF(0, 2).is_exact()
True
sage: CIF(-4, 0).sqrt().is_exact()
True
sage: CIF(-5, 0).sqrt().is_exact()
False
sage: CIF(0, 2*pi).is_exact()
False
sage: CIF(e).is_exact()
False
sage: CIF(1e100).is_exact()
True
sage: (CIF(1e100) + 1).is_exact()
False
This function always returns True as is algebraically closed.
EXAMPLES:
sage: CIF(2, 1).is_square()
True
Complex logarithm of .
Warning
This does always not use the standard branch cut for complex log! See the docstring for argument() to see what we do instead.
EXAMPLES:
sage: a = CIF(RIF(3, 4), RIF(13, 14))
sage: a.log().str(style='brackets')
'[2.5908917751460420 .. 2.6782931373360067] + [1.2722973952087170 .. 1.3597029935721503]*I'
sage: a.log().exp().str(style='brackets')
'[2.7954667135098274 .. 4.2819545928390213] + [12.751682453911920 .. 14.237018048974635]*I'
sage: a in a.log().exp()
True
If the interval crosses the negative real axis, then we don’t use the standard branch cut (and we violate the interval guarantees):
sage: CIF(-3, RIF(-1/4, 1/4)).log().str(style='brackets')
'[1.0986122886681095 .. 1.1020725100903968] + [3.0584514217013518 .. 3.2247338854782349]*I'
sage: CIF(-3, -1/4).log()
1.102072510090397? - 3.058451421701352?*I
Usually if an interval contains zero, we raise an exception:
sage: CIF(RIF(-1,1),RIF(-1,1)).log()
Traceback (most recent call last):
...
ValueError: Can't take the argument of interval strictly containing zero
But we allow the exact input zero:
sage: CIF(0).log()
[-infinity .. -infinity]
If a base is passed from another function, we can accommodate this:
sage: CIF(-1,1).log(2)
0.500000000000000? + 3.399270106370396?*I
Returns the norm of this complex number.
If is a complex number, then the norm of
is defined as
the product of
and its complex conjugate:
The norm of a complex number is different from its absolute value.
The absolute value of a complex number is defined to be the square
root of its norm. A typical use of the complex norm is in the
integral domain of Gaussian integers, where the norm of
each Gaussian integer
is defined as its complex norm.
EXAMPLES:
sage: CIF(2, 1).norm()
5
sage: CIF(1, -2).norm()
5
Returns True if self and other are intervals with at least one value in common.
EXAMPLES:
sage: CIF(0).overlaps(CIF(RIF(0, 1), RIF(-1, 0)))
True
sage: CIF(1).overlaps(CIF(1, 1))
False
Plot a complex interval as a rectangle.
EXAMPLES:
sage: sum(plot(CIF(RIF(1/k, 1/k), RIF(-k, k))) for k in [1..10])
Graphics object consisting of 20 graphics primitives
Exact and nearly exact points are still visible:
sage: plot(CIF(pi, 1), color='red') + plot(CIF(1, e), color='purple') + plot(CIF(-1, -1))
Graphics object consisting of 6 graphics primitives
A demonstration that acts chaotically on
:
sage: z = CIF(0, 2*pi/1000).exp()
sage: g = Graphics()
sage: for i in range(40):
... z = z^2
... g += z.plot(color=(1./(40-i), 0, 1))
...
sage: g
Graphics object consisting of 80 graphics primitives
Return precision of this complex number.
EXAMPLES:
sage: i = ComplexIntervalField(2000).0
sage: i.prec()
2000
Return real part of self.
EXAMPLES:
sage: i = ComplexIntervalField(100).0
sage: z = 2 + 3*i
sage: x = z.real(); x
2
sage: x.parent()
Real Interval Field with 100 bits of precision
The square root function.
Warning
We approximate the standard branch cut along the negative real axis, with sqrt(-r^2) = i*r for positive real r; but if the interval crosses the negative real axis, we pick the root with positive imaginary component for the entire interval.
INPUT:
EXAMPLES:
sage: CIF(-1).sqrt()^2
-1
sage: sqrt(CIF(2))
1.414213562373095?
sage: sqrt(CIF(-1))
1*I
sage: sqrt(CIF(2-I))^2
2.00000000000000? - 1.00000000000000?*I
sage: CC(-2-I).sqrt()^2
-2.00000000000000 - 1.00000000000000*I
Here, we select a non-principal root for part of the interval, and violate the standard interval guarantees:
sage: CIF(-5, RIF(-1, 1)).sqrt().str(style='brackets')
'[-0.22250788030178321 .. 0.22250788030178296] + [2.2251857651053086 .. 2.2581008643532262]*I'
sage: CIF(-5, -1).sqrt()
0.222507880301783? - 2.247111425095870?*I
Returns a string representation of self.
EXAMPLES:
sage: CIF(1.5).str()
'1.5000000000000000?'
sage: CIF(1.5, 2.5).str()
'1.5000000000000000? + 2.5000000000000000?*I'
sage: CIF(1.5, -2.5).str()
'1.5000000000000000? - 2.5000000000000000?*I'
sage: CIF(0, -2.5).str()
'-2.5000000000000000?*I'
sage: CIF(1.5).str(base=3)
'1.1111111111111111111111111111111112?'
sage: CIF(1, pi).str(style='brackets')
'[1.0000000000000000 .. 1.0000000000000000] + [3.1415926535897931 .. 3.1415926535897936]*I'
See also
Returns the smallest complex interval including the two complex intervals self and other.
EXAMPLES:
sage: CIF(0).union(CIF(5, 5)).str(style='brackets')
'[0.00000000000000000 .. 5.0000000000000000] + [0.00000000000000000 .. 5.0000000000000000]*I'
Return the complex number defined by the strings s_real and s_imag
as an element of ComplexIntervalField(prec=n), where potentially
has slightly more (controlled by pad) bits than given by
.
INPUT:
EXAMPLES:
sage: ComplexIntervalFieldElement('2.3')
2.300000000000000?
sage: ComplexIntervalFieldElement('2.3','1.1')
2.300000000000000? + 1.100000000000000?*I
sage: ComplexIntervalFieldElement(10)
10
sage: ComplexIntervalFieldElement(10,10)
10 + 10*I
sage: ComplexIntervalFieldElement(1.000000000000000000000000000,2)
1 + 2*I
sage: ComplexIntervalFieldElement(1,2.000000000000000000000)
1 + 2*I
sage: ComplexIntervalFieldElement(1.234567890123456789012345, 5.4321098654321987654321)
1.234567890123456789012350? + 5.432109865432198765432000?*I
TESTS:
Make sure we’ve rounded up log(10,2) enough to guarantee sufficient precision (trac ticket #10164). This is a little tricky because at the time of writing, we don’t support intervals long enough to trip the error. However, at least we can make sure that we either do it correctly or fail noisily:
sage: c_CIFE = sage.rings.complex_interval.create_ComplexIntervalFieldElement
sage: for kp in range(2,6):
... s = '1.' + '0'*10**kp + '1'
... try:
... assert c_CIFE(s,0).real()-1 != 0
... assert c_CIFE(0,s).imag()-1 != 0
... except TypeError:
... pass
Check if x is a ComplexIntervalFieldElement.
EXAMPLES:
sage: from sage.rings.complex_interval import is_ComplexIntervalFieldElement as is_CIFE
sage: is_CIFE(CIF(2))
True
sage: is_CIFE(CC(2))
False
Construct a ComplexIntervalFieldElement for pickling.
TESTS:
sage: a = CIF(1 + I)
sage: loads(dumps(a)) == a # indirect doctest
True