I don't understand this compilation error

This script:

import numpy as np
import numba as nb
from math import pi, atan2, sqrt

@nb.njit(fastmath=True, locals=dict(w=nb.uint32))
def test2(im, grads, w):
  for i in range(im.size-w-1):
    dx = im[i+w+1]-im[i]
    dy = im[i+w]-im[i+1]
    grads[i] = (sqrt(dx*dx+dy*dy), np.int8(np.int8((atan2(dy, dx)+1.125*pi)/(pi/4)+5)%8))

w, h = 640, 480
im = np.random.rand(w*h).astype('f4')
grads = np.empty_like(im, dtype=[('magn', 'f4'), ('dir', 'i1')])
test2(im, grads, w)
print(grads)

produces this error:

Traceback (most recent call last):
  File "/home/paul/vision/so-9.py", line 15, in <module>
    test2(im, grads, w)
  File "/home/paul/venv/vision/lib/python3.10/site-packages/numba/core/dispatcher.py", line 468, in _compile_for_args
    error_rewrite(e, 'typing')
  File "/home/paul/venv/vision/lib/python3.10/site-packages/numba/core/dispatcher.py", line 409, in error_rewrite
    raise e.with_traceback(None)
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function setitem>) found for signature:
 
 >>> setitem(unaligned array(Record(magn[type=float32;offset=0],dir[type=int8;offset=4];5;False), 1d, C), int64, Tuple(float32, int8))
 
There are 16 candidate implementations:
  - Of which 16 did not match due to:
  Overload of function 'setitem': File: <numerous>: Line N/A.
    With argument(s): '(unaligned array(Record(magn[type=float32;offset=0],dir[type=int8;offset=4];5;False), 1d, C), int64, Tuple(float32, int8))':
   No match.

During: typing of setitem at /home/paul/vision/so-9.py (10)

File "so-9.py", line 10:
def test2(im, grads, w):
    <source elided>
    dy = im[i+w]-im[i+1]
    grads[i] = (sqrt(dx*dx+dy*dy), np.int8(np.int8((atan2(dy, dx)+1.125*pi)/(pi/4)+5)%8))
    ^

The script runs fine without Numba. I though that Tuple(float32, int8) is the proper type to set an element of grads. What is the problem here?

I think you should be able to write it like:

grads["magn"][i] = sqrt(dx*dx+dy*dy)
grads["dir"][i] = np.int8(np.int8((atan2(dy, dx)+1.125*pi)/(pi/4)+5)%8)
1 Like

Related post

1 Like

In general, fancy-dtype stuff is a bit hit-and-miss with numba. It can usually be worked around one way or another.

1 Like