2121)
2222from mathics .core .numbers import get_precision , PrecisionValueError
2323
24+ def mp_constant (fn , d = None ):
25+ if d is None :
26+ return getattr (mpmath , fn )()
27+ else :
28+ mpmath .mp .dps = int_d = int (d )
29+ return getattr (mpmath , fn )(prec = int_d )
30+
2431def mp_convert_constant (obj , ** kwargs ):
2532 if isinstance (obj , mpmath .ctx_mp_python ._constant ):
2633 prec = kwargs .get ("prec" , None )
@@ -29,22 +36,46 @@ def mp_convert_constant(obj, **kwargs):
2936 return sympy .Float (obj )
3037 return obj
3138
39+ def numpy_constant (name , d = None ):
40+ return getattr (numpy , name )
3241
33- def mp_fn (fn , d = None ):
34- if d is None :
35- return getattr (mpmath , fn )()
36- else :
37- mpmath .mp .dps = int_d = int (d )
38- return getattr (mpmath , fn )(prec = int_d )
42+ def sympy_constant (fn , d = None ):
43+ return getattr (sympy , fn ).evalf (n = d )
3944
4045class _Constant_Common (Predefined ):
4146
4247 attributes = ("Constant" , "ReadProtected" )
48+ nargs = 0
4349
4450 def is_constant (self ) -> bool :
45- # free Symbol will be converted to corresponding SymPy symbol
4651 return True
4752
53+ def get_constant (self , precision , evaluation , preference = None ):
54+ ## print("XXX", self, preference)
55+ if preference is None :
56+ preference = evaluation .parse ("Settings`$PreferredBackendMethod" ).evaluate (evaluation ).get_string_value ()
57+ # TODO: validate PreferredBackendMethod is in "mpmath", "numpy", "sympy"
58+ try :
59+ d = get_precision (precision , evaluation )
60+ except PrecisionValueError :
61+ d = None
62+ ## print("XXX1", self, preference)
63+
64+ if preference == "sympy" and hasattr (self , "sympy_name" ):
65+ value = sympy_constant (self .sympy_name , d )
66+ elif preference == "mathmp" and hasattr (self , "mpmath_name" ):
67+ value = mp_constant (self .mpmath_name , d )
68+ elif preference == "numpy_name" and hasattr (self , "numpy_name" ):
69+ value = numpy_constant (self .numpy_name )
70+ elif hasattr (self , "mpmath_name" ):
71+ value = mp_constant (self .mpmath_name , d )
72+ elif hasattr (self , "sympy_name" ):
73+ value = sympy_constant (self .sympy_name , d )
74+ elif hasattr (self , "numpy_name" ):
75+ value = numpy_constant (self .numpy_name )
76+ return PrecisionReal (value )
77+
78+
4879class MPMathConstant (_Constant_Common ):
4980 """Representation of a constant in mpmath, e.g. Pi, E, I, etc."""
5081
@@ -59,25 +90,8 @@ def __init__(self, *args, **kwargs):
5990 self .mpmath_name = strip_context (self .get_name ()).lower ()
6091 self .mathics_to_mpmath [self .__class__ .__name__ ] = self .mpmath_name
6192
62- def get_constant (self , precision , evaluation , preference = "mpmath" ):
63- try :
64- d = get_precision (precision , evaluation )
65- except PrecisionValueError :
66- return
67-
68- mpmath_name = self .mpmath_name
69- if d is None :
70- return MachineReal (mp_fn (mpmath_name ))
71- elif preference == "mpmath" :
72- result = mp_fn (mpmath_name , d )
73- else :
74- sympy_fn = self .to_sympy ()
75- result = sympy_fn .n (d )
76- return PrecisionReal (result )
77-
78-
7993 def to_mpmath (self , args ):
80- if self .mpmath_name is None or len (args ) != self . nargs :
94+ if self .mpmath_name is None or len (args ) != 0 :
8195 return None
8296 return getattr (mpmath , self .mpmath_name )
8397
@@ -97,9 +111,9 @@ def __init__(self, *args, **kwargs):
97111 self .mathics_to_numpy [self .__class__ .__name__ ] = self .numpy_name
98112
99113 def to_numpy (self , args ):
100- if self .numpy_name is None or len (args ) != self . nargs :
114+ if self .numpy_name is None or len (args ) != 0 :
101115 return None
102- return getattr ( numpy , self .numpy_name )
116+ return self .get_constant ( )
103117
104118
105119class SympyConstant (_Constant_Common , SympyObject ):
@@ -108,28 +122,6 @@ class SympyConstant(_Constant_Common, SympyObject):
108122 # Subclasses should define this.
109123 sympy_name = None
110124
111- def get_constant (self , precision , evaluation , preference = "sympy" ):
112- try :
113- d = get_precision (precision , evaluation )
114- except PrecisionValueError :
115- return
116-
117- sympy_fn = self .to_sympy ()
118- if d is None :
119- if hasattr (self , "mpmath_name" ):
120- # Prefer mpmath when precision is not given.
121- result = mp_fn (self .mpmath_name )
122- else :
123- result = sympy_fn ()
124- return MachineReal (result )
125-
126- if preference == "sympy" :
127- result = sympy_fn_n (d )
128- elif hasattr (self , "mpmath_name" ):
129- result = mp_fn (self .mpmath_name , d )
130-
131- return PrecisionReal (result )
132-
133125 def to_sympy (self , expr = None , ** kwargs ):
134126 if expr is None or expr .is_atom ():
135127 result = getattr (sympy , self .sympy_name )
@@ -269,7 +261,7 @@ class E(MPMathConstant, SympyConstant):
269261
270262 def apply_N (self , precision , evaluation ):
271263 "N[E, precision_]"
272- return self .get_constant (precision , evaluation , preference = "sympy" )
264+ return self .get_constant (precision , evaluation )
273265
274266class EulerGamma (MPMathConstant , NumpyConstant , SympyConstant ):
275267 """
@@ -291,7 +283,7 @@ class EulerGamma(MPMathConstant, NumpyConstant, SympyConstant):
291283
292284 def apply_N (self , precision , evaluation ):
293285 "N[EulerGamma, precision_]"
294- return self .get_constant (precision , evaluation , preference = "sympy" )
286+ return self .get_constant (precision , evaluation )
295287
296288
297289class GoldenRatio (MPMathConstant , SympyConstant ):
@@ -312,7 +304,7 @@ class GoldenRatio(MPMathConstant, SympyConstant):
312304
313305 def apply_N (self , precision , evaluation ):
314306 "N[GoldenRatio, precision_]"
315- return self .get_constant (precision , evaluation , preference = "sympy" )
307+ return self .get_constant (precision , evaluation )
316308
317309
318310class Indeterminate (SympyConstant ):
@@ -361,6 +353,8 @@ class Infinity(SympyConstant):
361353 """
362354
363355 sympy_name = "oo"
356+ numpy_name = "Inf"
357+ mpmath_name = "inf"
364358 python_equivalent = math .inf
365359
366360 rules = {
@@ -390,4 +384,4 @@ class Pi(MPMathConstant, SympyConstant):
390384
391385 def apply_N (self , precision , evaluation ):
392386 "N[Pi, precision_]"
393- return self .get_constant (precision , evaluation , preference = "sympy" )
387+ return self .get_constant (precision , evaluation )
0 commit comments