Search code examples
pythonpython-2.7cythoninteger-divisionfloor

Cython header directive and __future__


What is the correct way to utilize Cython header directives AND utilize a future import? Python 2.7.x

Example:

1: from __future__ import division
2: #cython: boundscheck=False
3: #cython: wraparound=False
<strike>4: #cython: cdivision=True</strike>
4: #cython: cdivision=False

This ensures that division works as expected (using the future version), but I am unsure whether the directives are being observed. Swapping line 1 with line 4 causes division to revert to the standard Python 2.x method.


Solution

  • As commented by @user2357112 #cython: cdivision=True contradicts from __future__ import division. This code is illustrative:

    #cython: wraparound=False
    #cython: boundscheck=False
    #cython: nonecheck=False
    #cython: profile=False
    from __future__ import division
    
    def main():
        cdef double i, j
        i = 0
        j = 2
        print 1/j
        print 1/i
        print 1/2
    

    raising:

        print 1/i
    ZeroDivisionError: float division
    

    Adding #cython: cdivision=True it will give:

    0.5
    inf
    0
    

    where you can see the 1/2 being processed as a floor division.

    In this case I would recommend to apply the float point 1/2. wherever you want a float division when using Python 2.x...

    Swapping the lines as you mentioned:

    from __future__ import division
    #cython: wraparound=False
    #cython: boundscheck=False
    #cython: nonecheck=False
    #cython: profile=False
    #cython: cdivision=True
    

    will cancel all the Cython global directives, because they "must appear before any code (but can appear after other comments or whitespace)".