Skip to content

Commit 15d8d63

Browse files
authored
Merge pull request #1192 from mathics/realdigits-optimize
More descriptive and general in prep for profiling
2 parents cc30f32 + 007c8c0 commit 15d8d63

7 files changed

Lines changed: 220 additions & 178 deletions

File tree

mathics/builtin/arithmetic.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from mathics.version import __version__ # noqa used in loading to check consistency.
1111
import sympy
1212
import mpmath
13+
from functools import lru_cache
1314

1415
from mathics.builtin.base import (
1516
Builtin,
@@ -34,12 +35,29 @@
3435
SymbolNull,
3536
SymbolTrue,
3637
from_python,
38+
from_mpmath,
3739
)
3840
from mathics.core.numbers import min_prec, dps, SpecialValueError
3941

4042
from mathics.builtin.lists import _IterationFunction
4143
from mathics.core.convert import from_sympy, SympyExpression
4244

45+
@lru_cache(maxsize=1024)
46+
def call_mpmath(mpmath_function, mpmath_args):
47+
try:
48+
return mpmath_function(*mpmath_args)
49+
except ValueError as exc:
50+
text = str(exc)
51+
if text == "gamma function pole":
52+
return Symbol("ComplexInfinity")
53+
else:
54+
raise
55+
except ZeroDivisionError:
56+
return
57+
except SpecialValueError as exc:
58+
return Symbol(exc.name)
59+
60+
4361
class _MPMathFunction(SympyFunction):
4462

4563
attributes = ("Listable", "NumericFunction")
@@ -48,6 +66,7 @@ class _MPMathFunction(SympyFunction):
4866

4967
nargs = 1
5068

69+
@lru_cache(maxsize=1024)
5170
def get_mpmath_function(self, args):
5271
if self.mpmath_name is None or len(args) != self.nargs:
5372
return None
@@ -57,7 +76,7 @@ def apply(self, z, evaluation):
5776
"%(name)s[z__]"
5877

5978
args = z.numerify(evaluation).get_sequence()
60-
mpmath_function = self.get_mpmath_function(args)
79+
mpmath_function = self.get_mpmath_function(tuple(args))
6180
result = None
6281

6382
# if no arguments are inexact attempt to use sympy
@@ -82,7 +101,7 @@ def apply(self, z, evaluation):
82101
if None in float_args:
83102
return
84103

85-
result = self.call_mpmath(mpmath_function, float_args)
104+
result = call_mpmath(mpmath_function, tuple(float_args))
86105
if isinstance(result, (mpmath.mpc, mpmath.mpf)):
87106
if mpmath.isinf(result) and isinstance(result, mpmath.mpc):
88107
result = Symbol("ComplexInfinity")
@@ -93,7 +112,7 @@ def apply(self, z, evaluation):
93112
elif mpmath.isnan(result):
94113
result = Symbol("Indeterminate")
95114
else:
96-
result = Number.from_mpmath(result)
115+
result = from_mpmath(result)
97116
else:
98117
prec = min_prec(*args)
99118
d = dps(prec)
@@ -104,9 +123,9 @@ def apply(self, z, evaluation):
104123
mpmath_args = [x.to_mpmath() for x in args]
105124
if None in mpmath_args:
106125
return
107-
result = self.call_mpmath(mpmath_function, mpmath_args)
126+
result = call_mpmath(mpmath_function, tuple(mpmath_args))
108127
if isinstance(result, (mpmath.mpc, mpmath.mpf)):
109-
result = Number.from_mpmath(result, d)
128+
result = from_mpmath(result, d)
110129
return result
111130

112131
def call_mpmath(self, mpmath_function, mpmath_args):
@@ -338,12 +357,12 @@ def append_last():
338357
if is_machine_precision:
339358
numbers = [item.to_mpmath() for item in numbers]
340359
number = mpmath.fsum(numbers)
341-
number = Number.from_mpmath(number)
360+
number = from_mpmath(number)
342361
else:
343362
with mpmath.workprec(prec):
344363
numbers = [item.to_mpmath() for item in numbers]
345364
number = mpmath.fsum(numbers)
346-
number = Number.from_mpmath(number, dps(prec))
365+
number = from_mpmath(number, dps(prec))
347366
else:
348367
number = from_sympy(sum(item.to_sympy() for item in numbers))
349368
else:
@@ -670,12 +689,12 @@ def apply(self, items, evaluation):
670689
if is_machine_precision:
671690
numbers = [item.to_mpmath() for item in numbers]
672691
number = mpmath.fprod(numbers)
673-
number = Number.from_mpmath(number)
692+
number = from_mpmath(number)
674693
else:
675694
with mpmath.workprec(prec):
676695
numbers = [item.to_mpmath() for item in numbers]
677696
number = mpmath.fprod(numbers)
678-
number = Number.from_mpmath(number, dps(prec))
697+
number = from_mpmath(number, dps(prec))
679698
else:
680699
number = sympy.Mul(*[item.to_sympy() for item in numbers])
681700
number = from_sympy(number)

