Spaces:
Sleeping
Sleeping
| from sympy.external import import_module | |
| from sympy.testing.pytest import raises | |
| import ctypes | |
| if import_module('llvmlite'): | |
| import sympy.printing.llvmjitcode as g | |
| else: | |
| disabled = True | |
| import sympy | |
| from sympy.abc import a, b, n | |
| # copied from numpy.isclose documentation | |
| def isclose(a, b): | |
| rtol = 1e-5 | |
| atol = 1e-8 | |
| return abs(a-b) <= atol + rtol*abs(b) | |
| def test_simple_expr(): | |
| e = a + 1.0 | |
| f = g.llvm_callable([a], e) | |
| res = float(e.subs({a: 4.0}).evalf()) | |
| jit_res = f(4.0) | |
| assert isclose(jit_res, res) | |
| def test_two_arg(): | |
| e = 4.0*a + b + 3.0 | |
| f = g.llvm_callable([a, b], e) | |
| res = float(e.subs({a: 4.0, b: 3.0}).evalf()) | |
| jit_res = f(4.0, 3.0) | |
| assert isclose(jit_res, res) | |
| def test_func(): | |
| e = 4.0*sympy.exp(-a) | |
| f = g.llvm_callable([a], e) | |
| res = float(e.subs({a: 1.5}).evalf()) | |
| jit_res = f(1.5) | |
| assert isclose(jit_res, res) | |
| def test_two_func(): | |
| e = 4.0*sympy.exp(-a) + sympy.exp(b) | |
| f = g.llvm_callable([a, b], e) | |
| res = float(e.subs({a: 1.5, b: 2.0}).evalf()) | |
| jit_res = f(1.5, 2.0) | |
| assert isclose(jit_res, res) | |
| def test_two_sqrt(): | |
| e = 4.0*sympy.sqrt(a) + sympy.sqrt(b) | |
| f = g.llvm_callable([a, b], e) | |
| res = float(e.subs({a: 1.5, b: 2.0}).evalf()) | |
| jit_res = f(1.5, 2.0) | |
| assert isclose(jit_res, res) | |
| def test_two_pow(): | |
| e = a**1.5 + b**7 | |
| f = g.llvm_callable([a, b], e) | |
| res = float(e.subs({a: 1.5, b: 2.0}).evalf()) | |
| jit_res = f(1.5, 2.0) | |
| assert isclose(jit_res, res) | |
| def test_callback(): | |
| e = a + 1.2 | |
| f = g.llvm_callable([a], e, callback_type='scipy.integrate.test') | |
| m = ctypes.c_int(1) | |
| array_type = ctypes.c_double * 1 | |
| inp = {a: 2.2} | |
| array = array_type(inp[a]) | |
| jit_res = f(m, array) | |
| res = float(e.subs(inp).evalf()) | |
| assert isclose(jit_res, res) | |
| def test_callback_cubature(): | |
| e = a + 1.2 | |
| f = g.llvm_callable([a], e, callback_type='cubature') | |
| m = ctypes.c_int(1) | |
| array_type = ctypes.c_double * 1 | |
| inp = {a: 2.2} | |
| array = array_type(inp[a]) | |
| out_array = array_type(0.0) | |
| jit_ret = f(m, array, None, m, out_array) | |
| assert jit_ret == 0 | |
| res = float(e.subs(inp).evalf()) | |
| assert isclose(out_array[0], res) | |
| def test_callback_two(): | |
| e = 3*a*b | |
| f = g.llvm_callable([a, b], e, callback_type='scipy.integrate.test') | |
| m = ctypes.c_int(2) | |
| array_type = ctypes.c_double * 2 | |
| inp = {a: 0.2, b: 1.7} | |
| array = array_type(inp[a], inp[b]) | |
| jit_res = f(m, array) | |
| res = float(e.subs(inp).evalf()) | |
| assert isclose(jit_res, res) | |
| def test_callback_alt_two(): | |
| d = sympy.IndexedBase('d') | |
| e = 3*d[0]*d[1] | |
| f = g.llvm_callable([n, d], e, callback_type='scipy.integrate.test') | |
| m = ctypes.c_int(2) | |
| array_type = ctypes.c_double * 2 | |
| inp = {d[0]: 0.2, d[1]: 1.7} | |
| array = array_type(inp[d[0]], inp[d[1]]) | |
| jit_res = f(m, array) | |
| res = float(e.subs(inp).evalf()) | |
| assert isclose(jit_res, res) | |
| def test_multiple_statements(): | |
| # Match return from CSE | |
| e = [[(b, 4.0*a)], [b + 5]] | |
| f = g.llvm_callable([a], e) | |
| b_val = e[0][0][1].subs({a: 1.5}) | |
| res = float(e[1][0].subs({b: b_val}).evalf()) | |
| jit_res = f(1.5) | |
| assert isclose(jit_res, res) | |
| f_callback = g.llvm_callable([a], e, callback_type='scipy.integrate.test') | |
| m = ctypes.c_int(1) | |
| array_type = ctypes.c_double * 1 | |
| array = array_type(1.5) | |
| jit_callback_res = f_callback(m, array) | |
| assert isclose(jit_callback_res, res) | |
| def test_cse(): | |
| e = a*a + b*b + sympy.exp(-a*a - b*b) | |
| e2 = sympy.cse(e) | |
| f = g.llvm_callable([a, b], e2) | |
| res = float(e.subs({a: 2.3, b: 0.1}).evalf()) | |
| jit_res = f(2.3, 0.1) | |
| assert isclose(jit_res, res) | |
| def eval_cse(e, sub_dict): | |
| tmp_dict = {} | |
| for tmp_name, tmp_expr in e[0]: | |
| e2 = tmp_expr.subs(sub_dict) | |
| e3 = e2.subs(tmp_dict) | |
| tmp_dict[tmp_name] = e3 | |
| return [e.subs(sub_dict).subs(tmp_dict) for e in e[1]] | |
| def test_cse_multiple(): | |
| e1 = a*a | |
| e2 = a*a + b*b | |
| e3 = sympy.cse([e1, e2]) | |
| raises(NotImplementedError, | |
| lambda: g.llvm_callable([a, b], e3, callback_type='scipy.integrate')) | |
| f = g.llvm_callable([a, b], e3) | |
| jit_res = f(0.1, 1.5) | |
| assert len(jit_res) == 2 | |
| res = eval_cse(e3, {a: 0.1, b: 1.5}) | |
| assert isclose(res[0], jit_res[0]) | |
| assert isclose(res[1], jit_res[1]) | |
| def test_callback_cubature_multiple(): | |
| e1 = a*a | |
| e2 = a*a + b*b | |
| e3 = sympy.cse([e1, e2, 4*e2]) | |
| f = g.llvm_callable([a, b], e3, callback_type='cubature') | |
| # Number of input variables | |
| ndim = 2 | |
| # Number of output expression values | |
| outdim = 3 | |
| m = ctypes.c_int(ndim) | |
| fdim = ctypes.c_int(outdim) | |
| array_type = ctypes.c_double * ndim | |
| out_array_type = ctypes.c_double * outdim | |
| inp = {a: 0.2, b: 1.5} | |
| array = array_type(inp[a], inp[b]) | |
| out_array = out_array_type() | |
| jit_ret = f(m, array, None, fdim, out_array) | |
| assert jit_ret == 0 | |
| res = eval_cse(e3, inp) | |
| assert isclose(out_array[0], res[0]) | |
| assert isclose(out_array[1], res[1]) | |
| assert isclose(out_array[2], res[2]) | |
| def test_symbol_not_found(): | |
| e = a*a + b | |
| raises(LookupError, lambda: g.llvm_callable([a], e)) | |
| def test_bad_callback(): | |
| e = a | |
| raises(ValueError, lambda: g.llvm_callable([a], e, callback_type='bad_callback')) | |