Path: blob/master/sage/rings/complex_interval_field.py
4057 views
r"""1Field of Arbitrary Precision Complex Intervals23AUTHORS:45- William Stein wrote complex_field.py.6-- William Stein (2006-01-26): complete rewrite7Then complex_field.py was copied to complex_interval_field.py and8heavily modified:9-- Carl Witty (2007-10-24): rewrite for intervals1011-- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.1213"""1415#################################################################################16# Copyright (C) 2006 William Stein <[email protected]>17#18# Distributed under the terms of the GNU General Public License (GPL)19#20# http://www.gnu.org/licenses/21#*****************************************************************************2223import complex_double24import field25import integer26import weakref27import real_mpfi28import complex_interval29import complex_field30from sage.misc.sage_eval import sage_eval3132from sage.structure.parent_gens import ParentWithGens3334NumberFieldElement_quadratic = None35def late_import():36global NumberFieldElement_quadratic37if NumberFieldElement_quadratic is None:38import sage.rings.number_field.number_field_element_quadratic as nfeq39NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic4041def is_ComplexIntervalField(x):42return isinstance(x, ComplexIntervalField_class)4344cache = {}45def ComplexIntervalField(prec=53, names=None):46"""47Return the complex field with real and imaginary parts having prec48*bits* of precision.4950EXAMPLES:51sage: ComplexIntervalField()52Complex Interval Field with 53 bits of precision53sage: ComplexIntervalField(100)54Complex Interval Field with 100 bits of precision55sage: ComplexIntervalField(100).base_ring()56Real Interval Field with 100 bits of precision57sage: i = ComplexIntervalField(200).gen()58sage: i^259-160sage: i^i610.207879576350761908546955619834978770033877841631769608075136?62"""63global cache64if cache.has_key(prec):65X = cache[prec]66C = X()67if not C is None:68return C69C = ComplexIntervalField_class(prec)70cache[prec] = weakref.ref(C)71return C727374class ComplexIntervalField_class(field.Field):75"""76The field of complex numbers.7778EXAMPLES:79sage: C = ComplexIntervalField(); C80Complex Interval Field with 53 bits of precision81sage: Q = RationalField()82sage: C(1/3)830.3333333333333334?84sage: C(1/3, 2)850.3333333333333334? + 2*I8687We can also coerce rational numbers and integers into C, but88coercing a polynomial will raise an exception.8990sage: Q = RationalField()91sage: C(1/3)920.3333333333333334?93sage: S = PolynomialRing(Q, 'x')94sage: C(S.gen())95Traceback (most recent call last):96...97TypeError: unable to coerce to a ComplexIntervalFieldElement9899This illustrates precision.100sage: CIF = ComplexIntervalField(10); CIF(1/3, 2/3)1010.334? + 0.667?*I102sage: CIF103Complex Interval Field with 10 bits of precision104sage: CIF = ComplexIntervalField(100); CIF105Complex Interval Field with 100 bits of precision106sage: z = CIF(1/3, 2/3); z1070.333333333333333333333333333334? + 0.666666666666666666666666666667?*I108109We can load and save complex numbers and the complex field.110sage: cmp(loads(z.dumps()), z)1110112sage: loads(CIF.dumps()) == CIF113True114sage: k = ComplexIntervalField(100)115sage: loads(dumps(k)) == k116True117118This illustrates basic properties of a complex field.119sage: CIF = ComplexIntervalField(200)120sage: CIF.is_field()121True122sage: CIF.characteristic()1230124sage: CIF.precision()125200126sage: CIF.variable_name()127'I'128sage: CIF == ComplexIntervalField(200)129True130sage: CIF == ComplexIntervalField(53)131False132sage: CIF == 1.1133False134sage: CIF = ComplexIntervalField(53)135136sage: CIF.category()137Category of fields138sage: TestSuite(CIF).run()139"""140def __init__(self, prec=53):141self._prec = int(prec)142from sage.categories.fields import Fields143ParentWithGens.__init__(self, self._real_field(), ('I',), False, category = Fields())144145def __reduce__(self):146"""147Used for pickling.148149TESTS::150loads(dumps(CIF)) == CIF151"""152return ComplexIntervalField, (self._prec, )153154def is_exact(self):155"""156The complex interval field is not exact.157158EXAMPLES::159160sage: CIF.is_exact()161False162"""163return False164165def prec(self):166"""167Returns the precision of self (in bits).168169EXAMPLES::170171sage: CIF.prec()17253173sage: ComplexIntervalField(200).prec()174200175"""176return self._prec177178def to_prec(self, prec):179"""180Returns a complex interval field with the given precision.181182EXAMPLES::183184sage: CIF.to_prec(150)185Complex Interval Field with 150 bits of precision186sage: CIF.to_prec(15)187Complex Interval Field with 15 bits of precision188sage: CIF.to_prec(53) is CIF189True190"""191return ComplexIntervalField(prec)192193def _magma_init_(self, magma):194r"""195Return a string representation of self in the Magma language.196197EXAMPLES:198sage: magma(ComplexIntervalField(100)) # optional - magma199Complex field of precision 30200sage: floor(RR(log(2**100, 10)))20130202"""203return "ComplexField(%s : Bits := true)" % self.prec()204205def _sage_input_(self, sib, coerce):206r"""207Produce an expression which will reproduce this value when evaluated.208209EXAMPLES:210sage: sage_input(CIF, verify=True)211# Verified212CIF213sage: sage_input(ComplexIntervalField(25), verify=True)214# Verified215ComplexIntervalField(25)216sage: k = (CIF, ComplexIntervalField(37), ComplexIntervalField(1024))217sage: sage_input(k, verify=True)218# Verified219(CIF, ComplexIntervalField(37), ComplexIntervalField(1024))220sage: sage_input((k, k), verify=True)221# Verified222CIF37 = ComplexIntervalField(37)223CIF1024 = ComplexIntervalField(1024)224((CIF, CIF37, CIF1024), (CIF, CIF37, CIF1024))225sage: from sage.misc.sage_input import SageInputBuilder226sage: ComplexIntervalField(2)._sage_input_(SageInputBuilder(), False)227{call: {atomic:ComplexIntervalField}({atomic:2})}228"""229if self.prec() == 53:230return sib.name('CIF')231232v = sib.name('ComplexIntervalField')(sib.int(self.prec()))233name = 'CIF%d' % self.prec()234sib.cache(self, v, name)235return v236237precision = prec238239240# very useful to cache this.241def _real_field(self):242try:243return self.__real_field244except AttributeError:245self.__real_field = real_mpfi.RealIntervalField(self._prec)246return self.__real_field247248def _middle_field(self):249try:250return self.__middle_field251except AttributeError:252self.__middle_field = complex_field.ComplexField(self._prec)253return self.__middle_field254255def __cmp__(self, other):256if not isinstance(other, ComplexIntervalField_class):257return cmp(type(self), type(other))258return cmp(self._prec, other._prec)259260def __call__(self, x, im=None):261"""262EXAMPLES:263sage: CIF(2)2642265sage: CIF(CIF.0)2661*I267sage: CIF('1+I')2681 + 1*I269sage: CIF(2,3)2702 + 3*I271sage: CIF(pi, e)2723.141592653589794? + 2.718281828459046?*I273"""274if im is None:275if isinstance(x, complex_interval.ComplexIntervalFieldElement) and x.parent() is self:276return x277elif isinstance(x, complex_double.ComplexDoubleElement):278return complex_interval.ComplexIntervalFieldElement(self, x.real(), x.imag())279elif isinstance(x, str):280# TODO: this is probably not the best and most281# efficient way to do this. -- Martin Albrecht282return complex_interval.ComplexIntervalFieldElement(self,283sage_eval(x.replace(' ',''), locals={"I":self.gen(),"i":self.gen()}))284285late_import()286if isinstance(x, NumberFieldElement_quadratic) and list(x.parent().polynomial()) == [1, 0, 1]:287(re, im) = list(x)288return complex_interval.ComplexIntervalFieldElement(self, re, im)289290try:291return x._complex_mpfi_( self )292except AttributeError:293pass294try:295return x._complex_mpfr_field_( self )296except AttributeError:297pass298return complex_interval.ComplexIntervalFieldElement(self, x, im)299300def _coerce_impl(self, x):301"""302Return the canonical coerce of x into this complex field, if it is defined,303otherwise raise a TypeError.304305The rings that canonically coerce to the MPFI complex field are:306* this MPFI complex field, or any other of higher precision307* anything that canonically coerces to the mpfi real field with this prec308"""309try:310K = x.parent()311if is_ComplexIntervalField(K) and K._prec >= self._prec:312return self(x)313# elif complex_field.is_ComplexField(K) and K.prec() >= self._prec:314# return self(x)315except AttributeError:316pass317if hasattr(x, '_complex_mpfr_field_') or hasattr(x, '_complex_mpfi_'):318return self(x)319return self._coerce_try(x, self._real_field())320321def _repr_(self):322return "Complex Interval Field with %s bits of precision"%self._prec323324def _latex_(self):325return "\\Bold{C}"326327def characteristic(self):328return integer.Integer(0)329330def gen(self, n=0):331if n != 0:332raise IndexError, "n must be 0"333return complex_interval.ComplexIntervalFieldElement(self, 0, 1)334335def random_element(self, *args, **kwds):336"""337Create a random element of self. Simply chooses the real and338imaginary part randomly, passing arguments and keywords to the339underlying real interval field.340341EXAMPLES::342343sage: CIF.random_element()3440.15363619378561300? - 0.50298737524751780?*I345sage: CIF.random_element(10, 20)34618.047949821611205? + 10.255727028308920?*I347348Passes extra positional or keyword arguments through::349350sage: CIF.random_element(max=0, min=-5)351-0.079017286535590259? - 2.8712089896087117?*I352"""353return self._real_field().random_element(*args, **kwds) \354+ self.gen() * self._real_field().random_element(*args, **kwds)355356def is_field(self, proof = True):357"""358Return True, since the complex numbers are a field.359360EXAMPLES:361sage: CIF.is_field()362True363"""364return True365366def is_finite(self):367"""368Return False, since the complex numbers are infinite.369370EXAMPLES:371sage: CIF.is_finite()372False373"""374return False375376def pi(self):377return self(self._real_field().pi())378379def ngens(self):380return 1381382def zeta(self, n=2):383"""384Return a primitive $n$-th root of unity.385386INPUT:387n -- an integer (default: 2)388389OUTPUT:390a complex n-th root of unity.391"""392from integer import Integer393n = Integer(n)394if n == 1:395x = self(1)396elif n == 2:397x = self(-1)398elif n >= 3:399# Use De Moivre400# e^(2*pi*i/n) = cos(2pi/n) + i *sin(2pi/n)401RR = self._real_field()402pi = RR.pi()403z = 2*pi/n404x = complex_interval.ComplexIntervalFieldElement(self, z.cos(), z.sin())405x._set_multiplicative_order( n )406return x407408def scientific_notation(self, status=None):409return self._real_field().scientific_notation(status)410411412413414