Skip to content

Commit 8619fc2

Browse files
committed
Real and Integer value equality testing ...
Use internal Mathics routines here as these closer what happens in Mathics.
1 parent 93d0f97 commit 8619fc2

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

mathics/builtin/comparison.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
# -*- coding: utf-8 -*-
33

44

5+
from mathics.version import __version__ # noqa used in loading to check consistency.
6+
57
import itertools
68
from typing import Optional, Union
79

810
import sympy
9-
from mathics.version import __version__ # noqa used in loading to check consistency.
1011

1112
from mathics.builtin.base import (
1213
BinaryOperator,
@@ -21,6 +22,7 @@
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+
3540
class 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-
364381
def 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

Comments
 (0)