Skip to content

Commit 248ac70

Browse files
committed
Make sure np.asanyarray is applied least number of times
1 parent 8376e3a commit 248ac70

File tree

1 file changed

+52
-49
lines changed

1 file changed

+52
-49
lines changed

symengine/lib/symengine_wrapper.pyx

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4331,52 +4331,26 @@ def has_symbol(obj, symbol=None):
43314331

43324332

43334333
cdef class _Lambdify(object):
4334-
"""
4335-
Lambdify instances are callbacks that numerically evaluate their symbolic
4336-
expressions from user provided input (real or complex) into (possibly user
4337-
provided) output buffers (real or complex). Multidimensional data are
4338-
processed in their most cache-friendly way (i.e. "ravelled").
4339-
4340-
Parameters
4341-
----------
4342-
args: iterable of Symbols
4343-
\*exprs: array_like of expressions
4344-
the shape of exprs is preserved
4345-
real : bool
4346-
Whether datatype is ``double`` (``double complex`` otherwise).
4347-
4348-
Returns
4349-
-------
4350-
callback instance with signature f(inp, out=None)
4351-
4352-
Examples
4353-
--------
4354-
>>> from symengine import var, Lambdify
4355-
>>> var('x y z')
4356-
>>> f = Lambdify([x, y, z], [x+y+z, x*y*z])
4357-
>>> f([2, 3, 4])
4358-
[ 9., 24.]
4359-
>>> out = np.array(2)
4360-
>>> f(x, out); out
4361-
[ 9., 24.]
4362-
4363-
"""
43644334
cdef size_t args_size, tot_out_size
43654335
cdef list out_shapes
43664336
cdef readonly bint real
43674337
cdef readonly int n_exprs
43684338
cdef public str order
43694339
cdef vector[int] accum_out_sizes
43704340
cdef object numpy_dtype
4341+
cdef args
4342+
cdef tuple exprs
43714343

43724344
def __cinit__(self, args, *exprs, cppbool real=True, order='C'):
43734345
cdef vector[int] out_sizes
4346+
self.args = np.asanyarray(args)
4347+
self.args_size = self.args.size
4348+
self.exprs = tuple(np.asanyarray(expr) for expr in exprs)
4349+
self.out_shapes = [expr.shape for expr in self.exprs]
4350+
self.n_exprs = len(self.exprs)
43744351
self.real = real
43754352
self.order = order
43764353
self.numpy_dtype = np.float64 if self.real else np.complex128
4377-
self.out_shapes = [np.asarray(expr).shape for expr in exprs]
4378-
self.n_exprs = len(exprs)
4379-
self.args_size = np.asarray(args).size
43804354
if self.args_size == 0:
43814355
raise NotImplementedError("Support for zero arguments not yet supported")
43824356
self.tot_out_size = 0
@@ -4388,24 +4362,24 @@ cdef class _Lambdify(object):
43884362
for j in range(i):
43894363
self.accum_out_sizes[i] += out_sizes[j]
43904364

4391-
def __init__(self, args, *exprs, cppbool real=True, order='C'):
4365+
def __init__(self, *args, **kwargs):
43924366
cdef:
43934367
Basic e_
43944368
size_t ri, ci, nr, nc
43954369
symengine.MatrixBase *mtx
43964370
RCP[const symengine.Basic] b_
43974371
symengine.vec_basic args_, outs_
43984372

4399-
for arg in np.ravel(args, order=order):
4373+
for arg in np.ravel(self.args, order=self.order):
44004374
e_ = _sympify(arg)
44014375
args_.push_back(e_.thisptr)
44024376

4403-
for curr_expr in map(np.array, exprs):
4377+
for curr_expr in self.exprs:
44044378
if curr_expr.ndim == 0:
44054379
e_ = _sympify(curr_expr.item())
44064380
outs_.push_back(e_.thisptr)
44074381
else:
4408-
for e in np.ravel(curr_expr, order=order):
4382+
for e in np.ravel(curr_expr, order=self.order):
44094383
e_ = _sympify(e)
44104384
outs_.push_back(e_.thisptr)
44114385
self._init(args_, outs_)
@@ -4422,18 +4396,14 @@ cdef class _Lambdify(object):
44224396
int inp_offset=0, int out_offset=0):
44234397
raise ValueError("Not supported")
44244398

