-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
realfield.py
132 lines (91 loc) · 3.39 KB
/
realfield.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Implementation of :class:`RealField` class."""
import typing
import mpmath
from ..core import Float
from ..polys.polyerrors import CoercionFailed
from .characteristiczero import CharacteristicZero
from .field import Field
from .mpelements import MPContext
from .simpledomain import SimpleDomain
class RealField(CharacteristicZero, SimpleDomain, Field):
"""Real numbers up to the given precision."""
rep = 'RR'
is_RealField = True
is_Exact = False
is_Numerical = True
_default_precision = 53
@property
def has_default_precision(self):
return self.precision == self._default_precision
@property
def precision(self):
return self._context.prec
@property
def dps(self):
return self._context.dps
@property
def tolerance(self):
return self._context.tolerance
def __new__(cls, prec=_default_precision, dps=None, tol=None):
context = MPContext(prec, dps, tol)
obj = super().__new__(cls)
try:
obj.dtype = _reals_cache[(context.prec, context.tolerance)]
except KeyError:
_reals_cache[(context.prec, context.tolerance)] = obj.dtype = context.mpf
context._parent = obj
obj._context = context
obj._hash = hash((cls.__name__, obj.dtype, context.prec, context.tolerance))
obj.zero = obj.dtype(0)
obj.one = obj.dtype(1)
return obj
def __getnewargs_ex__(self):
return (), {'prec': self.precision,
'tol': mpmath.mpf(self.tolerance._mpf_)}
def __eq__(self, other):
return (isinstance(other, RealField)
and self.precision == other.precision
and self.tolerance == other.tolerance)
def __hash__(self):
return self._hash
def to_expr(self, element):
return Float(element, self.dps)
def from_expr(self, expr):
number = expr.evalf(self.dps)
if number.is_Number:
return self.dtype(number)
else:
raise CoercionFailed(f'expected real number, got {expr}')
def _from_PythonIntegerRing(self, element, base):
return self.dtype(element)
def _from_PythonRationalField(self, element, base):
return self.dtype(element.numerator) / element.denominator
def _from_GMPYIntegerRing(self, element, base):
return self.dtype(int(element))
def _from_GMPYRationalField(self, element, base):
return self.dtype(int(element.numerator)) / int(element.denominator)
def _from_AlgebraicField(self, element, base):
return self.from_expr(base.to_expr(element))
def _from_RealField(self, element, base):
if self == base:
return element
else:
return self.dtype(element)
def _from_ComplexField(self, element, base):
if not element.imag:
return self.dtype(element.real)
def to_rational(self, element, limit=True):
"""Convert a real number to rational number."""
return self._context.to_rational(element, limit)
def get_exact(self):
from . import QQ
return QQ
def gcd(self, a, b):
return self.one
def lcm(self, a, b):
return a*b
def almosteq(self, a, b, tolerance=None):
"""Check if ``a`` and ``b`` are almost equal."""
return self._context.almosteq(a, b, tolerance)
_reals_cache: typing.Dict[tuple, RealField] = {}
RR = RealField()