1919 Symbol ,
2020 strip_context ,
2121)
22- from mathics .core .numbers import get_precision , PrecisionValueError , machine_precision
22+ from mathics .core .numbers import get_precision , PrecisionValueError
2323
2424
2525def mp_constant (fn : str , d = None ) -> mpmath .ctx_mp_python .mpf :
@@ -29,11 +29,7 @@ def mp_constant(fn: str, d=None) -> mpmath.ctx_mp_python.mpf:
2929 if d is None :
3030 return getattr (mpmath , fn )()
3131 else :
32- # TODO: In some functions like Pi, you can
33- # ask for a certain number of digits, but the
34- # accuracy will be less than that. Figure out
35- # what's up and compensate somehow.
36- mpmath .mp .dps = int_d = int (d * 3.321928 )
32+ mpmath .mp .dps = int_d = int (d )
3733 return getattr (mpmath , fn )(prec = int_d )
3834
3935
@@ -47,16 +43,7 @@ def mp_convert_constant(obj, **kwargs):
4743
4844
4945def numpy_constant (name : str , d = None ) -> float :
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 )
46+ return getattr (numpy , name )
6047
6148
6249def sympy_constant (fn , d = None ):
@@ -67,75 +54,46 @@ class _Constant_Common(Predefined):
6754
6855 attributes = ("Constant" , "Protected" , "ReadProtected" )
6956 nargs = 0
70- options = {"Method" : "Automatic" }
71-
72- def apply_N (self , precision , evaluation , options = {}):
73- "N[%(name)s, precision_?NumericQ, OptionsPattern[%(name)s]]"
7457
75- preference = self .get_option (options , "Method" , evaluation ).get_string_value ()
76- if preference == "Automatic" :
77- return self .get_constant (precision , evaluation )
78- else :
79- return self .get_constant (precision , evaluation , preference )
80-
81- def apply_N2 (self , evaluation , options = {}):
82- "N[%(name)s, OptionsPattern[%(name)s]]"
83- return self .apply_N (None , evaluation , options )
58+ def apply_N (self , precision , evaluation ):
59+ "N[%(name)s, precision_]"
60+ return self .get_constant (precision , evaluation )
8461
8562 def is_constant (self ) -> bool :
8663 return True
8764
8865 def get_constant (self , precision , evaluation , preference = None ):
89- # first, determine the precision
90- machine_d = int ( 0.30103 * machine_precision )
91- d = None
92- if precision :
93- try :
94- d = get_precision (precision , evaluation )
95- except PrecisionValueError :
96- pass
66+ ## print("XXX", self, preference)
67+ if preference is None :
68+ preference = (
69+ evaluation .parse ("Settings`$PreferredBackendMethod" )
70+ .evaluate (evaluation )
71+ .get_string_value ()
72+ )
73+ # TODO: validate PreferredBackendMethod is in "mpmath", "numpy", "sympy"
74+ try :
75+ d = get_precision (precision , evaluation )
76+ except PrecisionValueError :
77+ d = None
9778
98- if d is None :
99- d = machine_d
79+ conversion_fn = MachineReal if d is None else PrecisionReal
10080
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 == "mpmath" and not hasattr (self , "mpmath_name" ):
115- preference = "numpy"
116- elif preference == "sympy" and not hasattr (self , "sympy_name" ):
117- preference = "numpy"
118-
119- if preference == "numpy" and not hasattr (self , "numpy_name" ):
120- if hasattr (self , "sympy_name" ):
121- preference = "sympy"
122- elif hasattr (self , "mpmath_name" ):
123- preference = "mpmath"
124- else :
125- preference = ""
126- if preference == "numpy" :
81+ # print("XXX1", self, preference, conversion_fn)
82+
83+ if preference == "sympy" and hasattr (self , "sympy_name" ):
84+ value = sympy_constant (self .sympy_name , d )
85+ elif preference == "mpmath" and hasattr (self , "mpmath_name" ):
86+ value = mp_constant (self .mpmath_name , d )
87+ elif preference == "numpy" and hasattr (self , "numpy_name" ):
88+ value = numpy_constant (self .numpy_name )
89+ elif hasattr (self , "mpmath_name" ):
90+ value = mp_constant (self .mpmath_name , d )
91+ elif hasattr (self , "sympy_name" ):
92+ value = sympy_constant (self .sympy_name , d )
93+ elif hasattr (self , "numpy_name" ):
12794 value = numpy_constant (self .numpy_name )
128- if d == machine_d :
129- return MachineReal (value )
130- if preference == "sympy" :
131- value = sympy_constant (self .sympy_name , d + 2 )
132- if preference == "mpmath" :
133- value = mp_constant (self .mpmath_name , d * 2 )
134- if value :
135- return PrecisionReal (sympy .Float (str (value ), d ))
136- # If the value is not available, return none
137- # and keep it unevaluated.
138- return
95+ return conversion_fn (value )
96+
13997
14098class MPMathConstant (_Constant_Common ):
14199 """Representation of a constant in mpmath, e.g. Pi, E, I, etc."""
@@ -194,22 +152,22 @@ def to_sympy(self, expr=None, **kwargs):
194152 return None
195153
196154
197- class Catalan (MPMathConstant , SympyConstant ):
155+ class Catalan (MPMathConstant , NumpyConstant , SympyConstant ):
198156 """
199157 <dl>
200158 <dt>'Catalan'
201159 <dd>is Catalan's constant with numerical value \u2243 0.915966.
202160 </dl>
203161
204162 >> Catalan // N
205- = 0.915965594177219
163+ = 0.915966
206164
207165 >> N[Catalan, 20]
208166 = 0.91596559417721901505
209167 """
210168
211169 mpmath_name = "catalan"
212- # numpy_name = "catalan" ## This is not defined in numpy
170+ numpy_name = "catalan"
213171 sympy_name = "Catalan"
214172
215173
@@ -281,13 +239,10 @@ def to_numpy(self, expr=None, **kwargs):
281239 # return mpmath.degree
282240 return numpy .pi / 180
283241
284- def apply_N (self , precision , evaluation , options = {} ):
285- "N[Degree, precision_, OptionsPattern[%(name)s] ]"
242+ def apply_N (self , precision , evaluation ):
243+ "N[Degree, precision_]"
286244 try :
287- if precision :
288- d = get_precision (precision , evaluation )
289- else :
290- d = get_precision (Symbol ("System`MachinePrecision" ), evaluation )
245+ d = get_precision (precision , evaluation )
291246 except PrecisionValueError :
292247 return
293248
@@ -323,8 +278,8 @@ class E(MPMathConstant, NumpyConstant, SympyConstant):
323278 numpy_name = "e"
324279 sympy_name = "E"
325280
326- def apply_N (self , precision , evaluation , options = {} ):
327- "N[E, precision_, OptionsPattern[%(name)s] ]"
281+ def apply_N (self , precision , evaluation ):
282+ "N[E, precision_]"
328283 return self .get_constant (precision , evaluation )
329284
330285
@@ -355,10 +310,9 @@ class Glaisher(MPMathConstant):
355310 </dl>
356311
357312 >> N[Glaisher]
358- = 1.28242712910062
313+ = 1.28243
359314 >> N[Glaisher, 50]
360- = 1.2824271291006226368753425688697917277676889273250
361- # 1.2824271291006219541941391071304678916931152343750
315+ = 1.2824271291006219541941391071304678916931152343750
362316 """
363317
364318 mpmath_name = "glaisher"
@@ -372,7 +326,7 @@ class GoldenRatio(MPMathConstant, SympyConstant):
372326 </dl>
373327
374328 >> GoldenRatio // N
375- = 1.61803398874989
329+ = 1.61803
376330 >> N[GoldenRatio, 40]
377331 = 1.618033988749894848204586834365638117720
378332 """
@@ -445,10 +399,9 @@ class Khinchin(MPMathConstant):
445399 </dl>
446400
447401 >> N[Khinchin]
448- = 2.68545200106531
402+ = 2.68545
449403 >> N[Khinchin, 50]
450- = 2.6854520010653064453097148354817956938203822939945
451- # = 2.6854520010653075701156922150403261184692382812500
404+ = 2.6854520010653075701156922150403261184692382812500
452405 """
453406
454407 mpmath_name = "khinchin"
@@ -463,19 +416,7 @@ class Pi(MPMathConstant, SympyConstant):
463416
464417 >> N[Pi]
465418 = 3.14159
466-
467- Force using the value given from numpy to compute Pi.
468- >> N[Pi, Method->"numpy"]
469- = 3.14159
470-
471- Force using the value given from sympy to compute Pi to 3 places,
472- two places after the decimal point.
473-
474- Note that sympy is the default method.
475- >> N[Pi, 3, Method->"sympy"]
476- = 3.14
477-
478- >> N[Pi, 50]
419+ >> N[Pi, 50]
479420 = 3.1415926535897932384626433832795028841971693993751
480421 >> Attributes[Pi]
481422 = {Constant, Protected, ReadProtected}
0 commit comments