pythontypesintegercython

How to efficiently use Python-style integers in Cython?


I am working in Cython, and I need to use Python's int type, not C's int type. How do I declare a Cython variable to be a Python-style integer?

cdef int x will use a C-style integer, not a Python-style integer.

cdef object x can store a Python-style integer, but it will be slow due to redundant runtime type checking.

If I know 100% that an object is going to be an int, can I avoid the runtime type checks?

The Cython docs seem to indicate that declaring it as object is the best that we can do, and we just have to live with the redundancy. This feels uncharacteristic of Cython, and I'm not fully convinced that I'm interpreting the documentation correctly.

Is is even possible to do what I'm asking?


Solution

  • The docs are pretty clear (emphasis added):

    The Python types int, long, and float are not available for static typing and instead interpreted as C int, long, and float respectively, as statically typing variables with these Python types has zero advantages.

    There are a number of concrete C APIs associated with stuff like list, tuple, etc., where static typing provides a meaningful benefit, allowing Cython to save time by compiling code that works with them on a more intrusive level (directly accessing the underlying array for list and tuple for example). For Python 3's int (and Python 2's long), that advantage largely doesn't exist; at best Cython could skip a tiny amount of type-checking work, in exchange for needing to reproduce all the rest of the code involved in the operations without those prechecks (Python 2's int is a C long under the hood, so you may as well declare it as such and benefit from using the raw C value directly). And it's quite a lot of code, given the complexities of working with arbitrary precision integers, and entirely unnecessary. If your values are small enough, you can use them as C types, but for anything larger, the cost of specializing for them would be greater than the gains.

    In short: Declare it as nothing, or object if you want to be explicit. There's no benefit to be had from what you're trying to do, and you can't do it in any event.