|
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 |
|
4 | 4 |
|
5 | | -import sympy |
6 | 5 | import itertools |
7 | 6 |
|
8 | | -from mathics.builtin.base import Builtin, BinaryOperator, Test, SympyFunction |
9 | | -from mathics.core.expression import (Expression, Number, Integer, Rational, |
10 | | - Real, Symbol, String) |
11 | | -from mathics.core.numbers import get_type, dps |
| 7 | +import sympy |
| 8 | + |
| 9 | +from mathics.builtin.base import BinaryOperator, Builtin, SympyFunction |
| 10 | +from mathics.core.expression import (Complex, Expression, Integer, Number, |
| 11 | + String, Symbol) |
| 12 | +from mathics.core.numbers import dps |
12 | 13 |
|
13 | 14 |
|
14 | 15 | class SameQ(BinaryOperator): |
@@ -88,6 +89,7 @@ class TrueQ(Builtin): |
88 | 89 | 'TrueQ[expr_]': 'If[expr, True, False, False]', |
89 | 90 | } |
90 | 91 |
|
| 92 | + |
91 | 93 | class BooleanQ(Builtin): |
92 | 94 | """ |
93 | 95 | <dl> |
@@ -313,37 +315,35 @@ def apply(self, items, evaluation): |
313 | 315 |
|
314 | 316 |
|
315 | 317 | def do_cmp(x1, x2): |
316 | | - inf1 = inf2 = real1 = real2 = None |
317 | | - if isinstance(x1, (Real, Integer, Rational)): |
318 | | - real1 = x1.to_sympy() |
319 | | - if isinstance(x2, (Real, Integer, Rational)): |
320 | | - real2 = x2.to_sympy() |
321 | | - if x1.has_form('DirectedInfinity', 1): |
322 | | - inf1 = x1.leaves[0].get_int_value() |
323 | | - if x2.has_form('DirectedInfinity', 1): |
324 | | - inf2 = x2.leaves[0].get_int_value() |
325 | | - |
326 | | - if real1 is not None and real2 is not None: |
327 | | - if x1 == x2: |
328 | | - return 0 |
329 | | - elif x1 < x2: |
330 | | - return -1 |
331 | | - else: |
332 | | - return 1 |
333 | | - elif inf1 is not None and inf2 is not None: |
334 | | - if inf1 == inf2: |
335 | | - return 0 |
336 | | - elif inf1 < inf2: |
337 | | - return -1 |
338 | | - else: |
339 | | - return 1 |
340 | | - elif inf1 is not None and real2 is not None: |
341 | | - return inf1 |
342 | | - elif real1 is not None and inf2 is not None: |
343 | | - return -inf2 |
344 | | - else: |
| 318 | + |
| 319 | + # don't attempt to compare complex numbers |
| 320 | + for x in (x1, x2): |
| 321 | + # TODO: Send message General::nord |
| 322 | + if isinstance(x, Complex) or ( |
| 323 | + x.has_form("DirectedInfinity", 1) and isinstance(x.leaves[0], Complex) |
| 324 | + ): |
| 325 | + return None |
| 326 | + |
| 327 | + # rely on sympy for better comparisons |
| 328 | + s1 = x1.to_sympy() |
| 329 | + s2 = x2.to_sympy() |
| 330 | + |
| 331 | + # this might seem like poorly written code at first glance, but |
| 332 | + # the equality comparison is required for it to function properly. |
| 333 | + # Sympy comparisons might not return sometimes, and will raise |
| 334 | + # an error in that case if not compared to True/False. |
| 335 | + |
| 336 | + eq = sympy.Equality(s1, s2) |
| 337 | + |
| 338 | + if eq == True: |
| 339 | + return 0 |
| 340 | + elif eq != False: |
345 | 341 | return None |
346 | 342 |
|
| 343 | + if sympy.StrictLessThan(s1, s2) == True: |
| 344 | + return -1 |
| 345 | + return 1 |
| 346 | + |
347 | 347 |
|
348 | 348 | class SympyComparison(SympyFunction): |
349 | 349 | def to_sympy(self, expr, **kwargs): |
@@ -732,9 +732,11 @@ class Max(_MinMax): |
732 | 732 | <dd>returns the expression with the greatest value among the $e_i$. |
733 | 733 | </dl> |
734 | 734 |
|
735 | | - Maximum of a series of numbers: |
| 735 | + Maximum of a series of values: |
736 | 736 | >> Max[4, -8, 1] |
737 | 737 | = 4 |
| 738 | + >> Max[E - Pi, Pi, E + Pi, 2 E] |
| 739 | + = E + Pi |
738 | 740 |
|
739 | 741 | 'Max' flattens lists in its arguments: |
740 | 742 | >> Max[{1,2},3,{-3,3.5,-Infinity},{{1/2}}] |
@@ -767,6 +769,8 @@ class Min(_MinMax): |
767 | 769 | Minimum of a series of numbers: |
768 | 770 | >> Min[4, -8, 1] |
769 | 771 | = -8 |
| 772 | + >> Min[E - Pi, Pi, E + Pi, 2 E] |
| 773 | + = E - Pi |
770 | 774 |
|
771 | 775 | 'Min' flattens lists in its arguments: |
772 | 776 | >> Min[{1,2},3,{-3,3.5,-Infinity},{{1/2}}] |
|
0 commit comments