Posts Tagged ‘python’

Sage ( at GSoC 2012

19 March, 2012

Sage (not the accounting software, but is accepted to Google Summer of Code 2012, and I will be one of many mentors. 

Experimental Sage-based Mathematics course

7 August, 2011

We are to embark upon teaching a 2nd year undergraduate course Experimental Mathematics, which will cover computer algebra basics, and refresh concepts from 1st year linear algebra, calculus, and combinatoris, with few more advanced things thrown in. The course will be based on Sage, with the actual software running on dedicated servers, and accessible via Sage web notebook interface (i.e. basically nothing but a web browser running on the student’s computer/laptop/ipad, etc).

Given the enrollment of about 120, this will be interesting…

PS. Most students did not appreciate the freedom given, and complained, complained, complained…

Python extensions with C libraries made easy by Cython

16 October, 2010

Suppose you have a library written in C that you like to be called from Python. There are many ways to accomplish this, and I would like to show here a complete example of doing this using Cython, which is basically a compiler from (an extension of Python) to C. Most of this, and much more, can be found in a quick tutorial.
For the purpose of an example, suppose you have a C function that computes the average of an array of doubles (all source files here, as well as the Makefile that basically contains the shell commands we show below, can be downloaded here, or cloned using git from github):

/* cmean.c */
double mean(int n, double* a)
double s;
int i;
for (s=0., i=0; i<n; i++) s+=*(a++);
return s/n;

with the prototype

/* cmean.h */
double mean(int, double*);

and you want to call it from Python, i.e. (we need to give the function another name here, cmean(), for technical as well as for semantic reasons—noone would pass the length of an array and the array to a function in Python, as the array itself would certainly do) say

print cmean(b)

would print the same as

print sum(b)/len(b)

As cmean() is not a Python built-in, we would expect to import it first. So the following

$ python


import dyn
from dyn import cmean
print cmean(b)
print sum(b)/len(b)

will print the number 18.01944425 twice. OK, so here is cmean() definition in Cython (note the file extension .pyx)

# m.pyx
cdef extern from "cmean.h":
double mean(int, double*)
from stdlib cimport *
def cmean(a):
n = len(a)
cdef double *v
v = malloc(n*sizeof(double))
for i in range(n):
v[i] = float(a[i])
m = mean(n, v)
return m

The main task of cmean() is to create a “plain” C array of doubles, pass it to our C function, get the result, clean after itself, and return the result. Unlike Python, Cython has types declarations. Unless one calls C-function from the Cython code, they are not mandatory though, although they can speed the things up tremendously in “real” computations. In the example here

cdef double *v

cannot be avoided — the code does not compile without it. In a usual C-like fasion, instead of 2 lines

cdef double *v
v = malloc(n*sizeof(double))

one could have written just

cdef double *v = malloc(n*sizeof(double))

The top two lines pass the prototype declaration of the C-function mean to be included into the C file to be generated, and the third line imports the functions from the C library stdlib (we need malloc and free from there).

Having this, we need to create the extension module dyn, to be imported by Python. This is perhaps the least intuitive part of the job. One way to accomplish it is to use Python distutils: i.e. we need to create a file to be called as

$ python build_ext --inplace

This should look as follows:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
library_dirs = ['.'],
libraries=["cmean"]) # Unix-like specific
name = "Demos",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules

One not yet explained thing here is how the shared library containing the compiled C-function mean() is hooked up to dyn. You see in the code above the declarations library_dirs and libraries. They assume that the shared library is called and that it is in the same directory (i.e. ‘.’ is the path to it) as the rest of the code. One can create (before creating dyn, more precisely, a file called by running

$ gcc -fPIC -shared cmean.c -o

One more point to watch is that on some Unix systems the loader will be unable to locate the dynamic libraries and/or we created (unless they are placed in certain stanadard directories, which is not something one wants to do with experimental code!). So will need to be run, e.g., as follows:

$ LD_LIBRARY_PATH=. python

For the sake of completeness, the aforementioned archive contains a C file that calls mean from, and the corresponding entries in the Makefile can do the necessary work to build and run it.

Last but not least, Sage automates parts of the interface building even better.