Cython compilation error "Not allowed in a constant expression"
Asked Answered
A

1

8

The following

cimport cython

@cython.boundscheck(False)
def boundtest():
     cdef int r=4
     cdef double l[3]

works fine. But when I try this:

cimport cython

@cython.boundscheck(False)
def boundtest():
     cdef int r=4
     cdef double l[r]

I receive the following error:

[1/1] Cythonizing test.pyx

Error compiling Cython file:
------------------------------------------------------------
...
cimport cython

@cython.boundscheck(False)
def boundtest():
     cdef int r=4
     cdef double l[r]
                   ^
------------------------------------------------------------

test.pyx:13:20: Not allowed in a constant expression
     

The decorator was added due to finding this related stackexchange post and reading the Cython book by Kurt W. Smith. As far as I can tell this should work to tell Cython not to worry about out of bounds errors that may result from having a dynamic indexing variable but for some reason it does not. I have also tried changing boundscheck in the compiler options and globally to no avail.

If it weren't for the Cython documentation claiming to be up to date I would think boundscheck has been depreciated.

Averse answered 19/9, 2017 at 17:41 Comment(0)
C
16

The failure has nothing to do with cython.boundscheck.

Boundchecking is just checking if you try to access an element of an array that isn't there. For example if you have a size 4 array and try to access element 5 - with boundscheck(True) it will give you an Exception, with boundscheck(False) it will result in undefined behavior (probably causing a segmentation fault).

The reason for the compilation failure is another: You can't create a static array with a dynamic length! The number of elements need to be known at compile time, that's just something enforces (I guess).

However you could define r to be known at compile time:

DEF r=4

cimport cython

@cython.boundscheck(False)
def boundtest():
    cdef double l[r]

You could however simply create a NumPy array and store it in a memoryview variable:

cimport cython
import numpy as np

@cython.boundscheck(False)
def boundtest():
    cdef int r=4
    cdef double[:] l = np.empty(r, dtype=np.double)
Cule answered 19/9, 2017 at 17:51 Comment(3)
It works, thank you very much! I wish the OP in the linked post had been a bit more explicit about changing his code to use a memoryview variable.Averse
@Averse Cython combines Python and C so it requires a bit of knowledge about both to get it right. Probably it was just "assumed" that you don't create dynamic length arrays using cdef double l[r] but only with known constants like cdef double l[4].Cule
Weird that Cython doesn't support C99 VLAs, but good for them. VLAs are dangerous.Twyla

© 2022 - 2024 — McMap. All rights reserved.