1"""Implementation of :class:`ComplexField` class.""" 2 3from __future__ import annotations 4 5import mpmath 6 7from ..core import Float, I 8from ..polys.polyerrors import CoercionFailed 9from .characteristiczero import CharacteristicZero 10from .field import Field 11from .mpelements import MPContext 12from .simpledomain import SimpleDomain 13 14 15class ComplexField(CharacteristicZero, SimpleDomain, Field): 16 """Complex numbers up to the given precision.""" 17 18 rep = 'CC' 19 20 is_ComplexField = True 21 22 is_Exact = False 23 is_Numerical = True 24 25 _default_precision = 53 26 27 @property 28 def has_default_precision(self): 29 return self.precision == self._default_precision 30 31 @property 32 def precision(self): 33 return self._context.prec 34 35 @property 36 def dps(self): 37 return self._context.dps 38 39 @property 40 def tolerance(self): 41 return self._context.tolerance 42 43 def __new__(cls, prec=_default_precision, dps=None, tol=None): 44 context = MPContext(prec, dps, tol) 45 46 obj = super().__new__(cls) 47 48 try: 49 obj.dtype = _complexes_cache[(context.prec, context.tolerance)] 50 except KeyError: 51 _complexes_cache[(context.prec, context.tolerance)] = obj.dtype = context.mpc 52 53 context._parent = obj 54 obj._context = context 55 obj._hash = hash((cls.__name__, obj.dtype, context.prec, context.tolerance)) 56 57 obj.zero = obj.dtype(0) 58 obj.one = obj.dtype(1) 59 60 return obj 61 62 def __getnewargs_ex__(self): 63 return (), {'prec': self.precision, 64 'tol': mpmath.mpf(self.tolerance._mpf_)} 65 66 def __eq__(self, other): 67 return (isinstance(other, ComplexField) 68 and self.precision == other.precision 69 and self.tolerance == other.tolerance) 70 71 def __hash__(self): 72 return self._hash 73 74 def to_expr(self, element): 75 return Float(element.real, self.dps) + I*Float(element.imag, self.dps) 76 77 def from_expr(self, expr): 78 number = expr.evalf(self.dps) 79 real, imag = number.as_real_imag() 80 81 if real.is_Number and imag.is_Number: 82 return self.dtype(real, imag) 83 else: 84 raise CoercionFailed(f'expected complex number, got {expr}') 85 86 def _from_PythonIntegerRing(self, element, base): 87 return self.dtype(element) 88 _from_GMPYIntegerRing = _from_PythonIntegerRing 89 _from_RealField = _from_PythonIntegerRing 90 _from_ComplexField = _from_PythonIntegerRing 91 92 def _from_PythonRationalField(self, element, base): 93 return self.dtype(element.numerator) / element.denominator 94 _from_GMPYRationalField = _from_PythonRationalField 95 96 def _from_AlgebraicField(self, element, base): 97 return self.from_expr(base.to_expr(element)) 98 99 def get_exact(self): 100 from . import QQ 101 return QQ.algebraic_field(I) 102 103 def gcd(self, a, b): 104 return self.one 105 106 def almosteq(self, a, b, tolerance=None): 107 """Check if ``a`` and ``b`` are almost equal.""" 108 return self._context.almosteq(a, b, tolerance) 109 110 def is_normal(self, a): 111 return True 112 113 114_complexes_cache: dict[tuple, ComplexField] = {} 115 116 117CC = ComplexField() 118