I'm trying to write a function that can be vectorized by numba to act as a ufunc on a set of arrays:
from numba import float32, float64, vectorize
@vectorize([float32, float32, float32, float32(float32, float32, float32, float32, float32, float32, float32, numba.float32),
float64, float64, float64, float64(float64, float64, float64, float64, float64, float64, float64, numba.float64)])
def _cafec_coeff_ufunc(ET_bar,
PET_bar,
R_bar,
PR_bar,
L_bar,
PL_bar,
RO_bar,
PRO_bar):
# calculate alpha
if PET_bar == 0:
if ET_bar == 0:
alpha = 1
else:
alpha = 0
else:
alpha = ET_bar / PET_bar
# calculate beta
if PR_bar == 0:
if R_bar == 0:
beta = 1
else:
beta = 0
else:
beta = R_bar / PR_bar
# calculate gamma
if PRO_bar == 0:
if RO_bar == 0:
gamma = 1
else:
gamma = 0
else:
gamma = RO_bar / PRO_bar
# calculate delta
if PL_bar == 0:
if L_bar == 0:
delta = 1
else:
delta = 0
else:
delta = L_bar / PL_bar
return alpha, beta, gamma, delta
I call the above function in another function, passing the eight arrays it needs as arguments. My expectation is that this function will be applied in a broadcasting fashion, as if a 1-D loop for each element i (assuming all input arrays are equal size) with the ufunc getting scalars from each array at the i-th index as its arguments, finally returning with four arrays with corresponding values in the i-th locations of the output arrays (result of the ufunc broadcast reduced into output arrays).
alpha, beta, gamma, delta = _cafec_coeff_ufunc(ETbar, PETbar, Rbar, PRbar, Lbar, PLbar, RObar, PRObar)
When I run the code above as part of a unit test for the calling method I get the following errors in console:
File "C:\home\git\indices_python\palmer.py", line 342, in <module>
numba.float64, numba.float64, numba.float64, numba.float64(numba.float64, numba.float64, numba.float64, numba.float64, numba.float64, numba.float64, numba.float64, numba.float64)])
File "C:\Anaconda3\lib\site-packages\numba\npyufunc\decorators.py", line 120, in wrap
vec.add(sig)
File "C:\Anaconda3\lib\site-packages\numba\npyufunc\dufunc.py", line 139, in add
args, return_type = sigutils.normalize_signature(sig)
File "C:\Anaconda3\lib\site-packages\numba\sigutils.py", line 35, in normalize_signature
% (sig.__class__.__name__,))
TypeError: invalid signature: 'Float' instance not allowed
I can modify the signature by adding quotes around the signature itself in order to turn it into a string. and when I do this the error now becomes this:
File "C:\home\git\indices_github\palmer.py", line 346, in <module>
@numba.vectorize(['f8,f8,f8,f8(f8,f8,f8,f8,f8,f8,f8,f8)'])
File "C:\home\Anaconda3\lib\site-packages\numba\npyufunc\decorators.py", line 120, in wrap
vec.add(sig)
File "C:\home\Anaconda3\lib\site-packages\numba\npyufunc\dufunc.py", line 139, in add
args, return_type = sigutils.normalize_signature(sig)
File "C:\home\Anaconda3\lib\site-packages\numba\sigutils.py", line 45, in normalize_signature
check_type(ty)
File "C:\home\Anaconda3\lib\site-packages\numba\sigutils.py", line 40, in check_type
"got %r" % (ty,))
TypeError: invalid signature: expected a type instance, got (float64, float64, float64, float64, float64, float64, float64, float64) -> float64
What am I doing wrong here?