88
99import mpmath
1010import sympy
11+ from sympy .core import numbers as sympy_numbers
1112
1213from mathics .core .element import BoxElementMixin , ImmutableValueMixin
1314from mathics .core .number import (
@@ -108,7 +109,7 @@ def is_numeric(self, evaluation=None) -> bool:
108109
109110 def to_mpmath (self , precision : Optional [int ] = None ) -> mpmath .ctx_mp_python .mpf :
110111 """
111- Convert self._value to an mpmath number with precision ``precision``
112+ Convert self.value to an mpmath number with precision ``precision``
112113 If ``precision`` is None, use mpmath's default precision.
113114
114115 A mpmath number is the default implementation for Number.
@@ -139,8 +140,9 @@ def round(self, d: Optional[int] = None) -> "Number":
139140
140141 @property
141142 def value (self ) -> T :
142- """
143- Equivalent value in Python's native datatype.
143+ """Equivalent value in either SymPy's or Python's native
144+ datatype if that exist. Note the SymPy value
145+ and the Python value might be the same thing.
144146 """
145147 return self ._value
146148
@@ -195,6 +197,8 @@ class Integer(Number[int]):
195197 # dictionary's value is the corresponding Mathics Integer object.
196198 _integers : Dict [Any , "Integer" ] = {}
197199
200+ _sympy : sympy_numbers .Integer
201+
198202 # We use __new__ here to ensure that two Integer's that have the same value
199203 # return the same object, and to set an object hash value.
200204 # Consider also @lru_cache, and mechanisms for limiting and
@@ -209,6 +213,7 @@ def __new__(cls, value) -> "Integer":
209213
210214 # Cache object so we don't allocate again.
211215 self ._integers [value ] = self
216+ self ._sympy = sympy_numbers .Integer (value )
212217
213218 # Set a value for self.__hash__() once so that every time
214219 # it is used this is fast. Note that in contrast to the
@@ -318,12 +323,16 @@ def round(self, d: Optional[int] = None) -> Union["MachineReal", "PrecisionReal"
318323 d = MACHINE_PRECISION_VALUE
319324 return PrecisionReal (sympy .Float (self .value , d ))
320325
321- def to_sympy (self , ** _ ):
322- return sympy .Integer (self ._value )
326+ @property
327+ def sympy (self ) -> sympy_numbers .Integer :
328+ return self ._sympy
323329
324- def sameQ (self , other ) -> bool :
330+ def to_sympy (self , ** _ ) -> sympy_numbers .Integer :
331+ return self .sympy
332+
333+ def sameQ (self , rhs ) -> bool :
325334 """Mathics SameQ"""
326- return isinstance (other , Integer ) and self ._value == other .value
335+ return isinstance (rhs , Integer ) and self ._value == rhs .value
327336
328337 def do_copy (self ) -> "Integer" :
329338 return Integer (self ._value )
@@ -492,25 +501,25 @@ def make_boxes(self, form):
492501 def is_zero (self ) -> bool :
493502 return self .value == 0.0
494503
495- def sameQ (self , other ) -> bool :
504+ def sameQ (self , rhs ) -> bool :
496505 """Mathics SameQ for MachineReal.
497- If the other comparison value is a MachineReal, the values
498- have to be equal. If the other value is a PrecisionReal though, then
506+ If the rhs comparison value is a MachineReal, the values
507+ have to be equal. If the rhs value is a PrecisionReal though, then
499508 the two values have to be within 1/2 ** (precision) of
500- other -value's precision. For any other type, sameQ is False.
509+ rhs -value's precision. For any rhs type, sameQ is False.
501510 """
502- if isinstance (other , MachineReal ):
503- return self .value == other .value
504- if isinstance (other , PrecisionReal ):
505- other_value = other .value
511+ if isinstance (rhs , MachineReal ):
512+ return self .value == rhs .value
513+ if isinstance (rhs , PrecisionReal ):
514+ rhs_value = rhs .value
506515 value = self .to_sympy ()
507516 # If sympy fixes the issue, this comparison would be
508517 # enough
509- if (value - other_value ).is_zero :
518+ if (value - rhs_value ).is_zero :
510519 return True
511520 # this handles the issue...
512- diff = abs (value - other_value )
513- prec = min (value ._prec , other_value ._prec )
521+ diff = abs (value - rhs_value )
522+ prec = min (value ._prec , rhs_value ._prec )
514523 return diff < 0.5 ** (prec )
515524 else :
516525 return False
@@ -539,13 +548,14 @@ class PrecisionReal(Real[sympy.Float]):
539548 # The key is the PrecisionReal's sympy.Float, and the
540549 # dictionary's value is the corresponding Mathics PrecisionReal object.
541550 _precision_reals : Dict [Any , "PrecisionReal" ] = {}
551+ _sympy : Number
542552
543553 def __new__ (cls , value ) -> "PrecisionReal" :
544554 n = sympy .Float (value )
545555 self = cls ._precision_reals .get (n )
546556 if self is None :
547557 self = Number .__new__ (cls )
548- self ._value = n
558+ self ._sympy = self . _value = n
549559
550560 # Cache object so we don't allocate again.
551561 self ._precision_reals [n ] = self
@@ -593,12 +603,12 @@ def round(self, d: Optional[int] = None) -> Union[MachineReal, "PrecisionReal"]:
593603 _prec = min (prec (d ), self .value ._prec )
594604 return PrecisionReal (sympy .Float (self .value , precision = _prec ))
595605
596- def sameQ (self , other ) -> bool :
606+ def sameQ (self , rhs ) -> bool :
597607 """Mathics SameQ for PrecisionReal"""
598- if isinstance (other , PrecisionReal ):
599- other_value = other .value
600- elif isinstance (other , MachineReal ):
601- other_value = other .to_sympy ()
608+ if isinstance (rhs , PrecisionReal ):
609+ other_value = rhs .value
610+ elif isinstance (rhs , MachineReal ):
611+ other_value = rhs .to_sympy ()
602612 else :
603613 return False
604614 value = self .value
@@ -679,11 +689,11 @@ def is_literal(self) -> bool:
679689 """
680690 return True
681691
682- def sameQ (self , other ) -> bool :
692+ def sameQ (self , rhs ) -> bool :
683693 """Mathics SameQ"""
684694 # FIX: check
685- if isinstance (other , ByteArrayAtom ):
686- return self .value == other .value
695+ if isinstance (rhs , ByteArrayAtom ):
696+ return self .value == rhs .value
687697 return False
688698
689699 def get_string_value (self ) -> Optional [str ]:
@@ -822,12 +832,10 @@ def get_sort_key(self, pattern_sort=False) -> tuple:
822832 else :
823833 return (0 , 0 , self .real .get_sort_key ()[2 ], self .imag .get_sort_key ()[2 ], 1 )
824834
825- def sameQ (self , other ) -> bool :
835+ def sameQ (self , rhs ) -> bool :
826836 """Mathics SameQ"""
827837 return (
828- isinstance (other , Complex )
829- and self .real == other .real
830- and self .imag == other .imag
838+ isinstance (rhs , Complex ) and self .real == rhs .real and self .imag == rhs .imag
831839 )
832840
833841 def round (self , d = None ) -> "Complex" :
@@ -951,9 +959,9 @@ def round(self, d=None) -> Union["MachineReal", "PrecisionReal"]:
951959 else :
952960 return PrecisionReal (self .value .n (d ))
953961
954- def sameQ (self , other ) -> bool :
962+ def sameQ (self , rhs ) -> bool :
955963 """Mathics SameQ"""
956- return isinstance (other , Rational ) and self .value == other .value
964+ return isinstance (rhs , Rational ) and self .value == rhs .value
957965
958966 def numerator (self ) -> "Integer" :
959967 return Integer (self .value .as_numer_denom ()[0 ])
@@ -1059,9 +1067,9 @@ def is_literal(self) -> bool:
10591067 """
10601068 return True
10611069
1062- def sameQ (self , other ) -> bool :
1070+ def sameQ (self , rhs ) -> bool :
10631071 """Mathics SameQ"""
1064- return isinstance (other , String ) and self .value == other .value
1072+ return isinstance (rhs , String ) and self .value == rhs .value
10651073
10661074 def to_expression (self ):
10671075 return self
0 commit comments