cgcccythonlong-integerint128

How to use 128 bit integers in Cython


On my 64 bit computer the long long type has 64 bits.

print(sizeof(long long))
# prints 8

I need to use 128 bit integers and luckily GCC supports these. How can I use these within Cython?

The following doesn't work. Compiling foo.pyx containing just

cdef __int128_t x = 0

yields

$ cython foo.pyx 

Error compiling Cython file:
------------------------------------------------------------
...

cdef __int128_t x = 0
    ^
------------------------------------------------------------

foo.pyx:2:5: '__int128_t' is not a type identifier

Solution

  • EDIT: this is NOT a workaround anymore, this is the right way to do it. Refer also to @IanH's answer.

    Now, the problem you have is that cython does not recognize your type, while gcc does. So we can try to trick cython.

    File helloworld.pyx:

    cdef extern from "header_int128.h":
        # this is WRONG, as this would be a int64. it is here
        # just to let cython pass the first step, which is generating
        # the .c file.
        ctypedef unsigned long long int128
    
    print "hello world"
    
    cpdef int foo():
        cdef int128 foo = 4
        return 32
    

    File header_int128.h:

    typedef __int128_t int128;
    

    File setup.py:

    from distutils.core import setup
    from Cython.Build import cythonize
    
    setup(ext_modules = cythonize("helloworld.pyx"))
    

    Now, on my machine, when I run python setup.py build_ext --inplace, the first step passes, and the file helloworld.c is generated, and then the gcc compilation passes as well.

    Now if you open the file helloworld.c, you can check that your variable foo is actually declared as an int128.

    Be very careful with using this workaround. In particular, it can happen that cython will not require a cast in the C code if you assign an int128 to a int64 for example, because at that step of the process it actually does not distinguish between them.