Path: blob/master/src/sage/rings/complex_interval_field.py
8817 views
r"""1Field of Arbitrary Precision Complex Intervals23AUTHORS:45- William Stein wrote complex_field.py.67- William Stein (2006-01-26): complete rewrite89Then ``complex_field.py`` was copied to ``complex_interval_field.py`` and10heavily modified:1112- Carl Witty (2007-10-24): rewrite for intervals1314- Niles Johnson (2010-08): :Trac:`3893`: ``random_element()``15should pass on ``*args`` and ``**kwds``.1617- Travis Scrimshaw (2012-10-18): Added documentation to get full coverage.1819.. NOTE::2021The :class:`ComplexIntervalField` differs from :class:`ComplexField` in22that :class:`ComplexIntervalField` only gives the digits with exact23precision, then a ``?`` signifying that that digit can have an error of24``+/-1``.25"""2627#################################################################################28# Copyright (C) 2006 William Stein <[email protected]>29#30# Distributed under the terms of the GNU General Public License (GPL)31#32# http://www.gnu.org/licenses/33#*****************************************************************************3435import complex_double36import field37import integer38import weakref39import real_mpfi40import complex_interval41import complex_field42from sage.misc.sage_eval import sage_eval4344from sage.structure.parent_gens import ParentWithGens4546NumberFieldElement_quadratic = None47def late_import():48"""49Import the objects/modules after build (when needed).5051TESTS::5253sage: sage.rings.complex_interval_field.late_import()54"""55global NumberFieldElement_quadratic56if NumberFieldElement_quadratic is None:57import sage.rings.number_field.number_field_element_quadratic as nfeq58NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic5960def is_ComplexIntervalField(x):61"""62Check if ``x`` is a :class:`ComplexIntervalField`.6364EXAMPLES::6566sage: from sage.rings.complex_interval_field import is_ComplexIntervalField as is_CIF67sage: is_CIF(CIF)68True69sage: is_CIF(CC)70False71"""72return isinstance(x, ComplexIntervalField_class)7374cache = {}75def ComplexIntervalField(prec=53, names=None):76"""77Return the complex interval field with real and imaginary parts having78``prec`` *bits* of precision.7980EXAMPLES::8182sage: ComplexIntervalField()83Complex Interval Field with 53 bits of precision84sage: ComplexIntervalField(100)85Complex Interval Field with 100 bits of precision86sage: ComplexIntervalField(100).base_ring()87Real Interval Field with 100 bits of precision88sage: i = ComplexIntervalField(200).gen()89sage: i^290-191sage: i^i920.207879576350761908546955619834978770033877841631769608075136?93"""94global cache95if cache.has_key(prec):96X = cache[prec]97C = X()98if not C is None:99return C100C = ComplexIntervalField_class(prec)101cache[prec] = weakref.ref(C)102return C103104105class ComplexIntervalField_class(field.Field):106"""107The field of complex (interval) numbers.108109EXAMPLES::110111sage: C = ComplexIntervalField(); C112Complex Interval Field with 53 bits of precision113sage: Q = RationalField()114sage: C(1/3)1150.3333333333333334?116sage: C(1/3, 2)1170.3333333333333334? + 2*I118119We can also coerce rational numbers and integers into ``C``, but120coercing a polynomial will raise an exception::121122sage: Q = RationalField()123sage: C(1/3)1240.3333333333333334?125sage: S = PolynomialRing(Q, 'x')126sage: C(S.gen())127Traceback (most recent call last):128...129TypeError: unable to coerce to a ComplexIntervalFieldElement130131This illustrates precision::132133sage: CIF = ComplexIntervalField(10); CIF(1/3, 2/3)1340.334? + 0.667?*I135sage: CIF136Complex Interval Field with 10 bits of precision137sage: CIF = ComplexIntervalField(100); CIF138Complex Interval Field with 100 bits of precision139sage: z = CIF(1/3, 2/3); z1400.333333333333333333333333333334? + 0.666666666666666666666666666667?*I141142We can load and save complex numbers and the complex interval field::143144sage: cmp(loads(z.dumps()), z)1450146sage: loads(CIF.dumps()) == CIF147True148sage: k = ComplexIntervalField(100)149sage: loads(dumps(k)) == k150True151152This illustrates basic properties of a complex (interval) field::153154sage: CIF = ComplexIntervalField(200)155sage: CIF.is_field()156True157sage: CIF.characteristic()1580159sage: CIF.precision()160200161sage: CIF.variable_name()162'I'163sage: CIF == ComplexIntervalField(200)164True165sage: CIF == ComplexIntervalField(53)166False167sage: CIF == 1.1168False169sage: CIF = ComplexIntervalField(53)170171sage: CIF.category()172Category of fields173sage: TestSuite(CIF).run()174"""175def __init__(self, prec=53):176"""177Initialize ``self``.178179EXAMPLES::180sage: ComplexIntervalField()181Complex Interval Field with 53 bits of precision182sage: ComplexIntervalField(200)183Complex Interval Field with 200 bits of precision184"""185self._prec = int(prec)186from sage.categories.fields import Fields187ParentWithGens.__init__(self, self._real_field(), ('I',), False, category = Fields())188189def __reduce__(self):190"""191Used for pickling.192193TESTS::194195sage: loads(dumps(CIF)) == CIF196True197"""198return ComplexIntervalField, (self._prec, )199200def is_exact(self):201"""202The complex interval field is not exact.203204EXAMPLES::205206sage: CIF.is_exact()207False208"""209return False210211def prec(self):212"""213Returns the precision of ``self`` (in bits).214215EXAMPLES::216217sage: CIF.prec()21853219sage: ComplexIntervalField(200).prec()220200221"""222return self._prec223224def to_prec(self, prec):225"""226Returns a complex interval field with the given precision.227228EXAMPLES::229230sage: CIF.to_prec(150)231Complex Interval Field with 150 bits of precision232sage: CIF.to_prec(15)233Complex Interval Field with 15 bits of precision234sage: CIF.to_prec(53) is CIF235True236"""237return ComplexIntervalField(prec)238239def _magma_init_(self, magma):240r"""241Return a string representation of ``self`` in the Magma language.242243EXAMPLES::244245sage: magma(ComplexIntervalField(100)) # optional - magma # indirect doctest246Complex field of precision 30247sage: floor(RR(log(2**100, 10)))24830249"""250return "ComplexField(%s : Bits := true)" % self.prec()251252def _sage_input_(self, sib, coerce):253r"""254Produce an expression which will reproduce this value when evaluated.255256EXAMPLES::257258sage: sage_input(CIF, verify=True)259# Verified260CIF261sage: sage_input(ComplexIntervalField(25), verify=True)262# Verified263ComplexIntervalField(25)264sage: k = (CIF, ComplexIntervalField(37), ComplexIntervalField(1024))265sage: sage_input(k, verify=True)266# Verified267(CIF, ComplexIntervalField(37), ComplexIntervalField(1024))268sage: sage_input((k, k), verify=True)269# Verified270CIF37 = ComplexIntervalField(37)271CIF1024 = ComplexIntervalField(1024)272((CIF, CIF37, CIF1024), (CIF, CIF37, CIF1024))273sage: from sage.misc.sage_input import SageInputBuilder274sage: ComplexIntervalField(2)._sage_input_(SageInputBuilder(), False)275{call: {atomic:ComplexIntervalField}({atomic:2})}276"""277if self.prec() == 53:278return sib.name('CIF')279280v = sib.name('ComplexIntervalField')(sib.int(self.prec()))281name = 'CIF%d' % self.prec()282sib.cache(self, v, name)283return v284285precision = prec286287# very useful to cache this.288def _real_field(self):289"""290Return the underlying :class:`RealIntervalField`.291292EXAMPLES::293294sage: R = CIF._real_field(); R295Real Interval Field with 53 bits of precision296sage: ComplexIntervalField(200)._real_field()297Real Interval Field with 200 bits of precision298sage: CIF._real_field() is R299True300"""301try:302return self.__real_field303except AttributeError:304self.__real_field = real_mpfi.RealIntervalField(self._prec)305return self.__real_field306307def _middle_field(self):308"""309Return the corresponding :class:`ComplexField` with the same precision310as ``self``.311312EXAMPLES::313314sage: CIF._middle_field()315Complex Field with 53 bits of precision316sage: ComplexIntervalField(200)._middle_field()317Complex Field with 200 bits of precision318"""319try:320return self.__middle_field321except AttributeError:322self.__middle_field = complex_field.ComplexField(self._prec)323return self.__middle_field324325def __cmp__(self, other):326"""327Compare ``other`` to ``self``.328329If ``other`` is not a :class:`ComplexIntervalField_class`, compare by330type, otherwise compare by precision.331332EXAMPLES::333334sage: cmp(CIF, ComplexIntervalField(200))335-1336sage: cmp(CIF, CC) != 0337True338sage: cmp(CIF, CIF)3390340"""341if not isinstance(other, ComplexIntervalField_class):342return cmp(type(self), type(other))343return cmp(self._prec, other._prec)344345def __call__(self, x, im=None):346"""347Construct an element.348349EXAMPLES::350351sage: CIF(2) # indirect doctest3522353sage: CIF(CIF.0)3541*I355sage: CIF('1+I')3561 + 1*I357sage: CIF(2,3)3582 + 3*I359sage: CIF(pi, e)3603.141592653589794? + 2.718281828459046?*I361"""362if im is None:363if isinstance(x, complex_interval.ComplexIntervalFieldElement) and x.parent() is self:364return x365elif isinstance(x, complex_double.ComplexDoubleElement):366return complex_interval.ComplexIntervalFieldElement(self, x.real(), x.imag())367elif isinstance(x, str):368# TODO: this is probably not the best and most369# efficient way to do this. -- Martin Albrecht370return complex_interval.ComplexIntervalFieldElement(self,371sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))372373late_import()374if isinstance(x, NumberFieldElement_quadratic) and list(x.parent().polynomial()) == [1, 0, 1]:375(re, im) = list(x)376return complex_interval.ComplexIntervalFieldElement(self, re, im)377378try:379return x._complex_mpfi_( self )380except AttributeError:381pass382try:383return x._complex_mpfr_field_( self )384except AttributeError:385pass386return complex_interval.ComplexIntervalFieldElement(self, x, im)387388def _coerce_impl(self, x):389"""390Return the canonical coerce of ``x`` into this complex field, if it is391defined, otherwise raise a ``TypeError``.392393The rings that canonically coerce to the MPFI complex field are:394395* this MPFI complex field, or any other of higher precision396397* anything that canonically coerces to the mpfi real field with this398precision399400EXAMPLES::401402sage: CIF((2,1)) + 2 + I # indirect doctest4034 + 2*I404sage: x = ComplexField(25)(2)405sage: x4062.000000407sage: CIF((2,1)) + x408Traceback (most recent call last):409...410TypeError: unsupported operand parent(s) for '+': 'Complex Interval411Field with 53 bits of precision' and 'Complex Field with 25 bits of precision'412"""413try:414K = x.parent()415if is_ComplexIntervalField(K) and K._prec >= self._prec:416return self(x)417# elif complex_field.is_ComplexField(K) and K.prec() >= self._prec:418# return self(x)419except AttributeError:420pass421if hasattr(x, '_complex_mpfr_field_') or hasattr(x, '_complex_mpfi_'):422return self(x)423return self._coerce_try(x, self._real_field())424425def _repr_(self):426"""427Return a string representation of ``self``.428429EXAMPLES::430431sage: ComplexIntervalField() # indirect doctest432Complex Interval Field with 53 bits of precision433sage: ComplexIntervalField(100) # indirect doctest434Complex Interval Field with 100 bits of precision435"""436return "Complex Interval Field with %s bits of precision"%self._prec437438def _latex_(self):439r"""440Return a latex representation of ``self``.441442EXAMPLES::443444sage: latex(ComplexIntervalField()) # indirect doctest445\Bold{C}446"""447return "\\Bold{C}"448449def characteristic(self):450"""451Return the characteristic of the complex (interval) field, which is 0.452453EXAMPLES::454455sage: CIF.characteristic()4560457"""458return integer.Integer(0)459460def gen(self, n=0):461"""462Return the generator of the complex (interval) field.463464EXAMPLES::465466sage: CIF.04671*I468sage: CIF.gen(0)4691*I470"""471if n != 0:472raise IndexError, "n must be 0"473return complex_interval.ComplexIntervalFieldElement(self, 0, 1)474475def random_element(self, *args, **kwds):476"""477Create a random element of ``self``.478479This simply chooses the real and imaginary part randomly, passing480arguments and keywords to the underlying real interval field.481482EXAMPLES::483484sage: CIF.random_element()4850.15363619378561300? - 0.50298737524751780?*I486sage: CIF.random_element(10, 20)48718.047949821611205? + 10.255727028308920?*I488489Passes extra positional or keyword arguments through::490491sage: CIF.random_element(max=0, min=-5)492-0.079017286535590259? - 2.8712089896087117?*I493"""494return self._real_field().random_element(*args, **kwds) \495+ self.gen() * self._real_field().random_element(*args, **kwds)496497def is_field(self, proof = True):498"""499Return ``True``, since the complex numbers are a field.500501EXAMPLES::502503sage: CIF.is_field()504True505"""506return True507508def is_finite(self):509"""510Return ``False``, since the complex numbers are infinite.511512EXAMPLES::513514sage: CIF.is_finite()515False516"""517return False518519def pi(self):520r"""521Returns `\pi` as an element in the complex (interval) field.522523EXAMPLES::524525sage: ComplexIntervalField(100).pi()5263.14159265358979323846264338328?527"""528return self(self._real_field().pi())529530def ngens(self):531r"""532The number of generators of this complex (interval) field as an533`\RR`-algebra.534535There is one generator, namely ``sqrt(-1)``.536537EXAMPLES::538539sage: CIF.ngens()5401541"""542return 1543544def zeta(self, n=2):545r"""546Return a primitive `n`-th root of unity.547548.. TODO::549550Implement :class:`ComplexIntervalFieldElement` multiplicative order551and set this output to have multiplicative order ``n``.552553INPUT:554555- ``n`` -- an integer (default: 2)556557OUTPUT:558559A complex `n`-th root of unity.560561EXAMPLES::562563sage: CIF.zeta(2)564-1565sage: CIF.zeta(5)5660.309016994374948? + 0.9510565162951536?*I567"""568from integer import Integer569n = Integer(n)570if n == 1:571x = self(1)572elif n == 2:573x = self(-1)574elif n >= 3:575# Use De Moivre576# e^(2*pi*i/n) = cos(2pi/n) + i *sin(2pi/n)577RR = self._real_field()578pi = RR.pi()579z = 2*pi/n580x = complex_interval.ComplexIntervalFieldElement(self, z.cos(), z.sin())581# Uncomment after implemented582#x._set_multiplicative_order( n )583return x584585def scientific_notation(self, status=None):586"""587Set or return the scientific notation printing flag.588589If this flag is ``True`` then complex numbers with this space as parent590print using scientific notation.591592EXAMPLES::593594sage: CIF((0.025, 2))5950.025000000000000002? + 2*I596sage: CIF.scientific_notation(True)597sage: CIF((0.025, 2))5982.5000000000000002?e-2 + 2*I599sage: CIF.scientific_notation(False)600sage: CIF((0.025, 2))6010.025000000000000002? + 2*I602"""603return self._real_field().scientific_notation(status)604605606607608