How to assign a multidimensional array to a sub-block of a 2d array

41 views Asked by At

I want to take a big 2d-array and fill it with values by inserting sub-blocks (read: smaller 2d arrays) until the big array has been filled. I want to do this as fast as possible, so I try to use what I think are c-arrays. But I am a beginner with cython. So here is a minimal nonworking example to explain what I want to do:

# test.pyx
import numpy as np
cimport numpy as cnp
cnp.import_array()

def HGamma_m( int L, double[:] param, cnp.ndarray[int64_t, ndim=2] R ):
    cdef complex [:,:] HGamma = np.zeros( (4*L,4*L) , dtype=np.complex128 )
    cdef int i, j
    cdef double l,m,n
    for i in range(L):
        for j in range(L):
            r = R[j] - R[i]
            l,m,n = r[0], r[1], r[2]
            HGamma[4*i:4*(i+1), 4*j:4*(j+1)] = [
                [ bowler*param[2],      bowler*param[3]*l,                              bowler*param[3]*m,                              bowler*param[3]*n],
                [-bowler*param[3]*l,    bowler*param[4]*l*l + bowler*param[5]*(1-l*l ), bowler*m*l*(param[4]-param[5]),                 bowler*n*l*(param[4] - param[5])],
                [-bowler*param[3]*m,    bowler*l*m*(param[4] - param[5]),               bowler*param[4]*m*m + bowler*param[5]*(1-m*m),  bowler*n*m*(param[4] - param[5])],
                [-bowler*param[3]*n,    bowler*l*n*(param[4] - param[5]),               bowler*m*n*(param[4]-param[5]),                 bowler*param[4]*n*n + bowler*param[5]*(1-n*n)]
            ]

It may be compiled by using the following code.

# setup.py
from setuptools import setup
from Cython.Build import cythonize
import numpy

setup(
    ext_modules = cythonize(
        "test.pyx", 
        annotate=True,
        compiler_directives={'language_level' : "3"}
    ),
    include_dirs=[numpy.get_include()]
)

But I get the error that it Cannot coerce list to type 'double complex' on the line that starts with HGamma[4*i:4*(i+1), 4*j:4*(j+1)] = [.

So how would I achieve this in the fastest practical way?

I tried to declare the array as a numpy array, which worked. But then I get what seems as unfairly slow slow execution as a function of increasing value of L. For that reason I want to do these simple arithmetic operations more quickly.

1

There are 1 answers

0
Armali On

As cythonize Cannot coerce list to type 'double complex', you can help it by writing

            HGamma[4*i:4*(i+1), 4*j:4*(j+1)] = np.array([
                [ bowler*param[2],      bowler*param[3]*l,                              bowler*param[3]*m,                              bowler*param[3]*n],
                [-bowler*param[3]*l,    bowler*param[4]*l*l + bowler*param[5]*(1-l*l ), bowler*m*l*(param[4]-param[5]),                 bowler*n*l*(param[4] - param[5])],
                [-bowler*param[3]*m,    bowler*l*m*(param[4] - param[5]),               bowler*param[4]*m*m + bowler*param[5]*(1-m*m),  bowler*n*m*(param[4] - param[5])],
                [-bowler*param[3]*n,    bowler*l*n*(param[4] - param[5]),               bowler*m*n*(param[4]-param[5]),                 bowler*param[4]*n*n + bowler*param[5]*(1-n*n)]
            ])