From 5c86844c34674e3d580ac2cd12ef171e18130b13 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Sat, 23 Aug 2008 23:17:23 +0000 Subject: Move documentation outside of source tree. Remove `doc` import from __init__. --- doc/cython/MANIFEST | 2 + doc/cython/Makefile | 37 +++++++++++++ doc/cython/README.txt | 20 +++++++ doc/cython/c_numpy.pxd | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/cython/c_python.pxd | 62 ++++++++++++++++++++++ doc/cython/numpyx.pyx | 127 ++++++++++++++++++++++++++++++++++++++++++++ doc/cython/run_test.py | 3 ++ doc/cython/setup.py | 49 +++++++++++++++++ 8 files changed, 436 insertions(+) create mode 100644 doc/cython/MANIFEST create mode 100644 doc/cython/Makefile create mode 100644 doc/cython/README.txt create mode 100644 doc/cython/c_numpy.pxd create mode 100644 doc/cython/c_python.pxd create mode 100644 doc/cython/numpyx.pyx create mode 100755 doc/cython/run_test.py create mode 100755 doc/cython/setup.py (limited to 'doc/cython') diff --git a/doc/cython/MANIFEST b/doc/cython/MANIFEST new file mode 100644 index 000000000..feb3ec22a --- /dev/null +++ b/doc/cython/MANIFEST @@ -0,0 +1,2 @@ +numpyx.pyx +setup.py diff --git a/doc/cython/Makefile b/doc/cython/Makefile new file mode 100644 index 000000000..7c9c72981 --- /dev/null +++ b/doc/cython/Makefile @@ -0,0 +1,37 @@ +# Simple makefile to quickly access handy build commands for Cython extension +# code generation. Note that the actual code to produce the extension lives in +# the setup.py file, this Makefile is just meant as a command +# convenience/reminder while doing development. + +help: + @echo "Numpy/Cython tasks. Available tasks:" + @echo "ext -> build the Cython extension module." + @echo "html -> create annotated HTML from the .pyx sources" + @echo "test -> run a simple test demo." + @echo "all -> Call ext, html and finally test." + +all: ext html test + +ext: numpyx.so + +test: ext + python run_test.py + +html: numpyx.pyx.html + +numpyx.so: numpyx.pyx numpyx.c + python setup.py build_ext --inplace + +numpyx.pyx.html: numpyx.pyx + cython -a numpyx.pyx + @echo "Annotated HTML of the C code generated in numpyx.html" + +# Phony targets for cleanup and similar uses + +.PHONY: clean +clean: + rm -rf *~ *.so *.c *.o *.html build + +# Suffix rules +%.c : %.pyx + cython $< diff --git a/doc/cython/README.txt b/doc/cython/README.txt new file mode 100644 index 000000000..ff0abb0fe --- /dev/null +++ b/doc/cython/README.txt @@ -0,0 +1,20 @@ +================== + NumPy and Cython +================== + +This directory contains a small example of how to use NumPy and Cython +together. While much work is planned for the Summer of 2008 as part of the +Google Summer of Code project to improve integration between the two, even +today Cython can be used effectively to write optimized code that accesses +NumPy arrays. + +The example provided is just a stub showing how to build an extension and +access the array objects; improvements to this to show more sophisticated tasks +are welcome. + +To run it locally, simply type:: + + make help + +which shows you the currently available targets (these are just handy +shorthands for common commands). \ No newline at end of file diff --git a/doc/cython/c_numpy.pxd b/doc/cython/c_numpy.pxd new file mode 100644 index 000000000..4a0bd1c01 --- /dev/null +++ b/doc/cython/c_numpy.pxd @@ -0,0 +1,136 @@ +# :Author: Travis Oliphant + +# API declaration section. This basically exposes the NumPy C API to +# Pyrex/Cython programs. + +cdef extern from "numpy/arrayobject.h": + + cdef enum NPY_TYPES: + NPY_BOOL + NPY_BYTE + NPY_UBYTE + NPY_SHORT + NPY_USHORT + NPY_INT + NPY_UINT + NPY_LONG + NPY_ULONG + NPY_LONGLONG + NPY_ULONGLONG + NPY_FLOAT + NPY_DOUBLE + NPY_LONGDOUBLE + NPY_CFLOAT + NPY_CDOUBLE + NPY_CLONGDOUBLE + NPY_OBJECT + NPY_STRING + NPY_UNICODE + NPY_VOID + NPY_NTYPES + NPY_NOTYPE + + cdef enum requirements: + NPY_CONTIGUOUS + NPY_FORTRAN + NPY_OWNDATA + NPY_FORCECAST + NPY_ENSURECOPY + NPY_ENSUREARRAY + NPY_ELEMENTSTRIDES + NPY_ALIGNED + NPY_NOTSWAPPED + NPY_WRITEABLE + NPY_UPDATEIFCOPY + NPY_ARR_HAS_DESCR + + NPY_BEHAVED + NPY_BEHAVED_NS + NPY_CARRAY + NPY_CARRAY_RO + NPY_FARRAY + NPY_FARRAY_RO + NPY_DEFAULT + + NPY_IN_ARRAY + NPY_OUT_ARRAY + NPY_INOUT_ARRAY + NPY_IN_FARRAY + NPY_OUT_FARRAY + NPY_INOUT_FARRAY + + NPY_UPDATE_ALL + + cdef enum defines: + NPY_MAXDIMS + + ctypedef struct npy_cdouble: + double real + double imag + + ctypedef struct npy_cfloat: + double real + double imag + + ctypedef int npy_intp + + ctypedef extern class numpy.dtype [object PyArray_Descr]: + cdef int type_num, elsize, alignment + cdef char type, kind, byteorder, hasobject + cdef object fields, typeobj + + ctypedef extern class numpy.ndarray [object PyArrayObject]: + cdef char *data + cdef int nd + cdef npy_intp *dimensions + cdef npy_intp *strides + cdef object base + cdef dtype descr + cdef int flags + + ctypedef extern class numpy.flatiter [object PyArrayIterObject]: + cdef int nd_m1 + cdef npy_intp index, size + cdef ndarray ao + cdef char *dataptr + + ctypedef extern class numpy.broadcast [object PyArrayMultiIterObject]: + cdef int numiter + cdef npy_intp size, index + cdef int nd + cdef npy_intp *dimensions + cdef void **iters + + object PyArray_ZEROS(int ndims, npy_intp* dims, NPY_TYPES type_num, int fortran) + object PyArray_EMPTY(int ndims, npy_intp* dims, NPY_TYPES type_num, int fortran) + dtype PyArray_DescrFromTypeNum(NPY_TYPES type_num) + object PyArray_SimpleNew(int ndims, npy_intp* dims, NPY_TYPES type_num) + int PyArray_Check(object obj) + object PyArray_ContiguousFromAny(object obj, NPY_TYPES type, + int mindim, int maxdim) + object PyArray_ContiguousFromObject(object obj, NPY_TYPES type, + int mindim, int maxdim) + npy_intp PyArray_SIZE(ndarray arr) + npy_intp PyArray_NBYTES(ndarray arr) + void *PyArray_DATA(ndarray arr) + object PyArray_FromAny(object obj, dtype newtype, int mindim, int maxdim, + int requirements, object context) + object PyArray_FROMANY(object obj, NPY_TYPES type_num, int min, + int max, int requirements) + object PyArray_NewFromDescr(object subtype, dtype newtype, int nd, + npy_intp* dims, npy_intp* strides, void* data, + int flags, object parent) + + object PyArray_FROM_OTF(object obj, NPY_TYPES type, int flags) + object PyArray_EnsureArray(object) + + object PyArray_MultiIterNew(int n, ...) + + char *PyArray_MultiIter_DATA(broadcast multi, int i) + void PyArray_MultiIter_NEXTi(broadcast multi, int i) + void PyArray_MultiIter_NEXT(broadcast multi) + + object PyArray_IterNew(object arr) + void PyArray_ITER_NEXT(flatiter it) + + void import_array() diff --git a/doc/cython/c_python.pxd b/doc/cython/c_python.pxd new file mode 100644 index 000000000..46d2fd1a7 --- /dev/null +++ b/doc/cython/c_python.pxd @@ -0,0 +1,62 @@ +# :Author: Robert Kern +# :Copyright: 2004, Enthought, Inc. +# :License: BSD Style + + +cdef extern from "Python.h": + # Not part of the Python API, but we might as well define it here. + # Note that the exact type doesn't actually matter for Pyrex. + ctypedef int size_t + + # Some type declarations we need + ctypedef int Py_intptr_t + + + # String API + char* PyString_AsString(object string) + char* PyString_AS_STRING(object string) + object PyString_FromString(char* c_string) + object PyString_FromStringAndSize(char* c_string, int length) + object PyString_InternFromString(char *v) + + # Float API + object PyFloat_FromDouble(double v) + double PyFloat_AsDouble(object ob) + long PyInt_AsLong(object ob) + + + # Memory API + void* PyMem_Malloc(size_t n) + void* PyMem_Realloc(void* buf, size_t n) + void PyMem_Free(void* buf) + + void Py_DECREF(object obj) + void Py_XDECREF(object obj) + void Py_INCREF(object obj) + void Py_XINCREF(object obj) + + # CObject API + ctypedef void (*destructor1)(void* cobj) + ctypedef void (*destructor2)(void* cobj, void* desc) + int PyCObject_Check(object p) + object PyCObject_FromVoidPtr(void* cobj, destructor1 destr) + object PyCObject_FromVoidPtrAndDesc(void* cobj, void* desc, + destructor2 destr) + void* PyCObject_AsVoidPtr(object self) + void* PyCObject_GetDesc(object self) + int PyCObject_SetVoidPtr(object self, void* cobj) + + # TypeCheck API + int PyFloat_Check(object obj) + int PyInt_Check(object obj) + + # Error API + int PyErr_Occurred() + void PyErr_Clear() + int PyErr_CheckSignals() + +cdef extern from "string.h": + void *memcpy(void *s1, void *s2, int n) + +cdef extern from "math.h": + double fabs(double x) diff --git a/doc/cython/numpyx.pyx b/doc/cython/numpyx.pyx new file mode 100644 index 000000000..cbc786ef0 --- /dev/null +++ b/doc/cython/numpyx.pyx @@ -0,0 +1,127 @@ +# -*- Mode: Python -*- Not really, but close enough +"""Cython access to Numpy arrays - simple example. +""" + +############################################################################# +# Load C APIs declared in .pxd files via cimport +# +# A 'cimport' is similar to a Python 'import' statement, but it provides access +# to the C part of a library instead of its Python-visible API. See the +# Pyrex/Cython documentation for details. + +cimport c_python as py + +cimport c_numpy as cnp + +# NOTE: numpy MUST be initialized before any other code is executed. +cnp.import_array() + +############################################################################# +# Load Python modules via normal import statements + +import numpy as np + +############################################################################# +# Regular code section begins + +# A 'def' function is visible in the Python-imported module +def print_array_info(cnp.ndarray arr): + """Simple information printer about an array. + + Code meant to illustrate Cython/NumPy integration only.""" + + cdef int i + + print '-='*10 + # Note: the double cast here (void * first, then py.Py_intptr_t) is needed + # in Cython but not in Pyrex, since the casting behavior of cython is + # slightly different (and generally safer) than that of Pyrex. In this + # case, we just want the memory address of the actual Array object, so we + # cast it to void before doing the py.Py_intptr_t cast: + print 'Printing array info for ndarray at 0x%0lx'% \ + (arr,) + print 'number of dimensions:',arr.nd + print 'address of strides: 0x%0lx'%(arr.strides,) + print 'strides:' + for i from 0<=iarr.strides[i] + print 'memory dump:' + print_elements( arr.data, arr.strides, arr.dimensions, + arr.nd, sizeof(double), arr.dtype ) + print '-='*10 + print + +# A 'cdef' function is NOT visible to the python side, but it is accessible to +# the rest of this Cython module +cdef print_elements(char *data, + py.Py_intptr_t* strides, + py.Py_intptr_t* dimensions, + int nd, + int elsize, + object dtype): + cdef py.Py_intptr_t i,j + cdef void* elptr + + if dtype not in [np.dtype(np.object_), + np.dtype(np.float64)]: + print ' print_elements() not (yet) implemented for dtype %s'%dtype.name + return + + if nd ==0: + if dtype==np.dtype(np.object_): + elptr = (data)[0] #[0] dereferences pointer in Pyrex + print ' ',elptr + elif dtype==np.dtype(np.float64): + print ' ',(data)[0] + elif nd == 1: + for i from 0<=idata)[0] + print ' ',elptr + elif dtype==np.dtype(np.float64): + print ' ',(data)[0] + data = data + strides[0] + else: + for i from 0<=i