mysum in Cython as
follows. Note the trick of void
pointers to avoid Cython reference counting, etc:
def mysum(x):
cdef object seq
cdef int len,i
cdef object item
cdef object total
total = 0
cdef PyObject** X
X = FAST_SEQ_UNSAFE(x)
for i from 0 <=i<len:
item = <object>X[i]
total = total + item
return (total)
FAST_SEQ_UNSAFE gets direct very very
unsafe access to the underlying array of PyObject's.
Somewhat surprisingly, this is actually faster than Python's built in sum function:
sage: time sum(range(5*10^6)) CPU times: user 1.59 s, sys: 0.08 s, total: 1.67 s 12499997500000L sage: time mysum(range(5*10^6)) CPU times: user 1.46 s, sys: 0.03 s, total: 1.49 s 12499997500000L
In the next example, we illustrate the above idea by defining
several simplified versions of the range command.
%skip
%cython
def f0(int n):
return eval('[%s for _ in xrange(%s)]'%(n, n))
def f1(int n):
v = []
for i from 0 <= i < n:
v.append(i)
return v
def f2(int n):
cdef int i
v = [None] * n
for i from 0 <= i < n:
v[i] = i
return v
def f3(int n):
cdef int i
w = [None] * n
cdef void** X
X = FAST_SEQ_UNSAFE(w)
for i from 0 <= i < n:
Py_DECREF(<PyObject*>X[i])
X[i] = PyInt_FromLong(i)
return w
def f4(int n):
cdef int i
v = PyList_New(n)
for i from 0 <= i < n:
PyList_SET_ITEM(v, i, <object>PyInt_FromLong(i))
#WARNING -- maybe I need to incref the ref to the long?!
return v
The fourth one is the fastest.
See About this document... for information on suggesting changes.