I am trying decorator @guvectorize
with a function that outputs a [m,2] array. (m is depending the size of the input)
When using following function signature, I get an error.
import numpy as np
from numba import guvectorize
@guvectorize('void(float64[:], float64, uint32[:,2])', '(m),()->(m,2)', nopython=True)
def array_copy(data, delta, result):
for i, val in np.ndenumerate(data):
# Open i.
i, = i
result[i,:] = [i, int(val)+delta]
data = np.arange(3, dtype='float64')
res = np.zeros((data.shape[0], 2), dtype='uint32')
array_copy(data, 3, res)
This function is only here to support the example. Here is the error message.
Traceback (most recent call last):
File "<ipython-input-17-63f8983bbf61>", line 5, in <module>
def array_copy(data, delta, result):
File "/home/pierre/anaconda3/lib/python3.8/site-packages/numba/np/ufunc/decorators.py", line 177, in wrap
guvec = GUVectorize(func, signature, **kws)
File "/home/pierre/anaconda3/lib/python3.8/site-packages/numba/np/ufunc/decorators.py", line 49, in __new__
return imp(func, signature, identity=identity, cache=cache,
File "/home/pierre/anaconda3/lib/python3.8/site-packages/numba/np/ufunc/ufuncbuilder.py", line 298, in __init__
self.sin, self.sout = parse_signature(signature)
File "/home/pierre/anaconda3/lib/python3.8/site-packages/numba/np/ufunc/sigparse.py", line 49, in parse_signature
outputs = list(parse(outs))
File "/home/pierre/anaconda3/lib/python3.8/site-packages/numba/np/ufunc/sigparse.py", line 35, in parse
raise ValueError('bad token in signature "%s"' % tok[1])
ValueError: bad token in signature "2"
Please, what is wrong? How may I specify that result
will have 2 columns?
Current implementation of Numba doesn't implement all the features defined in Numpy's GUFunc signatures, particularly fixed dimensions.
The trick is to pass the result array twice, so the dimensions of the result are inferred from that parameter.
The following example vectorizes a function that calculates the sum and product of each row vector of 3 elements:
import numpy as np
from numba import guvectorize
@guvectorize('void(float64[:], float64[:], float64[:])',
'(m),(n)->(n)',
nopython=True)
def sum_and_product(data, dummy, result):
result[0] = data[0] + data[1] + data[2]
result[1] = data[0] * data[1] * data[2]
Then:
data = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype=float)
data
array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
res = np.empty((3, 2), dtype=float)
res = sum_and_product(data, res)
res
array([[ 6., 6.],
[ 15., 120.],
[ 24., 504.]])
Notice that the signature specifies the dimensions of a single vector and, consequently, the code in the function operates on a single vector.