1919 Symbol ,
2020 strip_context ,
2121)
22- from mathics .core .numbers import get_precision , PrecisionValueError
22+ from mathics .core .numbers import get_precision , PrecisionValueError , machine_precision
2323
2424
2525def mp_constant (fn : str , d = None ) -> mpmath .ctx_mp_python .mpf :
@@ -33,7 +33,7 @@ def mp_constant(fn: str, d=None) -> mpmath.ctx_mp_python.mpf:
3333 # ask for a certain number of digits, but the
3434 # accuracy will be less than that. Figure out
3535 # what's up and compensate somehow.
36- mpmath .mp .dps = int_d = int (d )
36+ mpmath .mp .dps = int_d = int (d * 3.321928 )
3737 return getattr (mpmath , fn )(prec = int_d )
3838
3939
@@ -47,10 +47,16 @@ def mp_convert_constant(obj, **kwargs):
4747
4848
4949def numpy_constant (name : str , d = None ) -> float :
50- # TODO: although numpy doesn't support arbitrary precision,
51- # if d is smaller than the precision given we could *reduce* the
52- # float returned.
53- return getattr (numpy , name )
50+ if d :
51+ # by mmatera: Here I have a question:
52+ # 0.0123`2 should be rounded to
53+ # 0.01 or to 0.0123?
54+ # (absolute versus relative accuracy)
55+ val = getattr (numpy , name )
56+ val = numpy .round (val , d )
57+ return val
58+ else :
59+ return getattr (numpy , name )
5460
5561
5662def sympy_constant (fn , d = None ):
@@ -61,13 +67,16 @@ class _Constant_Common(Predefined):
6167
6268 attributes = ("Constant" , "Protected" , "ReadProtected" )
6369 nargs = 0
64- options = {"Method" : "sympy " }
70+ options = {"Method" : "Automatic " }
6571
6672 def apply_N (self , precision , evaluation , options = {}):
6773 "N[%(name)s, precision_?NumericQ, OptionsPattern[%(name)s]]"
6874
6975 preference = self .get_option (options , "Method" , evaluation ).get_string_value ()
70- return self .get_constant (precision , evaluation , preference )
76+ if preference == "Automatic" :
77+ return self .get_constant (precision , evaluation )
78+ else :
79+ return self .get_constant (precision , evaluation , preference )
7180
7281 def apply_N2 (self , evaluation , options = {}):
7382 "N[%(name)s, OptionsPattern[%(name)s]]"
@@ -77,41 +86,47 @@ def is_constant(self) -> bool:
7786 return True
7887
7988 def get_constant (self , precision , evaluation , preference = None ):
80- ## print("XXX", self, preference)
81- if preference is None :
82- preference = (
83- evaluation .parse ("Settings`$PreferredBackendMethod" )
84- .evaluate (evaluation )
85- .get_string_value ()
86- )
87- # TODO: validate PreferredBackendMethod is in "mpmath", "numpy", "sympy"
89+ # first, determine the precision
90+ machine_d = int ( 0.30103 * machine_precision )
8891 d = None
8992 if precision :
9093 try :
9194 d = get_precision (precision , evaluation )
9295 except PrecisionValueError :
9396 pass
9497
95- conversion_fn = MachineReal if d is None else PrecisionReal
96-
97- # print("XXX1", self, preference, conversion_fn)
98-
99- if preference == "sympy" and hasattr (self , "sympy_name" ):
100- value = sympy_constant (self .sympy_name , d )
101- elif preference == "mpmath" and hasattr (self , "mpmath_name" ):
102- value = mp_constant (self .mpmath_name , d )
103- elif preference == "numpy" and hasattr (self , "numpy_name" ):
104- # Note numpy doesn't support arbitarary precision
105- value = numpy_constant (self .numpy_name , d )
106- elif hasattr (self , "mpmath_name" ):
107- value = mp_constant (self .mpmath_name , d )
108- elif hasattr (self , "sympy_name" ):
109- value = sympy_constant (self .sympy_name , d )
110- elif hasattr (self , "numpy_name" ):
111- # Note numpy doesn't support arbitarary precision
112- value = numpy_constant (self .numpy_name , d )
113- return conversion_fn (value )
98+ if d is None :
99+ d = machine_d
114100
101+ # If preference not especified, determine it
102+ # from the precision.
103+ if preference is None :
104+ if d <= machine_d :
105+ preference = "numpy"
106+ else :
107+ preference = "mpmath"
108+ # If preference is not valid, send a message and return.
109+ if not (preference in ("sympy" , "numpy" , "mpmath" )):
110+ evaluation .message (f'{ preference } not in ("sympy", "numpy", "mpmath")' )
111+ return
112+ # Try to determine the numeric value
113+ value = None
114+ if preference == "numpy" :
115+ if hasattr (self , "numpy_name" ):
116+ value = numpy_constant (self .numpy_name )
117+ if d == machine_d :
118+ return MachineReal (value )
119+ elif preference == "sympy" :
120+ if hasattr (self , "sympy_name" ):
121+ value = sympy_constant (self .sympy_name , d )
122+ elif preference == "mpmath" :
123+ if hasattr (self , "sympy_name" ):
124+ value = mp_constant (self .mpmath_name , d )
125+ if value :
126+ return PrecisionReal (sympy .Float (str (value ), d ))
127+ # If the value is not available, return none
128+ # and keep it unevaluated.
129+ return
115130
116131class MPMathConstant (_Constant_Common ):
117132 """Representation of a constant in mpmath, e.g. Pi, E, I, etc."""
0 commit comments