Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expression constants #831

Merged
merged 4 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions mathics/builtin/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from mathics.builtin.inference import evaluate_predicate, get_assumptions_list
from mathics.builtin.scoping import dynamic_scoping
from mathics.core.atoms import (
MATHICS3_COMPLEX_I,
MATHICS3_COMPLEX_I_NEG,
Complex,
Integer,
Integer0,
Expand All @@ -43,9 +45,17 @@
)
from mathics.core.convert.expression import to_expression
from mathics.core.convert.sympy import SympyExpression, from_sympy, sympy_symbol_prefix
from mathics.core.element import BaseElement, ElementsProperties
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.expression_predefined import (
MATHICS3_COMPLEX_INFINITY,
MATHICS3_I_INFINITY,
MATHICS3_I_NEG_INFINITY,
MATHICS3_INFINITY,
MATHICS3_NEG_INFINITY,
PredefinedExpression,
)
from mathics.core.list import ListExpression
from mathics.core.number import dps, min_prec
from mathics.core.symbols import (
Expand Down Expand Up @@ -73,7 +83,13 @@
# This tells documentation how to sort this module
sort_order = "mathics.builtin.mathematical-functions"

ExpressionComplexInfinity = Expression(SymbolDirectedInfinity)

map_direction_infinity = {
Integer1: MATHICS3_INFINITY,
IntegerM1: MATHICS3_NEG_INFINITY,
MATHICS3_COMPLEX_I: MATHICS3_I_INFINITY,
MATHICS3_COMPLEX_I_NEG: MATHICS3_I_NEG_INFINITY,
}


class _MPMathFunction(SympyFunction):
Expand Down Expand Up @@ -647,12 +663,18 @@ class DirectedInfinity(SympyFunction):
"DirectedInfinity[z_?NumericQ]": "HoldForm[z Infinity]",
}

def eval_complex_infinity(self, evaluation: Evaluation):
"""DirectedInfinity[]"""
return MATHICS3_COMPLEX_INFINITY

def eval_directed_infinity(self, direction, evaluation: Evaluation):
"""DirectedInfinity[direction_]"""
if direction in (Integer1, IntegerM1):
return None
result = map_direction_infinity.get(direction, None)
if result:
return result

if direction.is_zero:
return ExpressionComplexInfinity
return MATHICS3_COMPLEX_INFINITY

normalized_direction = eval_Sign(direction)
# TODO: improve eval_Sign, to avoid the need of the
Expand All @@ -677,10 +699,9 @@ def eval_directed_infinity(self, direction, evaluation: Evaluation):