4425-
cpdef eval_real(self,
4426-
inp,
4427-
out):
4399+
cpdef eval_real(self, inp, out):
44284400
if inp.size != self.args_size:
44294401
raise ValueError("Size of inp incompatible with number of args.")
44304402
if out.size != self.tot_out_size:
44314403
raise ValueError("Size of out incompatible with number of exprs.")
44324404
self.unsafe_real(inp, out)
44334405

4434-
cpdef eval_complex(self,
4435-
inp,
4436-
out):
4406+
cpdef eval_complex(self, inp, out):
44374407
if inp.size != self.args_size:
44384408
raise ValueError("Size of inp incompatible with number of args.")
44394409
if out.size != self.tot_out_size:
@@ -4451,12 +4421,6 @@ cdef class _Lambdify(object):
44514421
If ``None``: an output container will be allocated (NumPy ndarray).
44524422
If ``len(exprs) > 0`` output is found in the corresponding
44534423
order.
4454-
order : 'C' or 'F'
4455-
C- or Fortran-contiguous memory layout. Note that this affects
4456-
broadcasting: e.g. a (m, n) matrix taking 3 arguments and given a
4457-
(k, l, 3) (C-contiguous) input will give a (k, l, m, n) shaped output,
4458-
whereas a (3, k, l) (C-contiguous) input will give a (m, n, k, l) shaped
4459-
output. If ``None`` order is taken as ``self.order`` (from initialization).
44604424
44614425
Returns
44624426
-------
@@ -4603,6 +4567,45 @@ IF HAVE_SYMENGINE_LLVM:
46034567

46044568

46054569
def Lambdify(args, *exprs, cppbool real=True, backend=None, order='C'):
4570+
"""
4571+
Lambdify instances are callbacks that numerically evaluate their symbolic
4572+
expressions from user provided input (real or complex) into (possibly user
4573+
provided) output buffers (real or complex). Multidimensional data are
4574+
processed in their most cache-friendly way (i.e. "ravelled").
4575+
4576+
Parameters
4577+
----------
4578+
args: iterable of Symbols
4579+
\*exprs: array_like of expressions
4580+
the shape of exprs is preserved
4581+
real : bool
4582+
Whether datatype is ``double`` (``double complex`` otherwise).
4583+
backend : str
4584+
'llvm' or 'lambda'. When ``None`` the environment variable
4585+
'SYMENGINE_LAMBDIFY_BACKEND' is used (taken as 'lambda' if unset).
4586+
order : 'C' or 'F'
4587+
C- or Fortran-contiguous memory layout. Note that this affects
4588+
broadcasting: e.g. a (m, n) matrix taking 3 arguments and given a
4589+
(k, l, 3) (C-contiguous) input will give a (k, l, m, n) shaped output,
4590+
whereas a (3, k, l) (C-contiguous) input will give a (m, n, k, l) shaped
4591+
output. If ``None`` order is taken as ``self.order`` (from initialization).
4592+
4593+
Returns
4594+
-------
4595+
callback instance with signature f(inp, out=None)
4596+
4597+
Examples
4598+
--------
4599+
>>> from symengine import var, Lambdify
4600+
>>> var('x y z')
4601+
>>> f = Lambdify([x, y, z], [x+y+z, x*y*z])
4602+
>>> f([2, 3, 4])
4603+
[ 9., 24.]
4604+
>>> out = np.array(2)
4605+
>>> f(x, out); out
4606+
[ 9., 24.]
4607+
4608+
"""
46064609
if backend is None:
46074610
backend = os.getenv('SYMENGINE_LAMBDIFY_BACKEND', "lambda")
46084611
if backend == "llvm":

0 commit comments

Comments
 (0)