symengine 0.14.0__cp313-cp313t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- symengine/lib/flint-19.dll +0 -0
- symengine/lib/libgcc_s_seh-1.dll +0 -0
- symengine/lib/libgmp-10.dll +0 -0
- symengine/lib/libmpc-3.dll +0 -0
- symengine/lib/libmpfr-6.dll +0 -0
- symengine/lib/libwinpthread-1.dll +0 -0
- symengine/lib/pywrapper.h +220 -0
- symengine/lib/symengine.pxd +955 -0
- symengine/lib/symengine_wrapper.cp313t-win_amd64.lib +0 -0
- symengine/lib/symengine_wrapper.cp313t-win_amd64.pyd +0 -0
- symengine/lib/symengine_wrapper.pxd +78 -0
- symengine/lib/zlib.dll +0 -0
- symengine/lib/zstd.dll +0 -0
- symengine-0.14.0.data/purelib/symengine/__init__.py +79 -0
- symengine-0.14.0.data/purelib/symengine/functions.py +10 -0
- symengine-0.14.0.data/purelib/symengine/lib/__init__.py +0 -0
- symengine-0.14.0.data/purelib/symengine/printing.py +33 -0
- symengine-0.14.0.data/purelib/symengine/sympy_compat.py +4 -0
- symengine-0.14.0.data/purelib/symengine/test_utilities.py +95 -0
- symengine-0.14.0.data/purelib/symengine/tests/__init__.py +0 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_arit.py +261 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_cse.py +17 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_dict_basic.py +28 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_eval.py +67 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_expr.py +28 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_functions.py +432 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_lambdify.py +863 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_logic.py +124 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_matrices.py +757 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_ntheory.py +254 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_number.py +186 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_pickling.py +59 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_printing.py +38 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_sage.py +175 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_series_expansion.py +22 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_sets.py +118 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_solve.py +25 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_subs.py +82 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_symbol.py +179 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_sympify.py +63 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_sympy_compat.py +200 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_sympy_conv.py +835 -0
- symengine-0.14.0.data/purelib/symengine/tests/test_var.py +68 -0
- symengine-0.14.0.data/purelib/symengine/utilities.py +280 -0
- symengine-0.14.0.dist-info/AUTHORS +40 -0
- symengine-0.14.0.dist-info/LICENSE +430 -0
- symengine-0.14.0.dist-info/METADATA +39 -0
- symengine-0.14.0.dist-info/RECORD +50 -0
- symengine-0.14.0.dist-info/WHEEL +5 -0
- symengine-0.14.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,863 @@
|
|
1
|
+
import array
|
2
|
+
import cmath
|
3
|
+
from functools import reduce
|
4
|
+
import itertools
|
5
|
+
from operator import mul
|
6
|
+
import math
|
7
|
+
|
8
|
+
import symengine as se
|
9
|
+
from symengine.test_utilities import raises
|
10
|
+
from symengine import have_numpy
|
11
|
+
import unittest
|
12
|
+
from unittest.case import SkipTest
|
13
|
+
|
14
|
+
try:
|
15
|
+
import sympy
|
16
|
+
from sympy.core.cache import clear_cache
|
17
|
+
import atexit
|
18
|
+
atexit.register(clear_cache)
|
19
|
+
have_sympy = True
|
20
|
+
except ImportError:
|
21
|
+
have_sympy = False
|
22
|
+
|
23
|
+
try:
|
24
|
+
import scipy
|
25
|
+
from scipy import LowLevelCallable
|
26
|
+
have_scipy = True
|
27
|
+
except ImportError:
|
28
|
+
have_scipy = False
|
29
|
+
|
30
|
+
if have_numpy:
|
31
|
+
import numpy as np
|
32
|
+
|
33
|
+
def _size(arr):
|
34
|
+
try:
|
35
|
+
return arr.memview.size
|
36
|
+
except AttributeError:
|
37
|
+
return len(arr)
|
38
|
+
|
39
|
+
|
40
|
+
def isclose(a, b, rtol=1e-13, atol=1e-13):
|
41
|
+
discr = a - b
|
42
|
+
toler = (atol + rtol*abs(a))
|
43
|
+
return abs(discr) < toler
|
44
|
+
|
45
|
+
|
46
|
+
def allclose(vec1, vec2, rtol=1e-13, atol=1e-13):
|
47
|
+
n1, n2 = _size(vec1), _size(vec2)
|
48
|
+
if n1 != n2:
|
49
|
+
return False
|
50
|
+
|
51
|
+
for idx in range(n1):
|
52
|
+
if not isclose(vec1[idx], vec2[idx], rtol, atol):
|
53
|
+
return False
|
54
|
+
return True
|
55
|
+
|
56
|
+
|
57
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
58
|
+
def test_ravel():
|
59
|
+
x = se.symbols('x')
|
60
|
+
exprs = [x+1, x+2, x+3, 1/x, 1/(x*x), 1/(x**3.0)]
|
61
|
+
A = se.DenseMatrix(2, 3, exprs)
|
62
|
+
assert np.all(np.ravel(A, order='C') == exprs)
|
63
|
+
|
64
|
+
|
65
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
66
|
+
def test_Lambdify():
|
67
|
+
n = 7
|
68
|
+
args = x, y, z = se.symbols('x y z')
|
69
|
+
L = se.Lambdify(args, [x+y+z, x**2, (x-y)/z, x*y*z], backend='lambda')
|
70
|
+
assert allclose(L(range(n, n+len(args))),
|
71
|
+
[3*n+3, n**2, -1/(n+2), n*(n+1)*(n+2)])
|
72
|
+
|
73
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
74
|
+
def test_Lambdify_with_opt_level():
|
75
|
+
args = x, y, z = se.symbols('x y z')
|
76
|
+
raises(TypeError, lambda: se.Lambdify(args, [x+y+z, x**2, (x-y)/z, x*y*z], backend='lambda', opt_level=0))
|
77
|
+
|
78
|
+
def _test_Lambdify_Piecewise(Lambdify):
|
79
|
+
x = se.symbols('x')
|
80
|
+
p = se.Piecewise((-x, x<0), (x*x*x, True))
|
81
|
+
f = Lambdify([x], [p])
|
82
|
+
arr = np.linspace(3, 7)
|
83
|
+
assert np.allclose(f(-arr).flat, arr, atol=1e-14, rtol=1e-15)
|
84
|
+
assert np.allclose(f(arr).flat, arr**3, atol=1e-14, rtol=1e-15)
|
85
|
+
|
86
|
+
|
87
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
88
|
+
def test_Lambdify_Piecewise():
|
89
|
+
_test_Lambdify_Piecewise(lambda *args: se.Lambdify(*args, backend='lambda'))
|
90
|
+
if se.have_llvm:
|
91
|
+
_test_Lambdify_Piecewise(lambda *args: se.Lambdify(*args, backend='llvm'))
|
92
|
+
|
93
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
94
|
+
def test_Lambdify_LLVM():
|
95
|
+
n = 7
|
96
|
+
args = x, y, z = se.symbols('x y z')
|
97
|
+
if not se.have_llvm:
|
98
|
+
raises(ValueError, lambda: se.Lambdify(args, [x+y+z, x**2,
|
99
|
+
(x-y)/z, x*y*z],
|
100
|
+
backend='llvm'))
|
101
|
+
raise SkipTest("No LLVM support")
|
102
|
+
L = se.Lambdify(args, [x+y+z, x**2, (x-y)/z, x*y*z], backend='llvm')
|
103
|
+
assert allclose(L(range(n, n+len(args))),
|
104
|
+
[3*n+3, n**2, -1/(n+2), n*(n+1)*(n+2)])
|
105
|
+
|
106
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
107
|
+
def test_Lambdify_LLVM_with_opt_level():
|
108
|
+
for opt_level in range(4):
|
109
|
+
n = 7
|
110
|
+
args = x, y, z = se.symbols('x y z')
|
111
|
+
if not se.have_llvm:
|
112
|
+
raises(ValueError, lambda: se.Lambdify(args, [x+y+z, x**2,
|
113
|
+
(x-y)/z, x*y*z],
|
114
|
+
backend='llvm', opt_level=opt_level))
|
115
|
+
raise SkipTest("No LLVM support")
|
116
|
+
L = se.Lambdify(args, [x+y+z, x**2, (x-y)/z, x*y*z], backend='llvm', opt_level=opt_level)
|
117
|
+
assert allclose(L(range(n, n+len(args))),
|
118
|
+
[3*n+3, n**2, -1/(n+2), n*(n+1)*(n+2)])
|
119
|
+
|
120
|
+
def _get_2_to_2by2():
|
121
|
+
args = x, y = se.symbols('x y')
|
122
|
+
exprs = np.array([[x+y+1.0, x*y],
|
123
|
+
[x/y, x**y]])
|
124
|
+
L = se.Lambdify(args, exprs)
|
125
|
+
|
126
|
+
def check(A, inp):
|
127
|
+
X, Y = inp
|
128
|
+
assert abs(A[0, 0] - (X+Y+1.0)) < 1e-15
|
129
|
+
assert abs(A[0, 1] - (X*Y)) < 1e-15
|
130
|
+
assert abs(A[1, 0] - (X/Y)) < 1e-15
|
131
|
+
assert abs(A[1, 1] - (X**Y)) < 1e-13
|
132
|
+
return L, check
|
133
|
+
|
134
|
+
|
135
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
136
|
+
def test_Lambdify_2dim():
|
137
|
+
lmb, check = _get_2_to_2by2()
|
138
|
+
for inp in [(5, 7), np.array([5, 7]), [5.0, 7.0]]:
|
139
|
+
A = lmb(inp)
|
140
|
+
assert A.shape == (2, 2)
|
141
|
+
check(A, inp)
|
142
|
+
|
143
|
+
|
144
|
+
def _get_array():
|
145
|
+
X, Y, Z = inp = array.array('d', [1, 2, 3])
|
146
|
+
args = x, y, z = se.symbols('x y z')
|
147
|
+
exprs = [x+y+z, se.sin(x)*se.log(y)*se.exp(z)]
|
148
|
+
ref = [X+Y+Z, math.sin(X)*math.log(Y)*math.exp(Z)]
|
149
|
+
|
150
|
+
def check(arr):
|
151
|
+
assert all([abs(x1-x2) < 1e-13 for x1, x2 in zip(ref, arr)])
|
152
|
+
return args, exprs, inp, check
|
153
|
+
|
154
|
+
|
155
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
156
|
+
def test_array():
|
157
|
+
args, exprs, inp, check = _get_array()
|
158
|
+
lmb = se.Lambdify(args, exprs)
|
159
|
+
out = lmb(inp)
|
160
|
+
check(out)
|
161
|
+
|
162
|
+
|
163
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
164
|
+
def test_numpy_array_out_exceptions():
|
165
|
+
args, exprs, inp, check = _get_array()
|
166
|
+
assert len(args) == 3 and len(exprs) == 2
|
167
|
+
lmb = se.Lambdify(args, exprs)
|
168
|
+
|
169
|
+
all_right = np.empty(len(exprs))
|
170
|
+
lmb(inp, out=all_right)
|
171
|
+
|
172
|
+
too_short = np.empty(len(exprs) - 1)
|
173
|
+
raises(ValueError, lambda: (lmb(inp, out=too_short)))
|
174
|
+
|
175
|
+
wrong_dtype = np.empty(len(exprs), dtype=int)
|
176
|
+
raises(ValueError, lambda: (lmb(inp, out=wrong_dtype)))
|
177
|
+
|
178
|
+
read_only = np.empty(len(exprs))
|
179
|
+
read_only.flags['WRITEABLE'] = False
|
180
|
+
raises(ValueError, lambda: (lmb(inp, out=read_only)))
|
181
|
+
|
182
|
+
all_right_broadcast_C = np.empty((4, len(exprs)), order='C')
|
183
|
+
inp_bcast = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
|
184
|
+
lmb(np.array(inp_bcast), out=all_right_broadcast_C)
|
185
|
+
|
186
|
+
noncontig_broadcast = np.empty((4, len(exprs), 3)).transpose((1, 2, 0))
|
187
|
+
raises(ValueError, lambda: (lmb(inp_bcast, out=noncontig_broadcast)))
|
188
|
+
|
189
|
+
all_right_broadcast_F = np.empty((len(exprs), 4), order='F')
|
190
|
+
lmb.order = 'F'
|
191
|
+
lmb(np.array(np.array(inp_bcast).T), out=all_right_broadcast_F)
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
196
|
+
def test_broadcast():
|
197
|
+
a = np.linspace(-np.pi, np.pi)
|
198
|
+
inp = np.ascontiguousarray(np.vstack((np.cos(a), np.sin(a))).T) # 50 rows 2 cols
|
199
|
+
assert inp.flags['C_CONTIGUOUS']
|
200
|
+
x, y = se.symbols('x y')
|
201
|
+
distance = se.Lambdify([x, y], [se.sqrt(x**2 + y**2)])
|
202
|
+
assert np.allclose(distance([inp[0, 0], inp[0, 1]]), [1])
|
203
|
+
dists = distance(inp)
|
204
|
+
assert dists.shape == (50, 1)
|
205
|
+
assert np.allclose(dists, 1)
|
206
|
+
|
207
|
+
|
208
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
209
|
+
def test_broadcast_multiple_extra_dimensions():
|
210
|
+
inp = np.arange(12.).reshape((4, 3, 1))
|
211
|
+
x = se.symbols('x')
|
212
|
+
cb = se.Lambdify([x], [x**2, x**3])
|
213
|
+
assert np.allclose(cb([inp[0, 2]]), [4, 8])
|
214
|
+
out = cb(inp)
|
215
|
+
assert out.shape == (4, 3, 1, 2)
|
216
|
+
out = out.squeeze()
|
217
|
+
assert abs(out[2, 1, 0] - 7**2) < 1e-14
|
218
|
+
assert abs(out[2, 1, 1] - 7**3) < 1e-14
|
219
|
+
assert abs(out[-1, -1, 0] - 11**2) < 1e-14
|
220
|
+
assert abs(out[-1, -1, 1] - 11**3) < 1e-14
|
221
|
+
|
222
|
+
|
223
|
+
def _get_cse_exprs():
|
224
|
+
args = x, y = se.symbols('x y')
|
225
|
+
exprs = [x*x + y, y/(x*x), y*x*x+x]
|
226
|
+
inp = [11, 13]
|
227
|
+
ref = [121+13, 13/121, 13*121 + 11]
|
228
|
+
return args, exprs, inp, ref
|
229
|
+
|
230
|
+
|
231
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
232
|
+
def test_cse():
|
233
|
+
args, exprs, inp, ref = _get_cse_exprs()
|
234
|
+
lmb = se.Lambdify(args, exprs, cse=True)
|
235
|
+
out = lmb(inp)
|
236
|
+
assert allclose(out, ref)
|
237
|
+
|
238
|
+
|
239
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
240
|
+
def test_cse_gh174():
|
241
|
+
x = se.symbols('x')
|
242
|
+
funcs = [se.cos(x)**i for i in range(5)]
|
243
|
+
f_lmb = se.Lambdify([x], funcs)
|
244
|
+
f_cse = se.Lambdify([x], funcs, cse=True)
|
245
|
+
a = np.array([1, 2, 3])
|
246
|
+
assert np.allclose(f_lmb(a), f_cse(a))
|
247
|
+
|
248
|
+
|
249
|
+
def _get_cse_exprs_big():
|
250
|
+
# this is essentially a performance test (can be replaced by a benchmark)
|
251
|
+
x, p = se.symarray('x', 14), se.symarray('p', 14)
|
252
|
+
exp = se.exp
|
253
|
+
exprs = [
|
254
|
+
x[0] + x[1] - x[4] + 36.252574322669, x[0] - x[2] + x[3] + 21.3219379611249,
|
255
|
+
x[3] + x[5] - x[6] + 9.9011158998744, 2*x[3] + x[5] - x[7] + 18.190422234653,
|
256
|
+
3*x[3] + x[5] - x[8] + 24.8679190043357, 4*x[3] + x[5] - x[9] + 29.9336062089226,
|
257
|
+
-x[10] + 5*x[3] + x[5] + 28.5520551531262, 2*x[0] + x[11] - 2*x[4] - 2*x[5] + 32.4401680272417,
|
258
|
+
3*x[1] - x[12] + x[5] + 34.9992934135095, 4*x[1] - x[13] + x[5] + 37.0716199972041,
|
259
|
+
(p[0] - p[1] + 2*p[10] + 2*p[11] - p[12] - 2*p[13] + p[2] + 2*p[5] + 2*p[6] + 2*p[7] +
|
260
|
+
2*p[8] + 2*p[9] - exp(x[0]) + exp(x[1]) - 2*exp(x[10]) - 2*exp(x[11]) + exp(x[12]) +
|
261
|
+
2*exp(x[13]) - exp(x[2]) - 2*exp(x[5]) - 2*exp(x[6]) - 2*exp(x[7]) - 2*exp(x[8]) - 2*exp(x[9])),
|
262
|
+
(-p[0] - p[1] - 15*p[10] - 2*p[11] - 3*p[12] - 4*p[13] - 4*p[2] - 3*p[3] - 2*p[4] - 3*p[6] -
|
263
|
+
6*p[7] - 9*p[8] - 12*p[9] + exp(x[0]) + exp(x[1]) + 15*exp(x[10]) + 2*exp(x[11]) +
|
264
|
+
3*exp(x[12]) + 4*exp(x[13]) + 4*exp(x[2]) + 3*exp(x[3]) + 2*exp(x[4]) + 3*exp(x[6]) +
|
265
|
+
6*exp(x[7]) + 9*exp(x[8]) + 12*exp(x[9])),
|
266
|
+
(-5*p[10] - p[2] - p[3] - p[6] - 2*p[7] - 3*p[8] - 4*p[9] + 5*exp(x[10]) + exp(x[2]) + exp(x[3]) +
|
267
|
+
exp(x[6]) + 2*exp(x[7]) + 3*exp(x[8]) + 4*exp(x[9])),
|
268
|
+
-p[1] - 2*p[11] - 3*p[12] - 4*p[13] - p[4] + exp(x[1]) + 2*exp(x[11]) + 3*exp(x[12]) + 4*exp(x[13]) + exp(x[4]),
|
269
|
+
(-p[10] - 2*p[11] - p[12] - p[13] - p[5] - p[6] - p[7] - p[8] - p[9] + exp(x[10]) +
|
270
|
+
2*exp(x[11]) + exp(x[12]) + exp(x[13]) + exp(x[5]) + exp(x[6]) + exp(x[7]) + exp(x[8]) + exp(x[9]))
|
271
|
+
]
|
272
|
+
return tuple(x) + tuple(p), exprs, np.ones(len(x) + len(p))
|
273
|
+
|
274
|
+
|
275
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
276
|
+
def test_cse_big():
|
277
|
+
args, exprs, inp = _get_cse_exprs_big()
|
278
|
+
lmb = se.Lambdify(args, exprs, cse=True)
|
279
|
+
out = lmb(inp)
|
280
|
+
ref = [expr.xreplace(dict(zip(args, inp))) for expr in exprs]
|
281
|
+
assert allclose(out, ref)
|
282
|
+
|
283
|
+
|
284
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
285
|
+
def test_broadcast_c():
|
286
|
+
n = 3
|
287
|
+
inp = np.arange(2*n).reshape((n, 2))
|
288
|
+
assert inp.flags['C_CONTIGUOUS']
|
289
|
+
lmb, check = _get_2_to_2by2()
|
290
|
+
A = lmb(inp)
|
291
|
+
assert A.shape == (3, 2, 2)
|
292
|
+
for i in range(n):
|
293
|
+
check(A[i, ...], inp[i, :])
|
294
|
+
|
295
|
+
|
296
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
297
|
+
def test_broadcast_fortran():
|
298
|
+
n = 3
|
299
|
+
inp = np.arange(2*n).reshape((n, 2), order='F')
|
300
|
+
lmb, check = _get_2_to_2by2()
|
301
|
+
A = lmb(inp)
|
302
|
+
assert A.shape == (3, 2, 2)
|
303
|
+
for i in range(n):
|
304
|
+
check(A[i, ...], inp[i, :])
|
305
|
+
|
306
|
+
|
307
|
+
def _get_1_to_2by3_matrix(Mtx=se.DenseMatrix):
|
308
|
+
x = se.symbols('x')
|
309
|
+
args = x,
|
310
|
+
exprs = Mtx(2, 3, [x+1, x+2, x+3,
|
311
|
+
1/x, 1/(x*x), 1/(x**3.0)])
|
312
|
+
L = se.Lambdify(args, exprs)
|
313
|
+
|
314
|
+
def check(A, inp):
|
315
|
+
X, = inp
|
316
|
+
assert abs(A[0, 0] - (X+1)) < 1e-15
|
317
|
+
assert abs(A[0, 1] - (X+2)) < 1e-15
|
318
|
+
assert abs(A[0, 2] - (X+3)) < 1e-15
|
319
|
+
assert abs(A[1, 0] - (1/X)) < 1e-15
|
320
|
+
assert abs(A[1, 1] - (1/(X*X))) < 1e-15
|
321
|
+
assert abs(A[1, 2] - (1/(X**3.0))) < 1e-15
|
322
|
+
return L, check
|
323
|
+
|
324
|
+
|
325
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
326
|
+
def test_2dim_Matrix():
|
327
|
+
L, check = _get_1_to_2by3_matrix()
|
328
|
+
inp = [7]
|
329
|
+
check(L(inp), inp)
|
330
|
+
|
331
|
+
|
332
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
333
|
+
@unittest.skipUnless(have_sympy, "SymPy not installed")
|
334
|
+
def test_2dim_Matrix__sympy():
|
335
|
+
import sympy as sp
|
336
|
+
L, check = _get_1_to_2by3_matrix(sp.Matrix)
|
337
|
+
inp = [7]
|
338
|
+
check(L(inp), inp)
|
339
|
+
|
340
|
+
|
341
|
+
|
342
|
+
def _test_2dim_Matrix_broadcast():
|
343
|
+
L, check = _get_1_to_2by3_matrix()
|
344
|
+
inp = range(1, 5)
|
345
|
+
out = L(inp)
|
346
|
+
for i in range(len(inp)):
|
347
|
+
check(out[i, ...], (inp[i],))
|
348
|
+
|
349
|
+
|
350
|
+
|
351
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
352
|
+
def test_2dim_Matrix_broadcast():
|
353
|
+
_test_2dim_Matrix_broadcast()
|
354
|
+
|
355
|
+
|
356
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
357
|
+
def test_2dim_Matrix_broadcast_multiple_extra_dim():
|
358
|
+
L, check = _get_1_to_2by3_matrix()
|
359
|
+
inp = np.arange(1, 4*5*6+1).reshape((4, 5, 6))
|
360
|
+
out = L(inp)
|
361
|
+
assert out.shape == (4, 5, 6, 2, 3)
|
362
|
+
for i, j, k in itertools.product(range(4), range(5), range(6)):
|
363
|
+
check(out[i, j, k, ...], (inp[i, j, k],))
|
364
|
+
|
365
|
+
|
366
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
367
|
+
def test_jacobian():
|
368
|
+
x, y = se.symbols('x, y')
|
369
|
+
args = se.DenseMatrix(2, 1, [x, y])
|
370
|
+
v = se.DenseMatrix(2, 1, [x**3 * y, (x+1)*(y+1)])
|
371
|
+
jac = v.jacobian(args)
|
372
|
+
lmb = se.Lambdify(args, jac)
|
373
|
+
out = np.empty((2, 2))
|
374
|
+
inp = X, Y = 7, 11
|
375
|
+
lmb(inp, out=out)
|
376
|
+
assert np.allclose(out, [[3 * X**2 * Y, X**3],
|
377
|
+
[Y + 1, X + 1]])
|
378
|
+
|
379
|
+
|
380
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
381
|
+
def test_jacobian__broadcast():
|
382
|
+
x, y = se.symbols('x, y')
|
383
|
+
args = se.DenseMatrix(2, 1, [x, y])
|
384
|
+
v = se.DenseMatrix(2, 1, [x**3 * y, (x+1)*(y+1)])
|
385
|
+
jac = v.jacobian(args)
|
386
|
+
lmb = se.Lambdify(args, jac)
|
387
|
+
out = np.empty((3, 2, 2))
|
388
|
+
inp0 = 7, 11
|
389
|
+
inp1 = 8, 13
|
390
|
+
inp2 = 5, 9
|
391
|
+
inp = np.array([inp0, inp1, inp2])
|
392
|
+
lmb(inp, out=out)
|
393
|
+
for idx, (X, Y) in enumerate([inp0, inp1, inp2]):
|
394
|
+
assert np.allclose(out[idx, ...], [[3 * X**2 * Y, X**3],
|
395
|
+
[Y + 1, X + 1]])
|
396
|
+
|
397
|
+
|
398
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
399
|
+
def test_excessive_args():
|
400
|
+
x = se.symbols('x')
|
401
|
+
lmb = se.Lambdify([x], [-x])
|
402
|
+
inp = np.ones(2)
|
403
|
+
out = lmb(inp)
|
404
|
+
assert np.allclose(inp, [1, 1])
|
405
|
+
assert len(out) == 2 # broad casting
|
406
|
+
assert np.allclose(out, -1)
|
407
|
+
|
408
|
+
|
409
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
410
|
+
def test_excessive_out():
|
411
|
+
x = se.symbols('x')
|
412
|
+
lmb = se.Lambdify([x], [-x])
|
413
|
+
inp = np.ones(1)
|
414
|
+
out = np.ones(2)
|
415
|
+
_ = lmb(inp, out=out[:inp.size])
|
416
|
+
assert np.allclose(inp, [1, 1])
|
417
|
+
assert out[0] == -1
|
418
|
+
assert out[1] == 1
|
419
|
+
|
420
|
+
|
421
|
+
def all_indices(shape):
|
422
|
+
return itertools.product(*(range(dim) for dim in shape))
|
423
|
+
|
424
|
+
|
425
|
+
def ravelled(A):
|
426
|
+
try:
|
427
|
+
return A.ravel()
|
428
|
+
except AttributeError:
|
429
|
+
L = []
|
430
|
+
for idx in all_indices(A.memview.shape):
|
431
|
+
L.append(A[idx])
|
432
|
+
return L
|
433
|
+
|
434
|
+
|
435
|
+
def _get_2_to_2by2_list(real=True):
|
436
|
+
args = x, y = se.symbols('x y')
|
437
|
+
exprs = [[x + y*y, y*y], [x*y*y, se.sqrt(x)+y*y]]
|
438
|
+
L = se.Lambdify(args, exprs, real=real)
|
439
|
+
|
440
|
+
def check(A, inp):
|
441
|
+
X, Y = inp
|
442
|
+
assert A.shape[-2:] == (2, 2)
|
443
|
+
ref = [X + Y*Y, Y*Y, X*Y*Y, cmath.sqrt(X)+Y*Y]
|
444
|
+
ravA = ravelled(A)
|
445
|
+
size = _size(ravA)
|
446
|
+
for i in range(size//4):
|
447
|
+
for j in range(4):
|
448
|
+
assert isclose(ravA[i*4 + j], ref[j])
|
449
|
+
return L, check
|
450
|
+
|
451
|
+
|
452
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
453
|
+
def test_2_to_2by2():
|
454
|
+
L, check = _get_2_to_2by2_list()
|
455
|
+
inp = [13, 17]
|
456
|
+
A = L(inp)
|
457
|
+
check(A, inp)
|
458
|
+
|
459
|
+
|
460
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
461
|
+
def test_unsafe_real():
|
462
|
+
L, check = _get_2_to_2by2_list()
|
463
|
+
inp = np.array([13., 17.])
|
464
|
+
out = np.empty(4)
|
465
|
+
L.unsafe_real(inp, out)
|
466
|
+
check(out.reshape((2, 2)), inp)
|
467
|
+
|
468
|
+
|
469
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
470
|
+
def test_unsafe_complex():
|
471
|
+
L, check = _get_2_to_2by2_list(real=False)
|
472
|
+
assert not L.real
|
473
|
+
inp = np.array([13+11j, 7+4j], dtype=np.complex128)
|
474
|
+
out = np.empty(4, dtype=np.complex128)
|
475
|
+
L.unsafe_complex(inp, out)
|
476
|
+
check(out.reshape((2, 2)), inp)
|
477
|
+
|
478
|
+
|
479
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
480
|
+
def test_itertools_chain():
|
481
|
+
args, exprs, inp, check = _get_array()
|
482
|
+
L = se.Lambdify(args, exprs)
|
483
|
+
inp = itertools.chain([inp[0]], (inp[1],), [inp[2]])
|
484
|
+
A = L(inp)
|
485
|
+
check(A)
|
486
|
+
|
487
|
+
|
488
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
489
|
+
def test_complex_1():
|
490
|
+
x = se.Symbol('x')
|
491
|
+
lmb = se.Lambdify([x], [1j + x], real=False)
|
492
|
+
assert abs(lmb([11+13j])[0] -
|
493
|
+
(11 + 14j)) < 1e-15
|
494
|
+
|
495
|
+
|
496
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
497
|
+
def test_complex_2():
|
498
|
+
x = se.Symbol('x')
|
499
|
+
lmb = se.Lambdify([x], [3 + x - 1j], real=False)
|
500
|
+
assert abs(lmb([11+13j])[0] -
|
501
|
+
(14 + 12j)) < 1e-15
|
502
|
+
|
503
|
+
|
504
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
505
|
+
def test_more_than_255_args():
|
506
|
+
# SymPy's lambdify can handle at most 255 arguments
|
507
|
+
# this is a proof of concept that this limitation does
|
508
|
+
# not affect SymEngine's Lambdify class
|
509
|
+
n = 257
|
510
|
+
x = se.symarray('x', n)
|
511
|
+
p, q, r = 17, 42, 13
|
512
|
+
terms = [i*s for i, s in enumerate(x, p)]
|
513
|
+
exprs = [se.add(*terms), r + x[0], -99]
|
514
|
+
callback = se.Lambdify(x, exprs)
|
515
|
+
input_arr = np.arange(q, q + n*n).reshape((n, n))
|
516
|
+
out = callback(input_arr)
|
517
|
+
ref = np.empty((n, 3))
|
518
|
+
coeffs = np.arange(p, p + n, dtype=np.int64)
|
519
|
+
for i in range(n):
|
520
|
+
ref[i, 0] = coeffs.dot(np.arange(q + n*i, q + n*(i+1), dtype=np.int64))
|
521
|
+
ref[i, 1] = q + n*i + r
|
522
|
+
ref[:, 2] = -99
|
523
|
+
assert np.allclose(out, ref)
|
524
|
+
|
525
|
+
|
526
|
+
def _Lambdify_heterogeneous_output(Lambdify):
|
527
|
+
x, y = se.symbols('x, y')
|
528
|
+
args = se.DenseMatrix(2, 1, [x, y])
|
529
|
+
v = se.DenseMatrix(2, 1, [x**3 * y, (x+1)*(y+1)])
|
530
|
+
jac = v.jacobian(args)
|
531
|
+
exprs = [jac, x+y, v, (x+1)*(y+1)]
|
532
|
+
lmb = Lambdify(args, *exprs)
|
533
|
+
inp0 = 7, 11
|
534
|
+
inp1 = 8, 13
|
535
|
+
inp2 = 5, 9
|
536
|
+
inp = np.array([inp0, inp1, inp2])
|
537
|
+
o_j, o_xpy, o_v, o_xty = lmb(inp)
|
538
|
+
for idx, (X, Y) in enumerate([inp0, inp1, inp2]):
|
539
|
+
assert np.allclose(o_j[idx, ...], [[3 * X**2 * Y, X**3],
|
540
|
+
[Y + 1, X + 1]])
|
541
|
+
assert np.allclose(o_xpy[idx, ...], [X+Y])
|
542
|
+
assert np.allclose(o_v[idx, ...], [[X**3 * Y], [(X+1)*(Y+1)]])
|
543
|
+
assert np.allclose(o_xty[idx, ...], [(X+1)*(Y+1)])
|
544
|
+
|
545
|
+
|
546
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
547
|
+
def test_Lambdify_heterogeneous_output():
|
548
|
+
_Lambdify_heterogeneous_output(se.Lambdify)
|
549
|
+
|
550
|
+
|
551
|
+
def _sympy_lambdify_heterogeneous_output(cb, Mtx):
|
552
|
+
x, y = se.symbols('x, y')
|
553
|
+
args = Mtx(2, 1, [x, y])
|
554
|
+
v = Mtx(2, 1, [x**3 * y, (x+1)*(y+1)])
|
555
|
+
jac = v.jacobian(args)
|
556
|
+
exprs = [jac, x+y, v, (x+1)*(y+1)]
|
557
|
+
lmb = cb(args, exprs)
|
558
|
+
inp0 = 7, 11
|
559
|
+
inp1 = 8, 13
|
560
|
+
inp2 = 5, 9
|
561
|
+
for idx, (X, Y) in enumerate([inp0, inp1, inp2]):
|
562
|
+
o_j, o_xpy, o_v, o_xty = lmb(X, Y)
|
563
|
+
assert np.allclose(o_j, [[3 * X**2 * Y, X**3],
|
564
|
+
[Y + 1, X + 1]])
|
565
|
+
assert np.allclose(o_xpy, [X+Y])
|
566
|
+
assert np.allclose(o_v, [[X**3 * Y], [(X+1)*(Y+1)]])
|
567
|
+
assert np.allclose(o_xty, [(X+1)*(Y+1)])
|
568
|
+
|
569
|
+
|
570
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
571
|
+
@unittest.skipUnless(have_sympy, "SymPy not installed")
|
572
|
+
def test_lambdify__sympy():
|
573
|
+
import sympy as sp
|
574
|
+
_sympy_lambdify_heterogeneous_output(se.lambdify, se.DenseMatrix)
|
575
|
+
_sympy_lambdify_heterogeneous_output(sp.lambdify, sp.Matrix)
|
576
|
+
|
577
|
+
|
578
|
+
def _test_Lambdify_scalar_vector_matrix(Lambdify):
|
579
|
+
if not have_numpy:
|
580
|
+
return
|
581
|
+
args = x, y = se.symbols('x y')
|
582
|
+
vec = se.DenseMatrix([x+y, x*y])
|
583
|
+
jac = vec.jacobian(se.DenseMatrix(args))
|
584
|
+
f = Lambdify(args, x**y, vec, jac)
|
585
|
+
assert f.n_exprs == 3
|
586
|
+
s, v, m = f([2, 3])
|
587
|
+
assert s == 2**3
|
588
|
+
assert np.allclose(v, [[2+3], [2*3]])
|
589
|
+
assert np.allclose(m, [
|
590
|
+
[1, 1],
|
591
|
+
[3, 2]
|
592
|
+
])
|
593
|
+
|
594
|
+
for inp in [[2, 3, 5, 7], np.array([[2, 3], [5, 7]])]:
|
595
|
+
s2, v2, m2 = f(inp)
|
596
|
+
assert np.allclose(s2, [2**3, 5**7])
|
597
|
+
assert np.allclose(v2, [
|
598
|
+
[[2+3], [2*3]],
|
599
|
+
[[5+7], [5*7]]
|
600
|
+
])
|
601
|
+
assert np.allclose(m2, [
|
602
|
+
[
|
603
|
+
[1, 1],
|
604
|
+
[3, 2]
|
605
|
+
],
|
606
|
+
[
|
607
|
+
[1, 1],
|
608
|
+
[7, 5]
|
609
|
+
]
|
610
|
+
])
|
611
|
+
|
612
|
+
|
613
|
+
def test_Lambdify_scalar_vector_matrix():
|
614
|
+
_test_Lambdify_scalar_vector_matrix(lambda *args: se.Lambdify(*args, backend='lambda'))
|
615
|
+
if se.have_llvm:
|
616
|
+
_test_Lambdify_scalar_vector_matrix(lambda *args: se.Lambdify(*args, backend='llvm'))
|
617
|
+
|
618
|
+
|
619
|
+
def test_Lambdify_scalar_vector_matrix_cse():
|
620
|
+
_test_Lambdify_scalar_vector_matrix(lambda *args: se.Lambdify(*args, backend='lambda', cse=True))
|
621
|
+
if se.have_llvm:
|
622
|
+
_test_Lambdify_scalar_vector_matrix(lambda *args: se.Lambdify(*args, backend='llvm', cse=True))
|
623
|
+
|
624
|
+
|
625
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
626
|
+
def test_Lambdify_gh174():
|
627
|
+
# Tests array broadcasting if the expressions form an N-dimensional array
|
628
|
+
# of say shape (k, l, m) and it contains 'n' arguments (x1, ... xn), then
|
629
|
+
# if the user provides a Fortran ordered (column-major) input array of shape
|
630
|
+
# (n, o, p, q), then the returned array will be of shape (k, l, m, o, p, q)
|
631
|
+
args = x, y = se.symbols('x y')
|
632
|
+
nargs = len(args)
|
633
|
+
vec1 = se.DenseMatrix([x, x**2, x**3])
|
634
|
+
assert vec1.shape == (3, 1)
|
635
|
+
assert np.asarray(vec1).shape == (3, 1)
|
636
|
+
lmb1 = se.Lambdify([x], vec1)
|
637
|
+
out1 = lmb1(3)
|
638
|
+
assert out1.shape == (3, 1)
|
639
|
+
assert np.all(out1 == [[3], [9], [27]])
|
640
|
+
assert lmb1([2, 3]).shape == (2, 3, 1)
|
641
|
+
lmb1.order = 'F' # change order
|
642
|
+
out1a = lmb1([2, 3])
|
643
|
+
assert out1a.shape == (3, 1, 2)
|
644
|
+
ref1a_squeeze = [[2, 3],
|
645
|
+
[4, 9],
|
646
|
+
[8, 27]]
|
647
|
+
assert np.all(out1a.squeeze() == ref1a_squeeze)
|
648
|
+
assert out1a.flags['F_CONTIGUOUS']
|
649
|
+
assert not out1a.flags['C_CONTIGUOUS']
|
650
|
+
|
651
|
+
lmb2c = se.Lambdify(args, vec1, x+y, order='C')
|
652
|
+
lmb2f = se.Lambdify(args, vec1, x+y, order='F')
|
653
|
+
for out2a in [lmb2c([2, 3]), lmb2f([2, 3])]:
|
654
|
+
assert np.all(out2a[0] == [[2], [4], [8]])
|
655
|
+
assert out2a[0].ndim == 2
|
656
|
+
assert out2a[1] == 5
|
657
|
+
assert out2a[1].ndim == 0
|
658
|
+
inp2b = np.array([
|
659
|
+
[2.0, 3.0],
|
660
|
+
[1.0, 2.0],
|
661
|
+
[0.0, 6.0]
|
662
|
+
])
|
663
|
+
raises(ValueError, lambda: (lmb2c(inp2b.T)))
|
664
|
+
out2c = lmb2c(inp2b)
|
665
|
+
out2f = lmb2f(np.asfortranarray(inp2b.T))
|
666
|
+
assert out2c[0].shape == (3, 3, 1)
|
667
|
+
assert out2f[0].shape == (3, 1, 3)
|
668
|
+
for idx, (_x, _y) in enumerate(inp2b):
|
669
|
+
assert np.all(out2c[0][idx, ...] == [[_x], [_x**2], [_x**3]])
|
670
|
+
|
671
|
+
assert np.all(out2c[1] == [5, 3, 6])
|
672
|
+
assert np.all(out2f[1] == [5, 3, 6])
|
673
|
+
assert out2c[1].shape == (3,)
|
674
|
+
assert out2f[1].shape == (3,)
|
675
|
+
|
676
|
+
def _mtx3(_x, _y):
|
677
|
+
return [[_x**row_idx + _y**col_idx for col_idx in range(3)]
|
678
|
+
for row_idx in range(4)]
|
679
|
+
mtx3c = np.array(_mtx3(x, y), order='C')
|
680
|
+
mtx3f = np.array(_mtx3(x, y), order='F')
|
681
|
+
lmb3c = se.Lambdify([x, y], x*y, mtx3c, vec1, order='C')
|
682
|
+
lmb3f = se.Lambdify([x, y], x*y, mtx3f, vec1, order='F')
|
683
|
+
inp3c = np.array([[2., 3], [3, 4], [5, 7], [6, 2], [3, 1]])
|
684
|
+
inp3f = np.asfortranarray(inp3c.T)
|
685
|
+
raises(ValueError, lambda: (lmb3c(inp3c.T)))
|
686
|
+
out3c = lmb3c(inp3c)
|
687
|
+
assert out3c[0].shape == (5,)
|
688
|
+
assert out3c[1].shape == (5, 4, 3)
|
689
|
+
assert out3c[2].shape == (5, 3, 1) # user can apply numpy.squeeze if they want to.
|
690
|
+
for a, b in zip(out3c, lmb3c(np.ravel(inp3c))):
|
691
|
+
assert np.all(a == b)
|
692
|
+
|
693
|
+
out3f = lmb3f(inp3f)
|
694
|
+
assert out3f[0].shape == (5,)
|
695
|
+
assert out3f[1].shape == (4, 3, 5)
|
696
|
+
assert out3f[2].shape == (3, 1, 5) # user can apply numpy.squeeze if they want to.
|
697
|
+
for a, b in zip(out3f, lmb3f(np.ravel(inp3f, order='F'))):
|
698
|
+
assert np.all(a == b)
|
699
|
+
|
700
|
+
for idx, (_x, _y) in enumerate(inp3c):
|
701
|
+
assert out3c[0][idx] == _x*_y
|
702
|
+
assert out3f[0][idx] == _x*_y
|
703
|
+
assert np.all(out3c[1][idx, ...] == _mtx3(_x, _y))
|
704
|
+
assert np.all(out3f[1][..., idx] == _mtx3(_x, _y))
|
705
|
+
assert np.all(out3c[2][idx, ...] == [[_x],[_x**2],[_x**3]])
|
706
|
+
assert np.all(out3f[2][..., idx] == [[_x],[_x**2],[_x**3]])
|
707
|
+
|
708
|
+
|
709
|
+
def _get_Ndim_args_exprs_funcs(order):
|
710
|
+
args = x, y = se.symbols('x y')
|
711
|
+
|
712
|
+
# Higher dimensional inputs
|
713
|
+
def f_a(index, _x, _y):
|
714
|
+
a, b, c, d = index
|
715
|
+
return _x**a + _y**b + (_x+_y)**-d
|
716
|
+
|
717
|
+
nd_exprs_a = np.zeros((3, 5, 1, 4), dtype=object, order=order)
|
718
|
+
for index in np.ndindex(*nd_exprs_a.shape):
|
719
|
+
nd_exprs_a[index] = f_a(index, x, y)
|
720
|
+
|
721
|
+
def f_b(index, _x, _y):
|
722
|
+
a, b, c = index
|
723
|
+
return b/(_x + _y)
|
724
|
+
|
725
|
+
nd_exprs_b = np.zeros((1, 7, 1), dtype=object, order=order)
|
726
|
+
for index in np.ndindex(*nd_exprs_b.shape):
|
727
|
+
nd_exprs_b[index] = f_b(index, x, y)
|
728
|
+
return args, nd_exprs_a, nd_exprs_b, f_a, f_b
|
729
|
+
|
730
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
731
|
+
def test_Lambdify_Ndimensional_order_C():
|
732
|
+
args, nd_exprs_a, nd_exprs_b, f_a, f_b = _get_Ndim_args_exprs_funcs(order='C')
|
733
|
+
lmb4 = se.Lambdify(args, nd_exprs_a, nd_exprs_b, order='C')
|
734
|
+
nargs = len(args)
|
735
|
+
|
736
|
+
inp_extra_shape = (3, 5, 4)
|
737
|
+
inp_shape = inp_extra_shape + (nargs,)
|
738
|
+
inp4 = np.arange(reduce(mul, inp_shape)*1.0).reshape(inp_shape, order='C')
|
739
|
+
out4a, out4b = lmb4(inp4)
|
740
|
+
assert out4a.ndim == 7
|
741
|
+
assert out4a.shape == inp_extra_shape + nd_exprs_a.shape
|
742
|
+
assert out4b.ndim == 6
|
743
|
+
assert out4b.shape == inp_extra_shape + nd_exprs_b.shape
|
744
|
+
raises(ValueError, lambda: (lmb4(inp4.T)))
|
745
|
+
for b, c, d in np.ndindex(inp_extra_shape):
|
746
|
+
_x, _y = inp4[b, c, d, :]
|
747
|
+
for index in np.ndindex(*nd_exprs_a.shape):
|
748
|
+
assert np.isclose(out4a[(b, c, d) + index], f_a(index, _x, _y))
|
749
|
+
for index in np.ndindex(*nd_exprs_b.shape):
|
750
|
+
assert np.isclose(out4b[(b, c, d) + index], f_b(index, _x, _y))
|
751
|
+
|
752
|
+
|
753
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
754
|
+
def test_Lambdify_Ndimensional_order_F():
|
755
|
+
args, nd_exprs_a, nd_exprs_b, f_a, f_b = _get_Ndim_args_exprs_funcs(order='F')
|
756
|
+
lmb4 = se.Lambdify(args, nd_exprs_a, nd_exprs_b, order='F')
|
757
|
+
nargs = len(args)
|
758
|
+
|
759
|
+
inp_extra_shape = (3, 5, 4)
|
760
|
+
inp_shape = (nargs,)+inp_extra_shape
|
761
|
+
inp4 = np.arange(reduce(mul, inp_shape)*1.0).reshape(inp_shape, order='F')
|
762
|
+
out4a, out4b = lmb4(inp4)
|
763
|
+
assert out4a.ndim == 7
|
764
|
+
assert out4a.shape == nd_exprs_a.shape + inp_extra_shape
|
765
|
+
assert out4b.ndim == 6
|
766
|
+
assert out4b.shape == nd_exprs_b.shape + inp_extra_shape
|
767
|
+
raises(ValueError, lambda: (lmb4(inp4.T)))
|
768
|
+
for b, c, d in np.ndindex(inp_extra_shape):
|
769
|
+
_x, _y = inp4[:, b, c, d]
|
770
|
+
for index in np.ndindex(*nd_exprs_a.shape):
|
771
|
+
assert np.isclose(out4a[index + (b, c, d)], f_a(index, _x, _y))
|
772
|
+
for index in np.ndindex(*nd_exprs_b.shape):
|
773
|
+
assert np.isclose(out4b[index + (b, c, d)], f_b(index, _x, _y))
|
774
|
+
|
775
|
+
|
776
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
777
|
+
def test_Lambdify_inp_exceptions():
|
778
|
+
args = x, y = se.symbols('x y')
|
779
|
+
lmb1 = se.Lambdify([x], x**2)
|
780
|
+
raises(ValueError, lambda: (lmb1([])))
|
781
|
+
assert lmb1(4) == 16
|
782
|
+
assert np.all(lmb1([4, 2]) == [16, 4])
|
783
|
+
|
784
|
+
lmb2 = se.Lambdify(args, x**2+y**2)
|
785
|
+
assert lmb2([2, 3]) == 13
|
786
|
+
raises(ValueError, lambda: lmb2([]))
|
787
|
+
raises(ValueError, lambda: lmb2([2]))
|
788
|
+
raises(ValueError, lambda: lmb2([2, 3, 4]))
|
789
|
+
assert np.all(lmb2([2, 3, 4, 5]) == [13, 16+25])
|
790
|
+
|
791
|
+
def _mtx(_x, _y):
|
792
|
+
return [
|
793
|
+
[_x-_y, _y**2],
|
794
|
+
[_x+_y, _x**2],
|
795
|
+
[_x*_y, _x**_y]
|
796
|
+
]
|
797
|
+
|
798
|
+
mtx = np.array(_mtx(x, y), order='F')
|
799
|
+
lmb3 = se.Lambdify(args, mtx, order='F')
|
800
|
+
inp3a = [2, 3]
|
801
|
+
assert np.all(lmb3(inp3a) == _mtx(*inp3a))
|
802
|
+
inp3b = np.array([2, 3, 4, 5, 3, 2, 1, 5])
|
803
|
+
for inp in [inp3b, inp3b.tolist(), inp3b.reshape((2, 4), order='F')]:
|
804
|
+
out3b = lmb3(inp)
|
805
|
+
assert out3b.shape == (3, 2, 4)
|
806
|
+
for i in range(4):
|
807
|
+
assert np.all(out3b[..., i] == _mtx(*inp3b[2*i:2*(i+1)]))
|
808
|
+
raises(ValueError, lambda: lmb3(inp3b.reshape((4, 2))))
|
809
|
+
raises(ValueError, lambda: lmb3(inp3b.reshape((2, 4)).T))
|
810
|
+
|
811
|
+
|
812
|
+
@unittest.skipUnless(have_scipy, "Scipy not installed")
|
813
|
+
def test_scipy():
|
814
|
+
from scipy import integrate
|
815
|
+
import numpy as np
|
816
|
+
args = t, x = se.symbols('t, x')
|
817
|
+
lmb = se.Lambdify(args, [se.exp(-x*t)/t**5], as_scipy=True)
|
818
|
+
res = integrate.nquad(lmb, [[1, np.inf], [0, np.inf]])
|
819
|
+
assert abs(res[0] - 0.2) < 1e-7
|
820
|
+
|
821
|
+
|
822
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
823
|
+
def test_as_ctypes():
|
824
|
+
import numpy as np
|
825
|
+
import ctypes
|
826
|
+
x, y, z = se.symbols('x, y, z')
|
827
|
+
l = se.Lambdify([x, y, z], [x+y+z, x*y*z+1])
|
828
|
+
addr1, addr2 = l.as_ctypes()
|
829
|
+
inp = np.array([1,2,3], dtype=np.double)
|
830
|
+
out = np.array([0, 0], dtype=np.double)
|
831
|
+
addr1(out.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), inp.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), addr2)
|
832
|
+
assert np.all(out == [6, 7])
|
833
|
+
|
834
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
835
|
+
@unittest.skipUnless(se.have_llvm, "No LLVM support")
|
836
|
+
def test_llvm_float():
|
837
|
+
import numpy as np
|
838
|
+
import ctypes
|
839
|
+
from symengine.lib.symengine_wrapper import LLVMFloat
|
840
|
+
x, y, z = se.symbols('x, y, z')
|
841
|
+
l = se.Lambdify([x, y, z], [se.Min(x, y), se.Max(y, z)], dtype=np.float32, backend='llvm')
|
842
|
+
inp = np.array([1,2,3], dtype=np.float32)
|
843
|
+
exp_out = np.array([1, 3], dtype=np.float32)
|
844
|
+
out = l(inp)
|
845
|
+
assert type(l) == LLVMFloat
|
846
|
+
assert out.dtype == np.float32
|
847
|
+
assert np.allclose(out, exp_out)
|
848
|
+
|
849
|
+
@unittest.skipUnless(have_numpy, "Numpy not installed")
|
850
|
+
@unittest.skipUnless(se.have_llvm, "No LLVM support")
|
851
|
+
@unittest.skipUnless(se.have_llvm_long_double, "No LLVM IEEE-80 bit support")
|
852
|
+
def test_llvm_long_double():
|
853
|
+
import numpy as np
|
854
|
+
import ctypes
|
855
|
+
from symengine.lib.symengine_wrapper import LLVMLongDouble
|
856
|
+
x, y, z = se.symbols('x, y, z')
|
857
|
+
l = se.Lambdify([x, y, z], [2*x, y/z], dtype=np.longdouble, backend='llvm')
|
858
|
+
inp = np.array([1,2,3], dtype=np.longdouble)
|
859
|
+
exp_out = np.array([2, 2.0/3.0], dtype=np.longdouble)
|
860
|
+
out = l(inp)
|
861
|
+
assert type(l) == LLVMLongDouble
|
862
|
+
assert out.dtype == np.longdouble
|
863
|
+
assert np.allclose(out, exp_out)
|