Convert from int to double and back in Cython

i like this post (click again to cancel)
0
i dont like this post (click again to cancel)

This is a really basic question, I'm sure, for cython types.

In the notebook, I have the following cell to compute a famous but totally inefficient $\pi(x)$ (prime counting function). It already is about 100 times faster than the equivalent in native Python.

Question: The result += (fact - j*int(floor(t))) line still is bright yellow. I don't know if there is any easy way to mix these types. The problem is I need for t to take two ints and make them something I can apply floor to, which appears to be a double. Then I need to make the floor an int again to multiply it by j. Any ideas? Again, I'm sure this is simple, but I haven't earned my Cython stripes yet.

%cython
cdef extern from "math.h":
    double floor(double x)

cdef int primeish(int n):
    cdef int fact
    cdef int result
    cdef int j
    cdef double t
    if n==1:
        return 0
    elif n==2:
        return 1
    elif n==3:
        return 2
    else:
        result = -1
        fact = 1
        for j in range(3,n+1):
            fact = fact*(j-2)
            t = fact/j
            result += (fact - j*int(floor(t)))
        return result

asked Apr 20 '11

kcrisman gravatar image kcrisman
6614 13 66 149
i like this answer (click again to cancel)
2
i dont like this answer (click again to cancel) kcrisman has selected this answer as correct

The statement

result += (fact - j*(<int>t))

will cast t to an int (dropping the fractional part like floor does) without calling floor. In the annotated cython code this change reduces the "yellowness" of that line. I'm not sure why it's yellow at all though, it seems like this statement should translate easily to pure C code.

If you want to use the C math library version of floor I think you need an appropriate include statement.


Edit:

If you use the @cython.cdivision(True) decorator, cython will not add exception checking for division by zero, this allows the division statement to be converted to one line of pure C code. In your code j is never zero, so this is okay. Also, you can skip the double t entirely if you just write fact/j. Since both are integers, the division occurs as integers and the result is the floor of the rational number fact/j.

Here is new code with the changes:

%cython
import cython

@cython.cdivision(True)    # turn division by zero checking off
def primeish(int n):
    cdef int fact
    cdef int result
    cdef int j
    cdef int t
    if n==1:
        return 0
    elif n==2:
        return 1
    elif n==3:
        return 2
    else:
        result = -1
        fact = 1
        for j in range(3,n+1):
            fact = fact*(j-2)
            t = fact / j    # integer division
            result += fact - t*j
        return result
link

posted Apr 20 '11

benjaminfjones gravatar image benjaminfjones
2470 3 33 66
http://bfj7.com/

updated Apr 21 '11

Makes sense; I remember something about 'casting' from reading C tutorials... kcrisman (Apr 20 '11)
Followup to make you earn your check mark :) - any way to make the t = fact/j turn white too? Obviously this can be done in C, but I don't know how to make Cython do it right. Thank you! kcrisman (Apr 20 '11)
Actually, it doesn't matter, because I need too long of numbers for the code to work right. No choice but to use Sage integers, I guess :) This is not for high performance! kcrisman (Apr 20 '11)
To answer your second comment: there is a cython compiler directive you can use `cdivision=True`. This turns off exception checking for division by zero. It's the exception checking that adds more C code and why the annotated code there is yellow. Look at http://docs.cython.org/src/reference/compilation.htmlbenjaminfjones (Apr 20 '11)
Thanks, that makes sense. I'm just never sure what will behave like Python and what will behave like what I think (not know) C will do. As I said, even with longs this code becomes wrong after about n=22, and as it's just for demonstration I have no interest in importing mpz etc :) kcrisman (Apr 21 '11)

Your answer

Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
[hide preview]

Question tools

Tags:

Stats:

Asked: Apr 20 '11

Seen: 483 times

Last updated: Apr 21 '11

powered by ASKBOT version 0.7.22
Copyright Sage, 2010. Some rights reserved under creative commons license.