@@ -4670,6 +4670,9 @@ cdef double _scipy_callback_lambda_real(int n, double *x, void *user_data) nogil
4670
4670
deref(lamb).call(& result, x)
4671
4671
return result
4672
4672
4673
+ cdef void _ctypes_callback_lambda_real(double * output, const double * input , void * user_data) nogil:
4674
+ cdef symengine.LambdaRealDoubleVisitor* lamb = < symengine.LambdaRealDoubleVisitor * > user_data
4675
+ deref(lamb).call(output, input )
4673
4676
4674
4677
IF HAVE_SYMENGINE_LLVM:
4675
4678
cdef double _scipy_callback_llvm_real(int n, double * x, void * user_data) nogil:
@@ -4678,6 +4681,10 @@ IF HAVE_SYMENGINE_LLVM:
4678
4681
deref(lamb).call(& result, x)
4679
4682
return result
4680
4683
4684
+ cdef void _ctypes_callback_llvm_real(double * output, const double * input , void * user_data) nogil:
4685
+ cdef symengine.LLVMDoubleVisitor* lamb = < symengine.LLVMDoubleVisitor * > user_data
4686
+ deref(lamb).call(output, input )
4687
+
4681
4688
4682
4689
def create_low_level_callable (lambdify , *args ):
4683
4690
from scipy import LowLevelCallable
@@ -4721,6 +4728,23 @@ cdef class LambdaDouble(_Lambdify):
4721
4728
addr2 = cast(< size_t> & self .lambda_double[0 ], c_void_p)
4722
4729
return create_low_level_callable(self , addr1, addr2)
4723
4730
4731
+ cpdef as_ctypes(self ):
4732
+ """
4733
+ Returns a tuple with first element being a ctypes function with signature
4734
+
4735
+ void func(double * output, const double *input, void *user_data)
4736
+
4737
+ and second element being a ctypes void pointer. This void pointer needs to be
4738
+ passed as input to the function as the third argument `user_data`.
4739
+ """
4740
+ from ctypes import c_double, c_void_p, c_int, cast, POINTER, CFUNCTYPE
4741
+ if not self .real:
4742
+ raise RuntimeError (" Lambda function has to be real" )
4743
+ addr1 = cast(< size_t> & _ctypes_callback_lambda_real,
4744
+ CFUNCTYPE(c_void_p, POINTER(c_double), POINTER(c_double), c_void_p))
4745
+ addr2 = cast(< size_t> & self .lambda_double[0 ], c_void_p)
4746
+ return addr1, addr2
4747
+
4724
4748
4725
4749
IF HAVE_SYMENGINE_LLVM:
4726
4750
cdef class LLVMDouble(_Lambdify):
@@ -4752,11 +4776,28 @@ IF HAVE_SYMENGINE_LLVM:
4752
4776
raise RuntimeError (" Lambda function has to be real" )
4753
4777
if self .tot_out_size > 1 :
4754
4778
raise RuntimeError (" SciPy LowLevelCallable supports only functions with 1 output" )
4755
- addr1 = cast(< size_t> & _scipy_callback_lambda_real ,
4779
+ addr1 = cast(< size_t> & _scipy_callback_llvm_real ,
4756
4780
CFUNCTYPE(c_double, c_int, POINTER(c_double), c_void_p))
4757
4781
addr2 = cast(< size_t> & self .lambda_double[0 ], c_void_p)
4758
4782
return create_low_level_callable(self , addr1, addr2)
4759
4783
4784
+ cpdef as_ctypes(self ):
4785
+ """
4786
+ Returns a tuple with first element being a ctypes function with signature
4787
+
4788
+ void func(double * output, const double *input, void *user_data)
4789
+
4790
+ and second element being a ctypes void pointer. This void pointer needs to be
4791
+ passed as input to the function as the third argument `user_data`.
4792
+ """
4793
+ from ctypes import c_double, c_void_p, c_int, cast, POINTER, CFUNCTYPE
4794
+ if not self .real:
4795
+ raise RuntimeError (" Lambda function has to be real" )
4796
+ addr1 = cast(< size_t> & _ctypes_callback_llvm_real,
4797
+ CFUNCTYPE(c_void_p, POINTER(c_double), POINTER(c_double), c_void_p))
4798
+ addr2 = cast(< size_t> & self .lambda_double[0 ], c_void_p)
4799
+ return addr1, addr2
4800
+
4760
4801
def llvm_loading_func (*args ):
4761
4802
return LLVMDouble(args, _load = True )
4762
4803
0 commit comments