Skip to content

Commit 189cf33

Browse files
mmaterammatera
andauthored
Plot compile to lambdify compile (#1538)
@bdlucas1, this is a proposal about where I think the lambdify code should be located. If this is not too disruptive, the next thing would be to use this code in the different places where we need a "compiled" versions of WL expressions, like in table generations, numerical integration, and optimizers. --------- Co-authored-by: mmatera <mmatera@fisica.unlp.edu.ar>
1 parent 98ece5d commit 189cf33

File tree

10 files changed

+286
-123
lines changed

10 files changed

+286
-123
lines changed

mathics/builtin/compilation.py

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from types import FunctionType
1212

1313
from mathics.builtin.box.compilation import CompiledCodeBox
14-
from mathics.core.atoms import Integer, String
14+
from mathics.core.atoms import Complex, Integer, Rational, Real, String
1515
from mathics.core.attributes import A_HOLD_ALL, A_PROTECTED
1616
from mathics.core.builtin import Builtin
1717
from mathics.core.convert.expression import to_mathics_list
@@ -33,6 +33,14 @@
3333
sort_order = "mathics.builtin.code-compilation"
3434

3535

36+
NAME_OF_TYPE = {
37+
bool: String("True of False"),
38+
int: String("integer"),
39+
float: String("machine-size real number"),
40+
complex: String("machine-size complex number"),
41+
}
42+
43+
3644
class Compile(Builtin):
3745
"""
3846
<url>:WMA link:https://reference.wolfram.com/language/ref/Compile.html</url>
@@ -83,7 +91,6 @@ class Compile(Builtin):
8391

8492
def eval(self, vars, expr, evaluation: Evaluation):
8593
"Compile[vars_, expr_]"
86-
8794
if not vars.has_form("List", None):
8895
evaluation.message("Compile", "invars")
8996
return
@@ -167,7 +174,15 @@ def to_sympy(self, *args, **kwargs):
167174
raise NotImplementedError
168175

169176
def __hash__(self):
170-
return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack
177+
try:
178+
return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack
179+
except TypeError:
180+
return hash(
181+
(
182+
"CompiledCode",
183+
self.cfunc,
184+
)
185+
) # XXX hack
171186

172187
def atom_to_boxes(self, f, evaluation: Evaluation):
173188
return CompiledCodeBox(String(self.__str__()), evaluation=evaluation)
@@ -191,30 +206,86 @@ class CompiledFunction(Builtin):
191206
192207
"""
193208

194-
messages = {"argerr": "Invalid argument `1` should be Integer, Real or boolean."}
209+
messages = {
210+
"argerr": "Invalid argument `1` should be Integer, Real, Complex or boolean.",
211+
"cfsa": "Argument `1` at position `2` should be a `3`.",
212+
}
195213
summary_text = "A CompiledFunction object."
196214

197215
def eval(self, argnames, expr, code, args, evaluation: Evaluation):
198216
"CompiledFunction[argnames_, expr_, code_CompiledCode][args__]"
199-
200217
argseq = args.get_sequence()
201218

202219
if len(argseq) != len(code.args):
203220
return
204221

205222
py_args = []
206-
for arg in argseq:
207-
if isinstance(arg, Integer):
208-
py_args.append(arg.get_int_value())
209-
elif arg.sameQ(SymbolTrue):
210-
py_args.append(True)
211-
elif arg.sameQ(SymbolFalse):
212-
py_args.append(False)
213-
else:
214-
py_args.append(arg.round_to_float(evaluation))
223+
args_spec = code.args or []
224+
if len(args_spec) != len(argseq):
225+
evaluation.mesage(
226+
"CompiledFunction",
227+
"cfct",
228+
Integer(len(argseq)),
229+
Integer(len(args_spec)),
230+
)
231+
return
232+
for pos, (arg, spec) in enumerate(zip(argseq, args_spec)):
233+
# TODO: check if the types are consistent.
234+
# If not, show a message.
235+
try:
236+
spec_type = spec.type
237+
if spec_type is float:
238+
if isinstance(arg, (Integer, Rational, Real)):
239+
val = spec_type(arg.value)
240+
else:
241+
raise TypeError
242+
elif spec_type is int:
243+
if isinstance(arg, (Integer, Rational, Real)):
244+
val = spec_type(arg.value)
245+
# If arg.value was not an integer, show a message but accept it:
246+
if val != arg.value:
247+
evaluation.message(
248+
"CompiledFunction",
249+
"cfsa",
250+
arg,
251+
Integer(pos + 1),
252+
NAME_OF_TYPE[spec_type],
253+
)
254+
else:
255+
raise TypeError
256+
elif spec_type is bool:
257+
if arg.sameQ(SymbolTrue):
258+
val = True
259+
elif arg.sameQ(SymbolFalse):
260+
val = False
261+
else:
262+
raise TypeError
263+
elif spec_type is complex:
264+
if isinstance(arg, Complex):
265+
value = arg.value
266+
val = complex(value[0].value, value[1].value)
267+
elif isinstance(arg, (Integer, Rational, Real)):
268+
val = complex(arg.value)
269+
else:
270+
raise TypeError
271+
else:
272+
raise TypeError
273+
except (ValueError, TypeError):
274+
# Fallback by replace values in expr?
275+
evaluation.message(
276+
"CompiledFunction",
277+
"cfsa",
278+
arg,
279+
Integer(pos + 1),
280+
NAME_OF_TYPE[spec.type],
281+
)
282+
return
283+
py_args.append(val)
215284
try:
216285
result = code.cfunc(*py_args)
217286
except (TypeError, ctypes.ArgumentError):
218287
evaluation.message("CompiledFunction", "argerr", args)
219288
return
289+
except Exception:
290+
return
220291
return from_python(result)

mathics/compile/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ class CompileArg:
1010
def __init__(self, name, type):
1111
self.name = name
1212
self.type = type
13+
14+
def __repr__(self):
15+
return f"{self.name}:{self.type}"

mathics/core/atoms.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,11 +628,11 @@ def element_order(self) -> tuple:
628628
of an expression. The tuple is ultimately compared lexicographically.
629629
"""
630630

631-
value = self._value
632-
value, prec = float(value), value._prec
631+
sympy_float = self._value
632+
value, prec = float(sympy_float), sympy_float._prec
633633
# For large values, use the sympy.Float value...
634634
if math.isinf(value):
635-
value, prec = self._value, value._prec
635+
return (BASIC_ATOM_NUMBER_ELT_ORDER, sympy_float, 0, 2, prec)
636636

637637
return (BASIC_ATOM_NUMBER_ELT_ORDER, value, 0, 2, prec)
638638

0 commit comments

Comments
 (0)