@@ -2143,6 +2143,7 @@ have_mpfr = False
2143
2143
have_mpc = False
2144
2144
have_piranha = False
2145
2145
have_flint = False
2146
+ have_llvm = False
2146
2147
2147
2148
IF HAVE_SYMENGINE_MPFR:
2148
2149
have_mpfr = True
@@ -2166,6 +2167,9 @@ IF HAVE_SYMENGINE_PIRANHA:
2166
2167
IF HAVE_SYMENGINE_FLINT:
2167
2168
have_flint = True
2168
2169
2170
+ IF HAVE_SYMENGINE_LLVM:
2171
+ have_llvm = True
2172
+
2169
2173
def eval (x , long prec ):
2170
2174
if prec <= 53 :
2171
2175
return eval_complex_double(x)
@@ -2566,7 +2570,7 @@ ctypedef fused ValueType:
2566
2570
cython.double
2567
2571
2568
2572
2569
- cdef class Lambdify (object ):
2573
+ cdef class _Lambdify (object ):
2570
2574
"""
2571
2575
Lambdify instances are callbacks that numerically evaluate their symbolic
2572
2576
expressions from user provided input (real or complex) into (possibly user
@@ -2598,22 +2602,21 @@ cdef class Lambdify(object):
2598
2602
cdef size_t args_size, out_size
2599
2603
cdef tuple out_shape
2600
2604
cdef readonly bool real
2601
- cdef vector[symengine.LambdaRealDoubleVisitor] lambda_double
2602
- cdef vector[symengine.LambdaComplexDoubleVisitor] lambda_double_complex
2603
2605
2604
2606
def __cinit__ (self , args , exprs , bool real = True ):
2607
+ self .real = real
2608
+ self .out_shape = get_shape(exprs)
2609
+ self .args_size = _size(args)
2610
+ self .out_size = reduce (mul, self .out_shape)
2611
+
2612
+
2613
+ def __init__ (self , args , exprs , bool real = True ):
2605
2614
cdef:
2606
- symengine.vec_basic args_
2607
- symengine.vec_basic outs_
2608
2615
Basic e_
2609
2616
size_t ri, ci, nr, nc
2610
2617
symengine.MatrixBase * mtx
2611
2618
RCP[const symengine.Basic] b_
2612
- int idx = 0
2613
- self .real = real
2614
- self .out_shape = get_shape(exprs)
2615
- self .args_size = _size(args)
2616
- self .out_size = reduce (mul, self .out_shape)
2619
+ symengine.vec_basic args_, outs_
2617
2620
2618
2621
if isinstance (args, DenseMatrix):
2619
2622
nr = args.nrows()
@@ -2640,35 +2643,32 @@ cdef class Lambdify(object):
2640
2643
e_ = sympify(e)
2641
2644
outs_.push_back(e_.thisptr)
2642
2645
2643
- if real:
2644
- self .lambda_double.resize(1 )
2645
- self .lambda_double[0 ].init(args_, outs_)
2646
- else :
2647
- self .lambda_double_complex.resize(1 )
2648
- self .lambda_double_complex[0 ].init(args_, outs_)
2649
-
2646
+ self ._init(args_, outs_)
2650
2647
2651
- cdef void _eval (self , ValueType[:: 1 ] inp, ValueType[:: 1 ] out ):
2652
- cdef size_t idx, ninp = inp.size, nout = out.size
2648
+ cdef _init (self , symengine.vec_basic & args_, symengine.vec_basic & outs_ ):
2649
+ raise ValueError ( " Not supported " )
2653
2650
2654
- if inp.size != self .args_size:
2655
- raise ValueError (" Size of inp incompatible with number of args." )
2656
- if out.size != self .out_size:
2657
- raise ValueError (" Size of out incompatible with number of exprs." )
2651
+ cdef void _eval_real(self , double [::1 ] inp, double [::1 ] out):
2652
+ raise ValueError (" Not supported" )
2658
2653
2659
- # Convert expr_subs to doubles write to out
2660
- if ValueType == cython.double:
2661
- self .lambda_double[0 ].call(& out[0 ], & inp[0 ])
2662
- else :
2663
- self .lambda_double_complex[0 ].call(& out[0 ], & inp[0 ])
2654
+ cdef void _eval_complex(self , double complex [::1 ] inp, double complex [::1 ] out):
2655
+ raise ValueError (" Not supported" )
2664
2656
2665
2657
# the two cpdef:ed methods below may use void return type
2666
2658
# once Cython 0.23 (from 2015) is acceptable as requirement.
2667
2659
cpdef unsafe_real(self , double [::1 ] inp, double [::1 ] out):
2668
- self ._eval(inp, out)
2660
+ if inp.size != self .args_size:
2661
+ raise ValueError (" Size of inp incompatible with number of args." )
2662
+ if out.size != self .out_size:
2663
+ raise ValueError (" Size of out incompatible with number of exprs." )
2664
+ self ._eval_real(inp, out)
2669
2665
2670
2666
cpdef unsafe_complex(self , double complex [::1 ] inp, double complex [::1 ] out):
2671
- self ._eval(inp, out)
2667
+ if inp.size != self .args_size:
2668
+ raise ValueError (" Size of inp incompatible with number of args." )
2669
+ if out.size != self .out_size:
2670
+ raise ValueError (" Size of out incompatible with number of exprs." )
2671
+ self ._eval_complex(inp, out)
2672
2672
2673
2673
def __call__ (self , inp , out = None , use_numpy = None ):
2674
2674
"""
@@ -2712,18 +2712,16 @@ cdef class Lambdify(object):
2712
2712
import numpy as np
2713
2713
2714
2714
if use_numpy:
2715
+ numpy_dtype = np.float64 if self .real else np.complex128
2715
2716
if isinstance (inp, DenseMatrix):
2717
+ arr = np.empty(inp_size, dtype = numpy_dtype)
2716
2718
if self .real:
2717
- arr = np.empty(inp_size, dtype = np.float64)
2718
2719
inp.dump_real(arr)
2719
- inp = arr
2720
2720
else :
2721
- arr = np.empty(inp_size, dtype = np.complex128)
2722
2721
inp.dump_complex(arr)
2723
- inp = arr
2722
+ inp = arr
2724
2723
else :
2725
- inp = np.ascontiguousarray(inp, dtype = np.float64 if
2726
- self .real else np.complex128)
2724
+ inp = np.ascontiguousarray(inp, dtype = numpy_dtype)
2727
2725
if inp.ndim > 1 :
2728
2726
inp = inp.ravel()
2729
2727
else :
@@ -2732,8 +2730,7 @@ cdef class Lambdify(object):
2732
2730
if out is None :
2733
2731
# allocate output container
2734
2732
if use_numpy:
2735
- out = np.empty(new_out_size, dtype = np.float64 if
2736
- self .real else np.complex128)
2733
+ out = np.empty(new_out_size, dtype = numpy_dtype)
2737
2734
else :
2738
2735
if self .real:
2739
2736
out = cython.view.array((new_out_size,),
@@ -2749,7 +2746,7 @@ cdef class Lambdify(object):
2749
2746
except AttributeError :
2750
2747
out = np.asarray(out)
2751
2748
out_dtype = out.dtype
2752
- if out_dtype != (np.float64 if self .real else np.complex128) :
2749
+ if out_dtype != numpy_dtype :
2753
2750
raise TypeError (" Output array is of incorrect type" )
2754
2751
if out.size < new_out_size:
2755
2752
raise ValueError (" Incompatible size of output argument" )
@@ -2801,6 +2798,45 @@ cdef class Lambdify(object):
2801
2798
out = tmp
2802
2799
return out
2803
2800
2801
+ cdef class LambdaDouble(_Lambdify):
2802
+
2803
+ cdef vector[symengine.LambdaRealDoubleVisitor] lambda_double
2804
+ cdef vector[symengine.LambdaComplexDoubleVisitor] lambda_double_complex
2805
+
2806
+ cdef _init(self , symengine.vec_basic& args_, symengine.vec_basic& outs_):
2807
+ if self .real:
2808
+ self .lambda_double.resize(1 )
2809
+ self .lambda_double[0 ].init(args_, outs_)
2810
+ else :
2811
+ self .lambda_double_complex.resize(1 )
2812
+ self .lambda_double_complex[0 ].init(args_, outs_)
2813
+
2814
+ cdef void _eval_real(self , double [::1 ] inp, double [::1 ] out):
2815
+ self .lambda_double[0 ].call(& out[0 ], & inp[0 ])
2816
+
2817
+ cdef void _eval_complex(self , double complex [::1 ] inp, double complex [::1 ] out):
2818
+ self .lambda_double_complex[0 ].call(& out[0 ], & inp[0 ])
2819
+
2820
+
2821
+ IF HAVE_SYMENGINE_LLVM:
2822
+ cdef class LLVMDouble(_Lambdify):
2823
+
2824
+ cdef vector[symengine.LLVMDoubleVisitor] lambda_double
2825
+
2826
+ cdef _init(self , symengine.vec_basic& args_, symengine.vec_basic& outs_):
2827
+ self .lambda_double.resize(1 )
2828
+ self .lambda_double[0 ].init(args_, outs_)
2829
+
2830
+ cdef void _eval_real(self , double [::1 ] inp, double [::1 ] out):
2831
+ self .lambda_double[0 ].call(& out[0 ], & inp[0 ])
2832
+
2833
+
2834
+ def Lambdify (args , exprs , bool real = True , bool llvm = False ):
2835
+ IF HAVE_SYMENGINE_LLVM:
2836
+ if llvm:
2837
+ return LLVMDouble(args, exprs, real)
2838
+
2839
+ return LambdaDouble(args, exprs, real)
2804
2840
2805
2841
def LambdifyCSE (args , exprs , real = True , cse = None , concatenate = None ):
2806
2842
"""
0 commit comments