if normalized_direction is None:
return None
return Expression(
return PredefinedExpression(
SymbolDirectedInfinity,
normalized_direction.evaluate(evaluation),
elements_properties=ElementsProperties(True, False, False),
)

def to_sympy(self, expr, **kwargs):
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/atomic/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
from mathics.core.convert.python import from_bool
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.expression_predefined import MATHICS3_INFINITY
from mathics.core.list import ListExpression
from mathics.core.parser import MathicsFileLineFeeder, parse
from mathics.core.symbols import Symbol, SymbolTrue
from mathics.core.systemsymbols import (
SymbolBlank,
SymbolDirectedInfinity,
SymbolFailed,
SymbolInputForm,
SymbolOutputForm,
Expand Down Expand Up @@ -800,7 +800,7 @@ def convert_rule(r):
# convert n
if n is None:
py_n = 0
elif n == Expression(SymbolDirectedInfinity, Integer1):
elif n.sameQ(MATHICS3_INFINITY):
py_n = 0
else:
py_n = n.get_int_value()
Expand Down
34 changes: 15 additions & 19 deletions mathics/builtin/binary/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
from mathics.core.convert.expression import to_expression, to_mathics_list
from mathics.core.convert.mpmath import from_mpmath
from mathics.core.expression import Expression
from mathics.core.expression_predefined import (
MATHICS3_I_INFINITY,
MATHICS3_I_NEG_INFINITY,
MATHICS3_INFINITY,
MATHICS3_NEG_INFINITY,
)
from mathics.core.read import SymbolEndOfFile
from mathics.core.streams import stream_manager
from mathics.core.symbols import Symbol
from mathics.core.systemsymbols import (
SymbolComplex,
SymbolDirectedInfinity,
SymbolIndeterminate,
)
from mathics.core.systemsymbols import SymbolIndeterminate
from mathics.eval.nevaluator import eval_N

SymbolBinaryWrite = Symbol("BinaryWrite")
Expand All @@ -38,27 +40,21 @@ def _IEEE_real(real):
if math.isnan(real):
return SymbolIndeterminate
elif math.isinf(real):
return Expression(SymbolDirectedInfinity, Integer((-1) ** (real < 0)))
return MATHICS3_NEG_INFINITY if real < 0 else MATHICS3_INFINITY
else:
return Real(real)

@staticmethod
def _IEEE_cmplx(real, imag):
if math.isnan(real) or math.isnan(imag):
return SymbolIndeterminate
elif math.isinf(real) or math.isinf(imag):
if math.isinf(real) and math.isinf(imag):
if math.isinf(real):
if math.isinf(imag):
return SymbolIndeterminate
return Expression(
SymbolDirectedInfinity,
to_expression(
SymbolComplex,
(-1) ** (real < 0) if math.isinf(real) else 0,
(-1) ** (imag < 0) if math.isinf(imag) else 0,
),
)
else:
return Complex(MachineReal(real), MachineReal(imag))
return MATHICS3_NEG_INFINITY if real < 0 else MATHICS3_INFINITY
if math.isinf(imag):
return MATHICS3_I_NEG_INFINITY if imag < 0 else MATHICS3_I_INFINITY
return Complex(MachineReal(real), MachineReal(imag))

@classmethod
def get_readers(cls):
Expand Down Expand Up @@ -172,7 +168,7 @@ def _Real128_reader(s):
return Real(sympy.Float(0, 4965))
elif expbits == 0x7FFF:
if fracbits == 0:
return Expression(SymbolDirectedInfinity, Integer((-1) ** signbit))
return MATHICS3_NEG_INFINITY if signbit else MATHICS3_INFINITY
else:
return SymbolIndeterminate

Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/functional/functional_iteration.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from mathics.core.convert.python import from_python
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.expression_predefined import MATHICS3_INFINITY
from mathics.core.symbols import Symbol, SymbolTrue
from mathics.core.systemsymbols import SymbolDirectedInfinity

# This tells documentation how to sort this module
sort_order = "mathics.builtin.iteratively-applying-functions"
Expand Down Expand Up @@ -51,7 +51,7 @@ class FixedPoint(Builtin):

def eval(self, f, expr, n, evaluation: Evaluation, options: dict):
"FixedPoint[f_, expr_, n_:DirectedInfinity[1], OptionsPattern[FixedPoint]]"
if n == Expression(SymbolDirectedInfinity, Integer1):
if n.sameQ(MATHICS3_INFINITY):
count = None
else:
count = n.get_int_value()
Expand Down Expand Up @@ -131,7 +131,7 @@ class FixedPointList(Builtin):
def eval(self, f, expr, n, evaluation: Evaluation):
"FixedPointList[f_, expr_, n_:DirectedInfinity[1]]"

if n == Expression(SymbolDirectedInfinity, Integer1):
if n.sameQ(MATHICS3_INFINITY):
count = None
else:
count = n.get_int_value()
Expand Down
12 changes: 4 additions & 8 deletions mathics/builtin/list/rearrange.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@
from typing import Callable

from mathics.builtin.base import Builtin, MessageException
from mathics.core.atoms import Integer, Integer0, Integer1
from mathics.core.atoms import Integer, Integer0
from mathics.core.attributes import A_FLAT, A_ONE_IDENTITY, A_PROTECTED
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression, structure
from mathics.core.expression_predefined import MATHICS3_INFINITY
from mathics.core.list import ListExpression
from mathics.core.symbols import Atom, Symbol, SymbolTrue
from mathics.core.systemsymbols import (
SymbolDirectedInfinity,
SymbolMap,
SymbolReverse,
SymbolSplit,
)
from mathics.core.systemsymbols import SymbolMap, SymbolReverse, SymbolSplit
from mathics.eval.parts import walk_levels


Expand Down Expand Up @@ -813,7 +809,7 @@ def insert_element(elements):
def eval(self, expr, n, h, evaluation):
"Flatten[expr_, n_, h_]"

if n == Expression(SymbolDirectedInfinity, Integer1):
if n.sameQ(MATHICS3_INFINITY):
n = -1 # a negative number indicates an unbounded level
else:
n_int = n.get_int_value()
Expand Down
10 changes: 6 additions & 4 deletions mathics/builtin/numbers/algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.expression_predefined import (
MATHICS3_COMPLEX_INFINITY,
MATHICS3_NEG_INFINITY,
)
from mathics.core.list import ListExpression
from mathics.core.rules import Pattern
from mathics.core.symbols import (
Expand All @@ -46,12 +50,10 @@
SymbolAlternatives,
SymbolAssumptions,
SymbolAutomatic,
SymbolComplexInfinity,
SymbolCos,
SymbolCosh,
SymbolCot,
SymbolCoth,
SymbolDirectedInfinity,
SymbolEqual,
SymbolIndeterminate,
SymbolLess,
Expand Down Expand Up @@ -1377,7 +1379,7 @@ def eval_novar(self, expr, evaluation):
def eval(self, expr, form, h, evaluation):
"Exponent[expr_, form_, h_]"
if expr == Integer0:
return Expression(SymbolDirectedInfinity, Integer(-1))
return MATHICS3_NEG_INFINITY

if not form.has_form("List", None):
# TODO: add ElementProperties in Expression interface refactor branch:
Expand Down Expand Up @@ -1647,7 +1649,7 @@ def eval_power_of_zero(self, b, evaluation):
if self.eval(Expression(SymbolLess, Integer0, b), evaluation) is SymbolTrue:
return Integer0
if self.eval(Expression(SymbolLess, b, Integer0), evaluation) is SymbolTrue:
return Symbol(SymbolComplexInfinity)
return MATHICS3_COMPLEX_INFINITY
if self.eval(Expression(SymbolEqual, b, Integer0), evaluation) is SymbolTrue:
return Symbol(SymbolIndeterminate)
return Expression(SymbolPower, Integer0, b)
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/string/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
from mathics.core.convert.python import from_python
from mathics.core.evaluation import Evaluation
from mathics.core.expression import BoxError, Expression, string_list
from mathics.core.expression_predefined import MATHICS3_INFINITY
from mathics.core.list import ListExpression
from mathics.core.symbols import SymbolFalse, SymbolFullForm, SymbolList, SymbolTrue
from mathics.core.systemsymbols import (
SymbolAll,
SymbolDirectedInfinity,
SymbolOutputForm,
SymbolStringInsert,
SymbolStringJoin,
Expand Down Expand Up @@ -521,7 +521,7 @@ def eval(self, string, patt, evaluation: Evaluation, options: dict):
return self.eval_n(
string,
patt,
Expression(SymbolDirectedInfinity, Integer1),
MATHICS3_INFINITY,
evaluation,
options,
)
Expand Down
55 changes: 25 additions & 30 deletions mathics/builtin/testing_expressions/equality_inequality.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@
)
from mathics.core.convert.expression import to_expression, to_numeric_args
from mathics.core.expression import Expression
from mathics.core.expression_predefined import (
MATHICS3_COMPLEX_INFINITY,
MATHICS3_INFINITY,
MATHICS3_NEG_INFINITY,
)
from mathics.core.number import dps
from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolList, SymbolTrue
from mathics.core.systemsymbols import (
SymbolAnd,
SymbolComplexInfinity,
SymbolDirectedInfinity,
SymbolExactNumberQ,
SymbolInequality,
Expand Down Expand Up @@ -110,6 +114,8 @@ def get_pairs(args):
yield (args[i], args[j])

def expr_equal(self, lhs, rhs, max_extra_prec=None) -> Optional[bool]:
if rhs is lhs:
return True
if isinstance(rhs, Expression):
lhs, rhs = rhs, lhs
if not isinstance(lhs, Expression):
Expand All @@ -129,34 +135,23 @@ def expr_equal(self, lhs, rhs, max_extra_prec=None) -> Optional[bool]:
return True

def infty_equal(self, lhs, rhs, max_extra_prec=None) -> Optional[bool]:
if rhs.get_head().sameQ(SymbolDirectedInfinity):
lhs, rhs = rhs, lhs
if not lhs.get_head().sameQ(SymbolDirectedInfinity):
if (
lhs.get_head() is not SymbolDirectedInfinity
or rhs.get_head() is not SymbolDirectedInfinity
):
return None
if rhs.sameQ(SymbolInfinity) or rhs.sameQ(SymbolComplexInfinity):
if len(lhs.elements) == 0:
return True
else:
return self.equal2(
to_expression(SymbolSign, lhs.elements[0]), Integer1, max_extra_prec
)
if rhs.is_numeric():
return False
elif isinstance(rhs, Atom):
lhs_elements, rhs_elements = lhs.elements, rhs.elements

if len(lhs_elements) != len(rhs_elements):
return None
if rhs.get_head().sameQ(lhs.get_head()):
dir1 = dir2 = Integer1
if len(lhs.elements) == 1:
dir1 = lhs.elements[0]
if len(rhs.elements) == 1:
dir2 = rhs.elements[0]
if self.equal2(dir1, dir2, max_extra_prec):
return True
# Now, compare the signs:
dir1_sign = Expression(SymbolSign, dir1)
dir2_sign = Expression(SymbolSign, dir2)
return self.equal2(dir1_sign, dir2_sign, max_extra_prec)
return
# Both are complex infinity?
if len(lhs_elements) == 0:
return True
if len(lhs_elements) == 1:
# Check directions: Notice that they are already normalized...
return self.equal2(lhs_elements[0], rhs_elements[0], max_extra_prec)
# DirectedInfinity with more than two elements cannot be compared here...
return None

def sympy_equal(self, lhs, rhs, max_extra_prec=None) -> Optional[bool]:
try:
Expand Down Expand Up @@ -200,12 +195,12 @@ def equal2(self, lhs: Any, rhs: Any, max_extra_prec=None) -> Optional[bool]:
"""
Two-argument Equal[]
"""
if lhs is rhs or lhs.sameQ(rhs):
return True
if hasattr(lhs, "equal2"):
result = lhs.equal2(rhs)
if result is not None:
return result
elif lhs.sameQ(rhs):
return True
# TODO: Check $Assumptions
# Still we didn't have a result. Try with the following
# tests
Expand Down Expand Up @@ -294,7 +289,7 @@ def eval(self, items, evaluation):
results.append(element)

if not results:
return Expression(SymbolDirectedInfinity, Integer(-self.sense))
return MATHICS3_INFINITY if self.sense < 0 else MATHICS3_NEG_INFINITY
if len(results) == 1:
return results.pop()
if len(results) < len(items):
Expand Down
3 changes: 3 additions & 0 deletions mathics/core/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,9 @@ def is_zero(self) -> bool:


RationalOneHalf = Rational(1, 2)
RationalMinusOneHalf = Rational(-1, 2)
MATHICS3_COMPLEX_I = Complex(Integer0, Integer1)
MATHICS3_COMPLEX_I_NEG = Complex(Integer0, IntegerM1)


class String(Atom, BoxElementMixin):
Expand Down
Loading