Neal Becker wrote:
> I need to write functions that apply element-wise numpy arrays, and should 
> be independent of the number of dimensions.
> 
> numpy has a mechanism for generic (dimension-independent) iteration over 
> elements of the array, but is there any way to use this (or implement 
> something similar) in cython?

There's two methods: ufuncs and multi-iterators. ufuncs is the most 
common one -- search for ufunc on the Cython wiki, there should be an 
example somewhere.

I just did this using multi-iterators (which I had to do because I 
needed some context -- a temporary buffer -- during the calculation). 
Attaching my code for calculating a Wigner 3j symbol elementwise with 
full broadcasting.

(It is not as fast as it could be -- it is possible to extract out the 
inner loop and have it as a C loop rather than rely on the iterator, 
which is faster. I didn't bother yet though, mainly because each Wigner 
symbol calculation is rather heavy.)

The NumPy docs is rather good in this area, check there next! (search 
for the multiiterator functions I use + ufuncs)

Also you need a newer numpy.pxd than the one shipped with Cython for 
both ufuncs and multiiterators. Just replace the one in Cython/Includes 
with the attachment. I will include it in the next Cython release.

[Edit: The attachments were too large, but they're up at 
sage.math.washington.edu/home/dagss as numpy.pxd and wigner.pyx. The 
main idea is:


     cdef np.broadcast it = np.broadcast(l1, l2, l3, m1, m2, m3)
     shape = (<object>it).shape
     if out is None:
         out = np.empty(shape, dtype)
     else:
         if out.shape != shape:
             raise ValueError(u"out argument has incorrect shape")
         if out.dtype != dtype:
             raise ValueError(u"out argument has incorrect dtype")
     it = np.broadcast(l1, l2, l3, m1, m2, m3, out)

     with nogil:
         while np.PyArray_MultiIter_NOTDONE(it):
             l1val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 0))[0]
             l2val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
             l3val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 2))[0]
             m1val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 3))[0]
             m2val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 4))[0]
             m3val = (<dtype_t*>np.PyArray_MultiIter_DATA(it, 4))[0]

             ...make outval...

             (<dtype_t*>np.PyArray_MultiIter_DATA(it, 6))[0] = outval
             np.PyArray_MultiIter_NEXT(it)


]

-- 
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to