===================
Pythran User Manual
===================

So you want to write algorithms that are easy to maintain as in python and
you want performance as in fortran or c++? Let give a try to pythran!
pythran is a python-to-c++ translator that turns python module into native c++
module. From a user point of view, you still ``import`` your module, but under
the hood... there is much more happening!

Disclaimer
----------

Pythran is *not* a full python-to-c++ converter, as in *shedskin*. Instead it
takes a subset of the python language and turns it into heavily templatized c++
code instantiated for your particular types.

Say hello to:

- polymorphic functions (!)
- lambdas
- list comprehension
- map, reduce and the like

Say bye bye to:

- classes
- dictionnaries
- exceptions
- polymorphic variables [ but not all of them :-) ]
- file handling

In a nutshell, pythran makes it possible to write numerical algorithms in
python and to have them run faster. Nuff said.

Installation
------------

Let us assume you're running a Debian/Ubuntu distrib. In that case, all you have to do is::

	$> sudo apt-get install libboost-python-dev python-ply python-networkx

If you prefer the ``easy_install`` way, from ``setuptools``
(``python-setuptools`` package under Debian), the way to go is::

	$>  PYTHONPATH=<my_prefix>/lib/python<my_version>/site-packages \
			easy_install --prefix <my_prefix> ply networkx

and set your ``PYTHONPATH`` appropriately, something like::

	$> export  PYTHONPATH=<my_prefix>/lib/python<my_version>/site-packages

And you're almost done! From the source directory, run::

	$> python setup.py install --prefix=<my_prefix>

And set your path to::

	$> export PATH=$PATH:<my_prefix>/bin

It makes the ``pythran`` command available to you.

Making Sure Everything is working
---------------------------------

The ``setup.py`` scripts automates this. The ``test`` target, as in::

    python setup.py test

runs a whole (and long) validation suite. The ``bench`` target, as in::

    python setup.py bench

compares the performance of pythran-generated code with cpython.

First Steps
-----------

To begin with, you need... a python function in a module. Something like::

	<<dprod.py>>
	def dprod(l0,l1):
		return sum([x*y for x,y in zip(l0,l1)])

will be perfect. But due to \_o< typing, ``l0`` and ``l1`` can be of any type,
so pythran needs a small hint there. Add the following line somewhere in your
file, say at the top head, or right before the function definition::

	#pythran export dprod(int list, int list)

This basically tells pythran the type of the forthcoming arguments.


Afterwards, frenetically type::

	$> pythran dprod.py

\o/ a ``dprod.so`` native module has been created and you can play with it
right *now*. The speedup will not be terrible because of the conversion cost
from python to C++.

So let's try again with a well-known example. Let me
introduce the almighty *matrix multiply*!::

	<<mm.py>>
	def zero(n,m): return [[0 for row in xrange(n)] for col in xrange(m)]
	def matrix_multiply(m0, m1):
		new_matrix = zero(len(m0),len(m1[0]))
		for i in xrange(len(m0)):
			for j in xrange(len(m1[0])):
				for k in xrange(len(m1)):
					new_matrix[i][j] += m0[i][k]*m1[k][j]
		return new_matrix

This a slightly more complex example, as a few intrinsics such as ``xrange`` or
``len`` are used, with a function call and even nested list comprehension. But
pythran can make its way through this. As you only want to export the
``matrix_multiply`` function, you can safely ignore the ``zero`` function and
just add::

	#pythran export matrix_multiply(float list list, float list list)

to the source file. Note how pythran can combine different types and infers the
resulting type. It also respects the nested list structure of python, so you
are not limited to matrices...

Enough talk, run::

	$> pythran mm.py

One touch of magic wand and you have your native binary. Note however that this
binary will not run directly at godlike speed, because it does not call any of
g++ optimization setps. What you really wanted to do was::

	$> pythran mm.py -Ofast -march=native -DNDEBUG

And be amazed by the generation of a ``mm.so`` native module that run around
20x faster than the original one. ``timeit`` approved!



Concerning Pythran specifications
---------------------------------

The ``#pythran export`` commands are critical to pythran. In fact if they are
missing, pythran will complain loudly (and fail miserably). So let us dive into
these complex language!

There is currently only one pythran command, the ``export`` command. Its syntax is::

	#pythran export function_name(argument_type*)

where ``function_name`` is the name of a function defined in the module, and
``argument_type*`` is a comma separated list of argument types, composed of any
combination of basic types and constructed types. What is a basic type?
Anything that looks like a python basic type! Constructed types are either
tuples, introduced by parenthesis, like ``(int, (float, str))`` or lists (resp.
set), introduced by the ``list`` (resp. ``set``) keyword::

	argument_type = basic_type
				  | (argument_type*)	# this is a tuple
				  | argument_type list	# this is a list
				  | argument_type set	# this is a set

	basic_type = bool | int | long | float | str

Easy enough, isn't it?

Advanced Usage
--------------

A failing compilation? A lust of c++ tangled code? Give a try to the ``-E``
switch that stops the compilation process right after c++ code generation, so
that you can inspect it.

Want more performance? Big fan of ``-Ofast -march=native``? pythran
automagically forwards these switches to the underlying compiler! pythran is
sensible to the ``-DNDEBUG`` switch too.

Wants to try your own compiler? Pythran uses ``c++`` by default, and this
behavior can be overridden using ``CXX`` or ``CXXFLAGS`` environment variables.

Adding OpenMP directives
------------------------

OpenMP is a standard set of directives for C, C++ and FORTRAN that makes it
somehow easier to turn a sequential program into a multithreaed one. Pythran
translates OpenMP-like code annotation into OpenMP directives::

    r=0
    "omp parallel for reduction(+:r) private(x,y)"
    for x,y in zip(l1,l2):
        r+=x*y

Note that as in python, all variables have function-level scope, ``x`` and
``y`` must be explicitely listed as private variables.

OpenMP directive parsing is enabled by ``-fopenmp`` when using ``g++`` as the
abckend compiler.

Getting Pure C++
----------------

Pythran can be used to generate raw templated C++ code, without any python
glue. To do so use the ``-e`` switch. It will turn the python code into c++
code you can call from a C++ code. In that case there is **no** need for a
particular Pythran specification.

Troubleshooting
---------------

Plenty of them! Seriously, pythran is pre-alpha software, so it will crash. You
must make it abort in unusual ways! And more important, you must provide
feedback to serge_sans_paille using its email serge.guelton@telecom-bretagne.eu
or the IRC channel ``#pythran`` on FreeNode.

**glhf!**
