Hi folks,
i recently started experimenting with numba and have a question considering the flexible specializations obtained via the @generated_jit
decorator.
As an example, i want to generate a jit’ed function for the dyadic product of two array a and b:
-
if a and b are vectors, the result should be a matrix:
cij = ai bj -
if a and b are matrices, the result should be a 4th order array:
cijkl = aij bkl
A working solution that i came up with is the following:
import numpy as np
import numba as nb
@nb.njit
def _t2_dyad_t2(a,b):
dim = a.shape[0]
c = np.zeros((dim,dim,dim,dim))
for i in range(dim):
for j in range(dim):
for k in range(dim):
for l in range(dim):
c[i,j,k,l] = a[i,j]*b[k,l]
return c
@nb.njit
def _t1_dyad_t1(a,b):
dim = a.shape[0]
c = np.zeros((dim,dim))
for i in range(dim):
for j in range(dim):
c[i,j] = a[i]*b[j]
return c
# generate auto-specializations of dyad()
@nb.generated_jit(nopython=True)
def dyad(a,b):
if ( isinstance(a, nb.types.Array) and a.ndim == 1
and isinstance(b, nb.types.Array) and b.ndim == 1):
# 4th order tensors
return _t1_dyad_t1
elif ( isinstance(a, nb.types.Array) and a.ndim == 2
and isinstance(b, nb.types.Array) and b.ndim == 2):
# 2nd order tensors / matrices
return _t2_dyad_t2
else:
raise Exception("Dyadic product not implemented for this types.")
a = np.random.rand(3)
b = np.random.rand(3)
A = np.random.rand(3,3)
B = np.random.rand(3,3)
c = dyad(a,b)
C = dyad(A,B)
My question is if there is a shorter way to specify "a
is a one-dimensional array", something like nb.types.Array[1]
?
On a side note, if there is an elegant way to generalize this type of product to arbitrary array combinations, that would be interesting too
Kind regards
Tim