in numpy, what does mode='c' do in ndarray?

52 views
Skip to first unread message

David Lowry-Duda

unread,
Feb 14, 2022, 2:19:07 PM2/14/22
to cython...@googlegroups.com
I'm not particularly proficient in cython, but I do know both python and
c. I'm modifying code [1] that includes lines similar to the following:

cimport numpy as cnumpy
# later, in a function
cdef cnumpy.ndarray[cnumpy.float_t, ndim=3, mode='c'] rgb

I'm trying to understand what the `mode='c'` part is doing here. At
first I thought this was numpy-specific, but now I think that this has
to do with cython more generally. The closest thing I can find in
documentation is
https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html,
but it's not quite an exact match.

Could you point me to the relevant documentation or help explain to me
what this does? Does this `mode='c'` line impose restrictions that I
need to keep in mind on later code that I write?

Thank you - DLD

[1]: https://github.com/sagemath/sage/blob/develop/src/sage/plot/complex_plot.pyx

--
David Lowry-Duda <da...@lowryduda.com> <davidlowryduda.com>

da-woods

unread,
Feb 14, 2022, 2:53:00 PM2/14/22
to cython...@googlegroups.com
It's means the array must be "C" contiguous (rows are contiguous). As
opposed to Fortran contiguous (mode="f") where the columns are
contiguous or unspecified. If you're able to specify the a mode you get
a gain in efficiency when indexing into the array because Cython doesn't
need to deal with the stride between some elements. However, your
function won't accept some array slices (for example).

Numpy arrays are C contiguous by default, but slicing or transposing
them may change that. Therefore mode="c" is good for "freshly allocated"
arrays but unhelpful for arrays that may be coming from unknown sources
with unknown manipulations.

David Lowry-Duda

unread,
Feb 14, 2022, 3:24:05 PM2/14/22
to cython-users
Thank you for your reply.

On Monday, February 14, 2022 at 2:53:00 PM UTC-5 D Woods wrote:
It's means the array must be "C" contiguous (rows are contiguous). As
opposed to Fortran contiguous (mode="f") where the columns are
contiguous or unspecified. If you're able to specify the a mode you get
a gain in efficiency when indexing into the array because Cython doesn't
need to deal with the stride between some elements. However, your
function won't accept some array slices (for example).

Numpy arrays are C contiguous by default, but slicing or transposing
them may change that. Therefore mode="c" is good for "freshly allocated"
arrays but unhelpful for arrays that may be coming from unknown sources
with unknown manipulations.

I interpret this to mean that I could replace `mode='c'` by `mode='f'` for example, but when I do this my cythonizer spits out the error

    Only allowed buffer modes are: "c", "fortran", "full", "strided" (as compile-time string). 

This certainly sounds nearly as you describe, in that there are c and fortran options. But there are also full and strided options, I guess? This is also very close to what appears on the cython memoryviews page, except that I'm surprised that I can define this for an ndarray type. Is this documented somewhere?

I don't know if this matters, but I note that I'm using sage's cythonizer. To produce this error, I wrote the following do-nothing file.

########
# test.spyx
cimport numpy as cnumpy
def do_nothing():
    cdef cnumpy.ndarray[cnumpy.float_t, ndim=3, mode='f'] rgb
    pass

# endfile
##########

and cythonized this via

> sage -cython test.spyx

- DLD

da-woods

unread,
Feb 14, 2022, 3:47:32 PM2/14/22
to cython...@googlegroups.com
On 14/02/2022 20:17, David Lowry-Duda wrote:
I interpret this to mean that I could replace `mode='c'` by `mode='f'` for example, but when I do this my cythonizer spits out the error

    Only allowed buffer modes are: "c", "fortran", "full", "strided" (as compile-time string). 

This certainly sounds nearly as you describe, in that there are c and fortran options. But there are also full and strided options, I guess? This is also very close to what appears on the cython memoryviews page, except that I'm surprised that I can define this for an ndarray type. Is this documented somewhere?

I went from memory and it sounds like I was slightly wrong. Use "fortran" instead of "f". I think "strided" is the default - it can take arbitrary array slices. I'm not quite sure what "full" is; possibly it might be closer to "indirect" for memoryviews?

Memoryviews have largely the same purpose as the ndarray type (so has similar features). The memoryview syntax is more modern and has some advantages so the documentation focuses on that.

The "mode" for the older syntax doesn't look to be thoroughly documented that I can see.



David Lowry-Duda

unread,
Feb 15, 2022, 3:35:00 AM2/15/22
to cython...@googlegroups.com
Thank you for being so responsive! This makes sense to me.

Cheers - DLD
Reply all
Reply to author
Forward
0 new messages