22# -*- coding: utf-8 -*-
33
44
5+ from mathics .version import __version__ # noqa used in loading to check consistency.
6+
57import itertools
68from typing import Optional , Union
79
810import sympy
9- from mathics .version import __version__ # noqa used in loading to check consistency.
1011
1112from mathics .builtin .base import (
1213 BinaryOperator ,
2122 Expression ,
2223 Integer ,
2324 Number ,
25+ Real ,
2426 String ,
2527 Symbol ,
2628 SymbolFalse ,
@@ -32,6 +34,9 @@ def cmp(a, b) -> int:
3234 "Returns 0 if a == b, -1 if a < b and 1 if a > b"
3335 return (a > b ) - (a < b )
3436
37+ def is_number (sympy_value ) -> bool :
38+ return hasattr (sympy_value , "is_number" ) or isinstance (sympy_value , sympy .Float )
39+
3540class SameQ (BinaryOperator ):
3641 """
3742 <dl>
@@ -231,17 +236,30 @@ def do_compare(self, l1, l2) -> Union[bool, None]:
231236 return result
232237 return True
233238
239+ # Use Mathics' built-in comparisons for Real and Integer. These use
240+ # WL's interpretation of Equal[] which allows for slop in Reals
241+ # in the least significant digit of precision, while for Integers, comparison
242+ # has to be exact.
243+
244+ if ((isinstance (l1 , Real ) and isinstance (l2 , Real )) or
245+ (isinstance (l1 , Integer ) and isinstance (l2 , Integer ))):
246+ return l1 == l2
247+
248+ # For everything else, use sympy.
249+
234250 l1_sympy = l1 .to_sympy (evaluate = True , prec = COMPARE_PREC )
235251 l2_sympy = l2 .to_sympy (evaluate = True , prec = COMPARE_PREC )
236252
237253 if l1_sympy is None or l2_sympy is None :
238254 return None
239255
240- if not hasattr (l1_sympy , "is_number" ):
256+
257+ if not is_number (l1_sympy ):
241258 l1_sympy = mp_convert_constant (l1_sympy , prec = COMPARE_PREC )
242- if not hasattr (l2_sympy , "is_number" ):
259+ if not is_number (l2_sympy ):
243260 l2_sympy = mp_convert_constant (l2_sympy , prec = COMPARE_PREC )
244261
262+
245263 if l1_sympy .is_number and l2_sympy .is_number :
246264 # assert min_prec(l1, l2) is None
247265 prec = COMPARE_PREC # TODO: Use $MaxExtraPrecision
@@ -360,7 +378,6 @@ def apply(self, items, evaluation):
360378 ]
361379 return Expression ("And" , * groups )
362380
363-
364381def do_cmp (x1 , x2 ) -> Optional [int ]:
365382
366383 # don't attempt to compare complex numbers
@@ -374,8 +391,10 @@ def do_cmp(x1, x2) -> Optional[int]:
374391 s1 = x1 .to_sympy ()
375392 s2 = x2 .to_sympy ()
376393
377- # use internal comparisons only for Reals
378- # and use sympy for everything else
394+ # Use internal comparisons only for Real which is uses
395+ # WL's interpretation of equal (which allows for slop
396+ # in the least significant digit of precision), and use
397+ # use sympy for everything else
379398 if s1 .is_Float and s2 .is_Float :
380399 if x1 == x2 :
381400 return 0
@@ -455,8 +474,9 @@ class Equal(_EqualityOperator, SympyComparison):
455474 ## TODO Needs power precision tracking
456475 ## >> 0.1 ^ 10000 == 0.1 ^ 10000 + 0.1 ^ 10012
457476 ## = False
458- ## >> 0.1 ^ 10000 == 0.1 ^ 10000 + 0.1 ^ 10013
459- ## = True
477+
478+ #> 0.1 ^ 10000 == 0.1 ^ 10000 + 0.1 ^ 10013
479+ = True
460480
461481 #> 0.1111111111111111 == 0.1111111111111126
462482 = True
0 commit comments