1010from mathics .version import __version__ # noqa used in loading to check consistency.
1111import sympy
1212import mpmath
13+ from functools import lru_cache
1314
1415from mathics .builtin .base import (
1516 Builtin ,
3435 SymbolNull ,
3536 SymbolTrue ,
3637 from_python ,
38+ from_mpmath ,
3739)
3840from mathics .core .numbers import min_prec , dps , SpecialValueError
3941
4042from mathics .builtin .lists import _IterationFunction
4143from 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+
4361class _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 )
0 commit comments