User guide

NumPy User Guide, Release 1.9.0
If you just use Pyrex to compile a standard Python module, then you will get a C-extension module that runs either
as fast or, possibly, more slowly than the equivalent Python module. Speed increases are possible only when you use
cdef to statically define C variables and use a special construct to create for loops:
cdef int i
for i from start <= i < stop
Let’s look at two examples we’ve seen before to see how they might be implemented using Pyrex. These examples
were compiled into extension modules using Pyrex-0.9.3.1.
Pyrex-add
Here is part of a Pyrex-file I named add.pyx which implements the add functions we previously implemented using
f2py:
cimport c_numpy
from c_numpy cimport import_array, ndarray, npy_intp, npy_cdouble, \
npy_cfloat, NPY_DOUBLE, NPY_CDOUBLE, NPY_FLOAT, \
NPY_CFLOAT
#We need to initialize NumPy
import_array()
def zadd(object ao, object bo):
cdef ndarray c, a, b
cdef npy_intp i
a = c_numpy.PyArray_ContiguousFromAny(ao,
NPY_CDOUBLE, 1, 1)
b = c_numpy.PyArray_ContiguousFromAny(bo,
NPY_CDOUBLE, 1, 1)
c = c_numpy.PyArray_SimpleNew(a.nd, a.dimensions,
a.descr.type_num)
for i from 0 <= i < a.dimensions[0]:
(<npy_cdouble
*
>c.data)[i].real = \
(<npy_cdouble
*
>a.data)[i].real + \
(<npy_cdouble
*
>b.data)[i].real
(<npy_cdouble
*
>c.data)[i].imag = \
(<npy_cdouble
*
>a.data)[i].imag + \
(<npy_cdouble
*
>b.data)[i].imag
return c
This module shows use of the cimport statement to load the definitions from the c_numpy.pxd file. As shown, both
versions of the import statement are supported. It also shows use of the NumPy C-API to construct NumPy arrays
from arbitrary input objects. The array c is created using PyArray_SimpleNew. Then the c-array is filled by addition.
Casting to a particiular data-type is accomplished using <cast *>. Pointers are de-referenced with bracket notation and
members of structures are accessed using ‘. notation even if the object is techinically a pointer to a structure. The use
of the special for loop construct ensures that the underlying code will have a similar C-loop so the addition calculation
will proceed quickly. Notice that we have not checked for NULL after calling to the C-API a cardinal sin when
writing C-code. For routines that return Python objects, Pyrex inserts the checks for NULL into the C-code for you
and returns with failure if need be. There is also a way to get Pyrex to automatically check for exceptions when you
call functions that don’t return Python objects. See the documentation of Pyrex for details.
Pyrex-filter
The two-dimensional example we created using weave is a bit uglier to implement in Pyrex because two-dimensional
indexing using Pyrex is not as simple. But, it is straightforward (and possibly faster because of pre-computed indices).
70 Chapter 5. Using Numpy C-API