Cython: Workaround scipy.optimize.cython_optimize.brentq argument ctype to work with class methods ctype

120 Views Asked by At

I'm trying to use the root finder scipy.optimize.cython_optimize.brentq inside a class, but the first argument of this function accepts only the type ctypedef double (*callback_type)(double, void*) and my class method is the type of ctypedef double (*w_func)(test,double, void*). How could I get this working?

The following code is an exemple of the problem.

%%cython
from scipy.optimize.cython_optimize cimport brentq

ctypedef double (*f_func)(test,double, double)
ctypedef double (*w_func)(test,double, void*)
ctypedef double (*callback_type)(double, void*)

ctypedef struct test_params:
    double y0
    double x1
    f_func f
    w_func w

cdef class test():
    def __init__(self):
        cdef test_params myargs
        myargs.y0 =  1.0
        myargs.x1 = 0.7
        myargs.f = self.sum2
        myargs.w = self.w
        print(self.brentqWrapper(myargs, -10, 10, 1e-3, 1e-3, 10))
    
    cdef double sum2(self, double x1,double y1):
        return x1+y1

    cdef double w(self, double y1, void *args):
        cdef test_params *myargs = <test_params *> args
        return y1 - myargs.y0 - myargs.f(self,myargs.x1,y1)

    # Cython wrapper function
    cdef double brentqWrapper(self,test_params args, double xa, double xb,
                                       double xtol, double rtol, int mitr):
        return brentq(args.w, xa, xb, <test_params *> &args, xtol, rtol, mitr, NULL)

test()
1

There are 1 best solutions below

1
On

ISTM it's easiest and most clean to restructure your code to have a module-level function which receives the class instance in its last argument.