From 67a07eae1ee3c03aa917cbf0f70b02940cccf194 Mon Sep 17 00:00:00 2001 From: weakit Date: Thu, 5 Nov 2020 19:44:50 +0530 Subject: [PATCH 1/2] redo do_cmp --- .gitignore | 2 + mathics/builtin/comparison.py | 74 ++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 14234d4b11..6e0acb0eca 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ mathics/web/media/pdf/ mathics/web/media/doc/classes.pdf mathics/web/media/doc/classes.png tmp + +.idea/ diff --git a/mathics/builtin/comparison.py b/mathics/builtin/comparison.py index dd275fd616..29481f9656 100644 --- a/mathics/builtin/comparison.py +++ b/mathics/builtin/comparison.py @@ -2,13 +2,14 @@ # -*- coding: utf-8 -*- -import sympy import itertools -from mathics.builtin.base import Builtin, BinaryOperator, Test, SympyFunction -from mathics.core.expression import (Expression, Number, Integer, Rational, - Real, Symbol, String) -from mathics.core.numbers import get_type, dps +import sympy + +from mathics.builtin.base import BinaryOperator, Builtin, SympyFunction +from mathics.core.expression import (Complex, Expression, Integer, Number, + String, Symbol) +from mathics.core.numbers import dps class SameQ(BinaryOperator): @@ -88,6 +89,7 @@ class TrueQ(Builtin): 'TrueQ[expr_]': 'If[expr, True, False, False]', } + class BooleanQ(Builtin): """
@@ -313,37 +315,35 @@ def apply(self, items, evaluation): def do_cmp(x1, x2): - inf1 = inf2 = real1 = real2 = None - if isinstance(x1, (Real, Integer, Rational)): - real1 = x1.to_sympy() - if isinstance(x2, (Real, Integer, Rational)): - real2 = x2.to_sympy() - if x1.has_form('DirectedInfinity', 1): - inf1 = x1.leaves[0].get_int_value() - if x2.has_form('DirectedInfinity', 1): - inf2 = x2.leaves[0].get_int_value() - - if real1 is not None and real2 is not None: - if x1 == x2: - return 0 - elif x1 < x2: - return -1 - else: - return 1 - elif inf1 is not None and inf2 is not None: - if inf1 == inf2: - return 0 - elif inf1 < inf2: - return -1 - else: - return 1 - elif inf1 is not None and real2 is not None: - return inf1 - elif real1 is not None and inf2 is not None: - return -inf2 - else: + + # don't attempt to compare complex numbers + for x in (x1, x2): + # TODO: Send message General::nord + if isinstance(x, Complex) or ( + x.has_form("DirectedInfinity", 1) and isinstance(x.leaves[0], Complex) + ): + return None + + # rely on sympy for better comparisons + s1 = x1.to_sympy() + s2 = x2.to_sympy() + + # this might seem like poorly written code at first glance, but + # the equality comparison is required for it to function properly. + # Sympy comparisons might not return sometimes, and will raise + # an error in that case if not compared to True/False. + + eq = sympy.Equality(s1, s2) + + if eq == True: + return 0 + elif eq != False: return None + if sympy.StrictLessThan(s1, s2) == True: + return -1 + return 1 + class SympyComparison(SympyFunction): def to_sympy(self, expr, **kwargs): @@ -732,9 +732,11 @@ class Max(_MinMax):
returns the expression with the greatest value among the $e_i$.
- Maximum of a series of numbers: + Maximum of a series of values: >> Max[4, -8, 1] = 4 + >> Max[E - Pi, Pi, E + Pi, 2 E] + = E + Pi 'Max' flattens lists in its arguments: >> Max[{1,2},3,{-3,3.5,-Infinity},{{1/2}}] @@ -767,6 +769,8 @@ class Min(_MinMax): Minimum of a series of numbers: >> Min[4, -8, 1] = -8 + >> Min[E - Pi, Pi, E + Pi, 2 E] + = E - Pi 'Min' flattens lists in its arguments: >> Min[{1,2},3,{-3,3.5,-Infinity},{{1/2}}] From 3479ad620b9692a2a6223497013aff29f5fdee15 Mon Sep 17 00:00:00 2001 From: weakit Date: Thu, 5 Nov 2020 22:43:27 +0530 Subject: [PATCH 2/2] fix comparison for reals and other types --- mathics/builtin/comparison.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/mathics/builtin/comparison.py b/mathics/builtin/comparison.py index 29481f9656..fd10078418 100644 --- a/mathics/builtin/comparison.py +++ b/mathics/builtin/comparison.py @@ -8,7 +8,7 @@ from mathics.builtin.base import BinaryOperator, Builtin, SympyFunction from mathics.core.expression import (Complex, Expression, Integer, Number, - String, Symbol) + Real, String, Symbol) from mathics.core.numbers import dps @@ -324,25 +324,28 @@ def do_cmp(x1, x2): ): return None - # rely on sympy for better comparisons s1 = x1.to_sympy() s2 = x2.to_sympy() - # this might seem like poorly written code at first glance, but - # the equality comparison is required for it to function properly. - # Sympy comparisons might not return sometimes, and will raise - # an error in that case if not compared to True/False. + # use internal comparisons only for Reals + # and use sympy for everything else + if s1.is_Float and s2.is_Float: + if x1 == x2: + return 0 + if x1 < x2: + return -1 + return 1 - eq = sympy.Equality(s1, s2) + # we don't want to compare anything that + # cannot be represented as a numeric value + if s1.is_number and s2.is_number: + if s1 == s2: + return 0 + if s1 < s2: + return -1 + return 1 - if eq == True: - return 0 - elif eq != False: - return None - - if sympy.StrictLessThan(s1, s2) == True: - return -1 - return 1 + return None class SympyComparison(SympyFunction): @@ -766,7 +769,7 @@ class Min(_MinMax):
returns the expression with the lowest value among the $e_i$. - Minimum of a series of numbers: + Minimum of a series of values: >> Min[4, -8, 1] = -8 >> Min[E - Pi, Pi, E + Pi, 2 E]