summaryrefslogtreecommitdiff
path: root/numpy/doc/cython
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/doc/cython')
-rw-r--r--numpy/doc/cython/MANIFEST2
-rw-r--r--numpy/doc/cython/Makefile37
-rw-r--r--numpy/doc/cython/Python.pxi62
-rw-r--r--numpy/doc/cython/README.txt20
-rw-r--r--numpy/doc/cython/numpy.pxi133
-rw-r--r--numpy/doc/cython/numpyx.pyx118
-rwxr-xr-xnumpy/doc/cython/run_test.py3
-rwxr-xr-xnumpy/doc/cython/setup.py49
8 files changed, 424 insertions, 0 deletions
diff --git a/numpy/doc/cython/MANIFEST b/numpy/doc/cython/MANIFEST
new file mode 100644
index 000000000..feb3ec22a
--- /dev/null
+++ b/numpy/doc/cython/MANIFEST
@@ -0,0 +1,2 @@
+numpyx.pyx
+setup.py
diff --git a/numpy/doc/cython/Makefile b/numpy/doc/cython/Makefile
new file mode 100644
index 000000000..80be2c066
--- /dev/null
+++ b/numpy/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 numpy.pyx.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/numpy/doc/cython/Python.pxi b/numpy/doc/cython/Python.pxi
new file mode 100644
index 000000000..46d2fd1a7
--- /dev/null
+++ b/numpy/doc/cython/Python.pxi
@@ -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/numpy/doc/cython/README.txt b/numpy/doc/cython/README.txt
new file mode 100644
index 000000000..ff0abb0fe
--- /dev/null
+++ b/numpy/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/numpy/doc/cython/numpy.pxi b/numpy/doc/cython/numpy.pxi
new file mode 100644
index 000000000..11cb8fac9
--- /dev/null
+++ b/numpy/doc/cython/numpy.pxi
@@ -0,0 +1,133 @@
+# :Author: Travis Oliphant
+
+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/numpy/doc/cython/numpyx.pyx b/numpy/doc/cython/numpyx.pyx
new file mode 100644
index 000000000..84dc333df
--- /dev/null
+++ b/numpy/doc/cython/numpyx.pyx
@@ -0,0 +1,118 @@
+# -*- Mode: Python -*- Not really, but close enough
+"""Cython access to Numpy arrays - simple example.
+"""
+
+# Includes from the python headers
+include "Python.pxi"
+# Include the Numpy C API for use via Cython extension code
+include "numpy.pxi"
+
+################################################
+# Initialize numpy - this MUST be done before any other code is executed.
+import_array()
+
+# Import the Numpy module for access to its usual Python API
+import numpy as np
+
+
+# A 'def' function is visible in the Python-imported module
+def print_array_info(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_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_intptr_t cast:
+ print 'Printing array info for ndarray at 0x%0lx'% \
+ (<Py_intptr_t><void *>arr,)
+ print 'number of dimensions:',arr.nd
+ print 'address of strides: 0x%0lx'%(<Py_intptr_t>arr.strides,)
+ print 'strides:'
+ for i from 0<=i<arr.nd:
+ # print each stride
+ print ' stride %d:'%i,<Py_intptr_t>arr.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_intptr_t* strides,
+ Py_intptr_t* dimensions,
+ int nd,
+ int elsize,
+ object dtype):
+ cdef 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 = (<void**>data)[0] #[0] dereferences pointer in Pyrex
+ print ' ',<object>elptr
+ elif dtype==np.dtype(np.float64):
+ print ' ',(<double*>data)[0]
+ elif nd == 1:
+ for i from 0<=i<dimensions[0]:
+ if dtype==np.dtype(np.object_):
+ elptr = (<void**>data)[0]
+ print ' ',<object>elptr
+ elif dtype==np.dtype(np.float64):
+ print ' ',(<double*>data)[0]
+ data = data + strides[0]
+ else:
+ for i from 0<=i<dimensions[0]:
+ print_elements(data, strides+1, dimensions+1, nd-1, elsize, dtype)
+ data = data + strides[0]
+
+def test_methods(ndarray arr):
+ """Test a few attribute accesses for an array.
+
+ This illustrates how the pyrex-visible object is in practice a strange
+ hybrid of the C PyArrayObject struct and the python object. Some
+ properties (like .nd) are visible here but not in python, while others
+ like flags behave very differently: in python flags appears as a separate,
+ object while here we see the raw int holding the bit pattern.
+
+ This makes sense when we think of how pyrex resolves arr.foo: if foo is
+ listed as a field in the ndarray struct description, it will be directly
+ accessed as a C variable without going through Python at all. This is why
+ for arr.flags, we see the actual int which holds all the flags as bit
+ fields. However, for any other attribute not listed in the struct, it
+ simply forwards the attribute lookup to python at runtime, just like python
+ would (which means that AttributeError can be raised for non-existent
+ attributes, for example)."""
+
+ print 'arr.any() :',arr.any()
+ print 'arr.nd :',arr.nd
+ print 'arr.flags :',arr.flags
+
+def test():
+ """this function is pure Python"""
+ arr1 = np.array(-1e-30,dtype=np.float64)
+ arr2 = np.array([1.0,2.0,3.0],dtype=np.float64)
+
+ arr3 = np.arange(9,dtype=np.float64)
+ arr3.shape = 3,3
+
+ four = 4
+ arr4 = np.array(['one','two',3,four],dtype=np.object_)
+
+ arr5 = np.array([1,2,3]) # int types not (yet) supported by print_elements
+
+ for arr in [arr1,arr2,arr3,arr4,arr5]:
+ print_array_info(arr)
+
diff --git a/numpy/doc/cython/run_test.py b/numpy/doc/cython/run_test.py
new file mode 100755
index 000000000..96388011e
--- /dev/null
+++ b/numpy/doc/cython/run_test.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+from numpyx import test
+test()
diff --git a/numpy/doc/cython/setup.py b/numpy/doc/cython/setup.py
new file mode 100755
index 000000000..270e11c56
--- /dev/null
+++ b/numpy/doc/cython/setup.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+"""Install file for example on how to use Cython with Numpy.
+
+Note: Cython is the successor project to Pyrex. For more information, see
+http://cython.org.
+"""
+
+from distutils.core import setup
+from distutils.extension import Extension
+
+import numpy
+
+# We detect whether Cython is available, so that below, we can eventually ship
+# pre-generated C for users to compile the extension without having Cython
+# installed on their systems.
+try:
+ from Cython.Distutils import build_ext
+ has_cython = True
+except ImportError:
+ has_cython = False
+
+# Define a cython-based extension module, using the generated sources if cython
+# is not available.
+if has_cython:
+ pyx_sources = ['numpyx.pyx']
+ cmdclass = {'build_ext': build_ext}
+else:
+ # In production work, you can ship the auto-generated C source yourself to
+ # your users. In this case, we do NOT ship the .c file as part of numpy,
+ # so you'll need to actually have cython installed at least the first
+ # time. Since this is really just an example to show you how to use
+ # *Cython*, it makes more sense NOT to ship the C sources so you can edit
+ # the pyx at will with less chances for source update conflicts when you
+ # update numpy.
+ pyx_sources = ['numpyx.c']
+ cmdclass = {}
+
+
+# Declare the extension object
+pyx_ext = Extension('numpyx',
+ pyx_sources,
+ include_dirs = [numpy.get_include()])
+
+# Call the routine which does the real work
+setup(name = 'numpyx',
+ description = 'Small example on using Cython to write a Numpy extension',
+ ext_modules = [pyx_ext],
+ cmdclass = cmdclass,
+ )