Skip to content

Commit

Permalink
session.parse (#858)
Browse files Browse the repository at this point in the history
Adding this method which is  handy for low-level tests.  
Also,
* Removing unused imports. 
* Adding symbols to mathics.core.systemsymbols

---------

Co-authored-by: R. Bernstein <[email protected]>
  • Loading branch information
mmatera and rocky authored May 27, 2023
1 parent 1c1ec6b commit 09b0fe5
Show file tree
Hide file tree
Showing 11 changed files with 409 additions and 46 deletions.
6 changes: 5 additions & 1 deletion mathics/builtin/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,10 +799,14 @@ def get_operator_display(self) -> Optional[str]:


class Predefined(Builtin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.symbol = Symbol(self.get_name())

def get_functions(self, prefix="eval", is_pymodule=False) -> List[Callable]:
functions = list(super().get_functions(prefix))
if prefix == "eval" and hasattr(self, "evaluate"):
functions.append((Symbol(self.get_name()), self.evaluate))
functions.append((self.symbol, self.evaluate))
return functions


Expand Down
81 changes: 48 additions & 33 deletions mathics/builtin/numbers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,19 @@
# This tells documentation how to sort this module
sort_order = "mathics.builtin.mathematical-constants"


import math
from typing import Optional

import mpmath
import numpy
import sympy

from mathics.builtin.base import Builtin, Predefined, SympyObject
from mathics.core.atoms import MachineReal, PrecisionReal
from mathics.core.atoms import NUMERICAL_CONSTANTS, MachineReal, PrecisionReal
from mathics.core.attributes import A_CONSTANT, A_PROTECTED, A_READ_PROTECTED
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation
from mathics.core.number import (
MACHINE_DIGITS,
MAX_MACHINE_NUMBER,
MIN_MACHINE_NUMBER,
PrecisionValueError,
get_precision,
prec,
)
from mathics.core.number import MACHINE_DIGITS, PrecisionValueError, get_precision, prec
from mathics.core.symbols import Atom, Symbol, strip_context
from mathics.core.systemsymbols import SymbolIndeterminate

Expand Down Expand Up @@ -89,28 +83,33 @@ def eval_N(self, precision, evaluation):
def is_constant(self) -> bool:
return True

def get_constant(self, precision, evaluation):
def get_constant(
self,
precision: Optional[BaseElement] = None,
evaluation: Optional[Evaluation] = None,
):
# first, determine the precision
d = None
if precision:
try:
d = get_precision(precision, evaluation)
except PrecisionValueError:
pass
preference = None
if evaluation:
if precision:
try:
d = get_precision(precision, evaluation)
except PrecisionValueError:
pass

preflist = evaluation._preferred_n_method.copy()
while preflist:
pref_method = preflist.pop()
if pref_method in ("numpy", "mpmath", "sympy"):
preference = pref_method
break

if d is None:
d = MACHINE_DIGITS

# If preference not especified, determine it
# from the precision.
preference = None
preflist = evaluation._preferred_n_method.copy()
while preflist:
pref_method = preflist.pop()
if pref_method in ("numpy", "mpmath", "sympy"):
preference = pref_method
break

if preference is None:
if d <= MACHINE_DIGITS:
preference = "numpy"
Expand All @@ -131,10 +130,16 @@ def get_constant(self, precision, evaluation):
preference = "mpmath"
else:
preference = ""

if preference == "numpy":
value = numpy_constant(self.numpy_name)
if d == MACHINE_DIGITS:
return MachineReal(value)
try:
return NUMERICAL_CONSTANTS[self.symbol]
except KeyError:
value = MachineReal(numpy_constant(self.numpy_name))
NUMERICAL_CONSTANTS[self.symbol] = value
return value
value = numpy_constant(self.numpy_name)
if preference == "sympy":
value = sympy_constant(self.sympy_name, d + 2)
if preference == "mpmath":
Expand Down Expand Up @@ -177,13 +182,16 @@ class _NumpyConstant(_Constant_Common):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.numpy_name is None:
self.numpy_name = strip_context(self.get_name()).lower()
self.numpy_name = strip_context(self.symbol.name).lower()
self.mathics_to_numpy[self.__class__.__name__] = self.numpy_name
try:
value_float = numpy_constant(self.numpy_name)
except AttributeError:
value_float = self.to_numpy(self.symbol)
NUMERICAL_CONSTANTS[self.symbol] = MachineReal(value_float)

def to_numpy(self, args):
if self.numpy_name is None or len(args) != 0:
return None
return self.get_constant()
return NUMERICAL_CONSTANTS[self.symbol]


class _SympyConstant(_Constant_Common, SympyObject):
Expand Down Expand Up @@ -608,7 +616,7 @@ class MaxMachineNumber(Predefined):
summary_text = "largest normalized positive machine number"

def evaluate(self, evaluation: Evaluation) -> MachineReal:
return MachineReal(MAX_MACHINE_NUMBER)
return NUMERICAL_CONSTANTS[self.symbol]


class MinMachineNumber(Predefined):
Expand All @@ -635,10 +643,10 @@ class MinMachineNumber(Predefined):
summary_text = "smallest normalized positive machine number"

def evaluate(self, evaluation: Evaluation) -> MachineReal:
return MachineReal(MIN_MACHINE_NUMBER)
return NUMERICAL_CONSTANTS[self.symbol]


class Pi(_MPMathConstant, _SympyConstant):
class Pi(_MPMathConstant, _NumpyConstant, _SympyConstant):
"""
<url>
:Pi, \u03c0: https://en.wikipedia.org/wiki/Pi</url> (<url>
Expand Down Expand Up @@ -740,3 +748,10 @@ class Underflow(Builtin):
"Underflow[] * x_Real": "0.",
}
summary_text = "underflow in numeric evaluation"


# Constants that are not numpy constants,
for cls in (Catalan, Degree, Glaisher, GoldenRatio, Khinchin):
instance = cls(expression=False)
val = instance.get_constant()
NUMERICAL_CONSTANTS[instance.symbol] = MachineReal(val.value)
5 changes: 5 additions & 0 deletions mathics/builtin/testing_expressions/numerical_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from mathics.core.expression import Expression
from mathics.core.symbols import BooleanType, SymbolFalse, SymbolTrue
from mathics.core.systemsymbols import SymbolExpandAll, SymbolSimplify
from mathics.eval.arithmetic import test_zero_arithmetic_expr
from mathics.eval.nevaluator import eval_N


Expand Down Expand Up @@ -460,6 +461,10 @@ def eval(self, expr, evaluation):
"%(name)s[expr_]"
from sympy.matrices.utilities import _iszero

# This handles most of the arithmetic cases
if test_zero_arithmetic_expr(expr):
return SymbolTrue

sympy_expr = expr.to_sympy()
result = _iszero(sympy_expr)
if result is None:
Expand Down
10 changes: 10 additions & 0 deletions mathics/core/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from mathics.core.number import (
FP_MANTISA_BINARY_DIGITS,
MACHINE_PRECISION_VALUE,
MAX_MACHINE_NUMBER,
MIN_MACHINE_NUMBER,
dps,
min_prec,
prec,
Expand Down Expand Up @@ -946,6 +948,14 @@ def is_zero(self) -> bool:
MATHICS3_COMPLEX_I = Complex(Integer0, Integer1)
MATHICS3_COMPLEX_I_NEG = Complex(Integer0, IntegerM1)

# Numerical constants
# These constants are populated by the `Predefined`
# classes. See `mathics.builtin.numbers.constants`
NUMERICAL_CONSTANTS = {
Symbol("System`$MaxMachineNumber"): MachineReal(MAX_MACHINE_NUMBER),
Symbol("System`$MinMachineNumber"): MachineReal(MIN_MACHINE_NUMBER),
}


class String(Atom, BoxElementMixin):
value: str
Expand Down
4 changes: 3 additions & 1 deletion mathics/core/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ def _get_float_inf(value, evaluation) -> Optional[float]:
return value.round_to_float(evaluation)


def get_precision(value, evaluation, show_messages=True) -> Optional[float]:
def get_precision(
value: BaseElement, evaluation, show_messages: bool = True
) -> Optional[float]:
"""
Returns the ``float`` in the interval [``$MinPrecision``, ``$MaxPrecision``] closest to ``value``.
If ``value`` does not belongs to that interval, and ``show_messages`` is True, a Message warning is shown.
Expand Down
6 changes: 6 additions & 0 deletions mathics/core/systemsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

# This list is sorted in alphabetic order.
SymbolAborted = Symbol("System`$Aborted")
SymbolAbs = Symbol("System`Abs")
SymbolAccuracy = Symbol("System`Accuracy")
SymbolAll = Symbol("System`All")
SymbolAlternatives = Symbol("System`Alternatives")
Expand Down Expand Up @@ -84,6 +85,7 @@
SymbolEquivalent = Symbol("System`Equivalent")
SymbolEulerGamma = Symbol("System`EulerGamma")
SymbolExactNumberQ = Symbol("System`ExactNumberQ")
SymbolExp = Symbol("System`Exp")
SymbolExpandAll = Symbol("System`ExpandAll")
SymbolExport = Symbol("System`Export")
SymbolExportString = Symbol("System`ExportString")
Expand All @@ -109,6 +111,7 @@
SymbolHoldForm = Symbol("System`HoldForm")
SymbolHoldPattern = Symbol("System`HoldPattern")
SymbolHue = Symbol("System`Hue")
SymbolI = Symbol("System`I")
SymbolIf = Symbol("System`If")
SymbolIm = Symbol("System`Im")
SymbolImage = Symbol("System`Image")
Expand All @@ -126,6 +129,7 @@
SymbolLess = Symbol("System`Less")
SymbolLessEqual = Symbol("System`LessEqual")
SymbolKey = Symbol("System`Key")
SymbolKhinchin = Symbol("System`Khinchin")
SymbolLetterCharacter = Symbol("System`LetterCharacter")
SymbolLine = Symbol("System`Line")
SymbolLog = Symbol("System`Log")
Expand Down Expand Up @@ -179,6 +183,7 @@
SymbolPi = Symbol("System`Pi")
SymbolPiecewise = Symbol("System`Piecewise")
SymbolPlot = Symbol("System`Plot")
SymbolPlus = Symbol("System`Plus")
SymbolPoint = Symbol("System`Point")
SymbolPower = Symbol("System`Power")
SymbolPolygon = Symbol("System`Polygon")
Expand Down Expand Up @@ -242,6 +247,7 @@
SymbolTan = Symbol("System`Tan")
SymbolTanh = Symbol("System`Tanh")
SymbolTeXForm = Symbol("System`TeXForm")
SymbolTimes = Symbol("System`Times")
SymbolThrow = Symbol("System`Throw")
SymbolThreshold = Symbol("System`Threshold")
SymbolToString = Symbol("System`ToString")
Expand Down
Loading

0 comments on commit 09b0fe5

Please sign in to comment.