List of arrays in jitclass

Dear everyone,
I’m trying to define an empty list as attribute of a class. The list is going to contain 2-dim float64 arrays (i.e. points on plane).

I found how to define an empty list of floats:

spec = {
    'points_pos' :  types.ListType(types.float64),
}
@jitclass(spec)
class Class:
    def __init__(self):
        self.points_pos = typed.List.empty_list(types.float64)

So, I thought that something like this would have worked:

spec = {
    'points_pos' :  types.ListType(types.float64[:]),
}
@jitclass(spec)
class Class:
    def __init__(self):
        self.points_pos = typed.List.empty_list(types.float64[:])

Unfortunately, I get the error:

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function getitem>) found for signature:
 
 >>> getitem(class(float64), slice<a:b>)
There are 22 candidate implementations:
      - Of which 22 did not match due to:
      Overload of function 'getitem': File: <numerous>: Line N/A.
        With argument(s): '(class(float64), slice<a:b>)':
       No match.

I can’t understand the reason as it looks like it’s the correct data type. If I try something like, it returns true

vet = typed.List.empty_list(types.float64[:])
numba.typeof(vet) == types.ListType(types.float64[:])

Thank you for any suggestion

Hi @M1T10

The issue in the above is due to the use of the convenience constructor types.float64[:] within a JIT compiled region. When doing the JIT compilation of the __init__ Numba doesn’t know how to interpret a getitem with a slice argument on a types.float64, hence the error. The way to workaround this is to define the type outside the JIT scope and refer to it, e.g.

from numba import njit, types, typed
from numba.experimental import jitclass
import numpy as np

# Define the type outside of the JIT compiled scope
float64_1d_array_type = types.float64[:]

spec = {'list_of_arrays': types.ListType(float64_1d_array_type)}
@jitclass(spec)
class MyClass():
    def __init__(self):
        self.list_of_arrays = typed.List.empty_list(float64_1d_array_type)

inst = MyClass()
inst.list_of_arrays.append(np.ones(4))
print(inst.list_of_arrays)

this workaround should always succeed no matter how involved the type expression is.

Hope this helps.

1 Like