Search code examples
cythonmemoryview

Memoryviews slices in Cython ask for a scalar


I'm trying to create a memoryview to store several vectors as rows, but when I try to change the value of any I got an error, like it is expecting a scalar.

%%cython
import numpy as np
cimport numpy as np

DTYPE = np.float
ctypedef np.float_t DTYPE_t
cdef DTYPE_t[:, ::1] results = np.zeros(shape=(10, 10), dtype=DTYPE)

results[:, 0] = np.random.rand(10)

This trows me the following error:

TypeError: only size-1 arrays can be converted to Python scalars

Which I don't understand given that I want to overwrite the first row with that vector... Any idea about what I am doing wrong?


Solution

  • The operation you would like to use is possible between numpy arrays (Python functionality) or Cython's memory views (C functionality, i.e. Cython generates right for-loops in the C-code), but not when you mix a memory view (on the left-hand side) and a numpy array (on the right-hand side).

    So you have either to use Cython's memory-views:

    ...
    cdef DTYPE_t[::1] r = np.random.rand(10)
    results[:, 0] = r
    #check it worked:
    print(results.base)
    ...
    

    or numpy-arrays (we know .base is a numpy-array):

    results.base[:, 0] = np.random.rand(10)
    #check it worked:
    print(results.base)
    

    Cython's version has less overhead, but for large matrices there won't be much difference.