mathics/builtin/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
# cython: language_level=3
23

34
import re
45
import sympy

mathics/builtin/files.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
# cython: language_level=3
23

34
"""
45
File Operations
@@ -19,7 +20,7 @@
1920
import requests
2021
import pathlib
2122

22-
from io import BytesIO, StringIO
23+
from io import BytesIO
2324
import os.path as osp
2425
from itertools import chain
2526

@@ -29,21 +30,20 @@
2930
from mathics.core.parser import MathicsFileLineFeeder
3031

3132
from mathics.core.expression import (
33+
BoxError,
34+
Complex,
3235
Expression,
36+
Integer,
37+
MachineReal,
3338
Real,
34-
Complex,
3539
String,
3640
Symbol,
3741
SymbolFailed,
3842
SymbolFalse,
3943
SymbolNull,
4044
SymbolTrue,
41-
SymbolInfinity,
45+
from_mpmath,
4246
from_python,
43-
Integer,
44-
BoxError,
45-
MachineReal,
46-
Number,
4747
valid_context_name,
4848
)
4949
from mathics.core.numbers import dps
@@ -1067,7 +1067,7 @@ def _Real128_reader(s):
10671067
else:
10681068
result = mpmath.fdiv(core, 2 ** -exp)
10691069

1070-
return Number.from_mpmath(result, dps(112))
1070+
return from_mpmath(result, dps(112))
10711071

10721072
@staticmethod
10731073
def _TerminatedString_reader(s):
@@ -2187,7 +2187,8 @@ def check_options(options):
21872187
result = {}
21882188
trace_get = evaluation.parse('Settings`$TraceGet')
21892189
if options["System`Trace"].to_python() or trace_get.evaluate(evaluation) == SymbolTrue:
2190-
result["TraceFn"] = print
2190+
import builtins
2191+
result["TraceFn"] = builtins.print
21912192
else:
21922193
result["TraceFn"] = None
21932194

mathics/builtin/linalg.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from mathics.version import __version__ # noqa used in loading to check consistency.
1212
from mathics.builtin.base import Builtin
1313
from mathics.core.convert import from_sympy
14-
from mathics.core.expression import Expression, Integer, Symbol, Real, Number
14+
from mathics.core.expression import Expression, Integer, Symbol, Real, from_mpmath
1515

1616

1717
def matrix_data(m):
@@ -385,7 +385,7 @@ def apply(self, m, b, evaluation):
385385

386386
try:
387387
solution = matrix.solve_least_squares(b_vector) # default method = Cholesky
388-
except NotImplementedError as e:
388+
except NotImplementedError:
389389
return evaluation.message("LeastSquares", "underdetermined")
390390

391391
return from_sympy(solution)
@@ -729,7 +729,7 @@ def mp_eig(mp_matrix) -> Expression:
729729
eigenvalues.sort(
730730
key=lambda v: (abs(v[0]), -v[0].real, -(v[0].imag)), reverse=True
731731
)
732-
eigenvalues = [[Number.from_mpmath(c) for c in row] for row in eigenvalues]
732+
eigenvalues = [[from_mpmath(c) for c in row] for row in eigenvalues]
733733
return Expression("List", *eigenvalues)
734734

735735
options = {"Method": "sympy"}
@@ -831,7 +831,7 @@ def apply(self, m, power, evaluation):
831831
res = sympy_m ** sympy_power
832832
except NotImplementedError:
833833
return evaluation.message("MatrixPower", "matrixpowernotimplemented", m)
834-
except ValueError as e:
834+
except ValueError:
835835
return evaluation.message("MatrixPower", "matrixpowernotinvertible", m)
836836
return from_sympy(res)
837837

0 commit comments

Comments
 (0)