0

I want to have a Cython function in a class, and exposure a ufunc version of it to Python, while keeping the fast scaler version for use in Cython. My current attempt to do this gives me (nearly) what I want, however means I have to write 4 versions of every function I want to do this for, which feels very awkward.

Is there a better way of doing this?

Current Attempt

cdef double _func(double p, double x):
    # (1) actual implementation ... pretend some math is here
    return x / p 

@cython.ufunc
cdef double _ufunc(double p, double x):
    # (2) the ufunc 'decorator' only works outside classes so need this here
    return _func(p, x)

@cython.final
cdef class Thing:
    cdef readonly double p

    def __cinit__(self, double p):
        if p == 0: raise ValueError(f"p must not be 0")
        self.p = p
    
    cdef _func(self, x):
        # (3) this version gives me the API I want in Cython
        # (would prefer to have just `func`)
        return _func(self.p, x)

    def func(self, x):
        # (4) this version gives me the API I want in Python
        return _ufunc(self.p, x)

Desired Use In Python

t = Thing(p=5)
t.func(x=4)
t.func(x=np.linspace(0,1,100))

Desired Use In Cython

# class to hold (possibly many) parameter's & check then once so can skip later checks
cdef Thing t = Thing(p=5) 
cdef double y = t.func(4) # want this to be as fast a possible
hbwales
  • 158
  • 5

0 Answers0