I am trying to assign the output of linalg inverse function (la.inv) to a view in cython. Unfortunately this does not work. I can always assign the output of la.inv() to a temporary ndarray object and then copy its content to the view.
Is there a better way to do it.
cpdef int testfunc1(np.ndarray[np.float_t, ndim=2] A,
double [:,:] B) except -1:
print("inverse of A:", la.inv(A))
if np.isnan(A).any():
return -1
else:
B = la.inv(A)
return 1
cpdef int testfunc2(np.ndarray[np.float_t, ndim=2] A) except -1:
cdef long p = np.shape(A)[0], status
cdef B = np.zeros(shape=(p, p), dtype=float)
cdef double[:,:] BView = B
print("before inverse. B: ", B)
status = testfunc1(A, BView)
print("after inverse. B: ", B)
if status == -1:
return -1
else:
return 1
The output:
A = np.random.ranf(4).reshape(2, 2)
status = testfunc2(A)
if status == -1:
raise ValueError("nan cell.")
else:
print("pass")
('before inverse. B: ', array([[ 0., 0.],
[ 0., 0.]]))
('inverse of A:', array([[ 4.4407987 , -0.10307341],
[-2.26088593, 1.19604499]]))
('after inverse. B: ', array([[ 0., 0.],
[ 0., 0.]]))
This isn't caused by views or by Cython.
B = la.inv(A)
creates a new array and gives it the nameB
in the scope oftestfunc1
. This does not affect the array with the nameB
intestfunc2
.Be aware that your code, where the heavy lifting is done by NumPy functions, is unlikely to benefit from Cython.
One way to make this work is to do:
in
testfunc1
. @SaulloCastro mentions that this does't work in Cython asB
has a memory view type, however you may be able make it work by declaring the argumentB
as an ndarray (not sure about this). Otherwise without Cython:You can create a temporary buffer that will receive the value of the
la.inv()
and then populate the memory view:As pointed out by @MrE, you can use
np.copyto()
if you use anp.ndarray
instead of a MemoryView:If I create a mememoryview on
la.inv(A)
I can perform a 1 step, and presumably efficient, memoryview to memoryview copy:producing:
I'm guessing that the the memoryview copy will be faster, but the sample arrays are too small for meaningful time tests.
I tested this as part of responding at https://stackoverflow.com/a/30418448/901925
In
Python
you can reassign thedata
buffer of an array (albeit at some risk):cython
raises errors about unsafe pointers during the compile stage with this statement.Inspired by examples I found for https://stackoverflow.com/a/28855962/901925 using
np.PyArray_SimpleNewFromData
, I tried using otherPyArray...
functions to do the same sort ofbase
reassignment:Currently I am trying to resolve a
AttributeError: 'module' object has no attribute 'PyArray_SetBaseObject'
error.