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.
Files changed (50) hide show
  1. symengine/lib/flint-19.dll +0 -0
  2. symengine/lib/libgcc_s_seh-1.dll +0 -0
  3. symengine/lib/libgmp-10.dll +0 -0
  4. symengine/lib/libmpc-3.dll +0 -0
  5. symengine/lib/libmpfr-6.dll +0 -0
  6. symengine/lib/libwinpthread-1.dll +0 -0
  7. symengine/lib/pywrapper.h +220 -0
  8. symengine/lib/symengine.pxd +955 -0
  9. symengine/lib/symengine_wrapper.cp313t-win_amd64.lib +0 -0
  10. symengine/lib/symengine_wrapper.cp313t-win_amd64.pyd +0 -0
  11. symengine/lib/symengine_wrapper.pxd +78 -0
  12. symengine/lib/zlib.dll +0 -0
  13. symengine/lib/zstd.dll +0 -0
  14. symengine-0.14.0.data/purelib/symengine/__init__.py +79 -0
  15. symengine-0.14.0.data/purelib/symengine/functions.py +10 -0
  16. symengine-0.14.0.data/purelib/symengine/lib/__init__.py +0 -0
  17. symengine-0.14.0.data/purelib/symengine/printing.py +33 -0
  18. symengine-0.14.0.data/purelib/symengine/sympy_compat.py +4 -0
  19. symengine-0.14.0.data/purelib/symengine/test_utilities.py +95 -0
  20. symengine-0.14.0.data/purelib/symengine/tests/__init__.py +0 -0
  21. symengine-0.14.0.data/purelib/symengine/tests/test_arit.py +261 -0
  22. symengine-0.14.0.data/purelib/symengine/tests/test_cse.py +17 -0
  23. symengine-0.14.0.data/purelib/symengine/tests/test_dict_basic.py +28 -0
  24. symengine-0.14.0.data/purelib/symengine/tests/test_eval.py +67 -0
  25. symengine-0.14.0.data/purelib/symengine/tests/test_expr.py +28 -0
  26. symengine-0.14.0.data/purelib/symengine/tests/test_functions.py +432 -0
  27. symengine-0.14.0.data/purelib/symengine/tests/test_lambdify.py +863 -0
  28. symengine-0.14.0.data/purelib/symengine/tests/test_logic.py +124 -0
  29. symengine-0.14.0.data/purelib/symengine/tests/test_matrices.py +757 -0
  30. symengine-0.14.0.data/purelib/symengine/tests/test_ntheory.py +254 -0
  31. symengine-0.14.0.data/purelib/symengine/tests/test_number.py +186 -0
  32. symengine-0.14.0.data/purelib/symengine/tests/test_pickling.py +59 -0
  33. symengine-0.14.0.data/purelib/symengine/tests/test_printing.py +38 -0
  34. symengine-0.14.0.data/purelib/symengine/tests/test_sage.py +175 -0
  35. symengine-0.14.0.data/purelib/symengine/tests/test_series_expansion.py +22 -0
  36. symengine-0.14.0.data/purelib/symengine/tests/test_sets.py +118 -0
  37. symengine-0.14.0.data/purelib/symengine/tests/test_solve.py +25 -0
  38. symengine-0.14.0.data/purelib/symengine/tests/test_subs.py +82 -0
  39. symengine-0.14.0.data/purelib/symengine/tests/test_symbol.py +179 -0
  40. symengine-0.14.0.data/purelib/symengine/tests/test_sympify.py +63 -0
  41. symengine-0.14.0.data/purelib/symengine/tests/test_sympy_compat.py +200 -0
  42. symengine-0.14.0.data/purelib/symengine/tests/test_sympy_conv.py +835 -0
  43. symengine-0.14.0.data/purelib/symengine/tests/test_var.py +68 -0
  44. symengine-0.14.0.data/purelib/symengine/utilities.py +280 -0
  45. symengine-0.14.0.dist-info/AUTHORS +40 -0
  46. symengine-0.14.0.dist-info/LICENSE +430 -0
  47. symengine-0.14.0.dist-info/METADATA +39 -0
  48. symengine-0.14.0.dist-info/RECORD +50 -0
  49. symengine-0.14.0.dist-info/WHEEL +5 -0
  50. 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)