[Numpy-svn] r4994 - in trunk/numpy/doc: . cython pyrex

numpy-svn at scipy.org numpy-svn at scipy.org
Tue Apr 8 21:55:00 EDT 2008


Author: fperez
Date: 2008-04-08 20:54:54 -0500 (Tue, 08 Apr 2008)
New Revision: 4994

Added:
   trunk/numpy/doc/cython/
   trunk/numpy/doc/cython/MANIFEST
   trunk/numpy/doc/cython/Makefile
   trunk/numpy/doc/cython/Python.pxi
   trunk/numpy/doc/cython/README.txt
   trunk/numpy/doc/cython/numpy.pxi
   trunk/numpy/doc/cython/numpyx.pyx
   trunk/numpy/doc/cython/run_test.py
   trunk/numpy/doc/cython/setup.py
   trunk/numpy/doc/pyrex/README.txt
Modified:
   trunk/numpy/doc/pyrex/numpyx.pyx
   trunk/numpy/doc/pyrex/setup.py
Log:
Add up to date (and slightly cleaned up) support for Cython after porting
the existing Pyrex one, put in deprecation markers in the old Pyrex dir.  

The pyrex dir can be removed in a subsequent commit.



Added: trunk/numpy/doc/cython/MANIFEST
===================================================================
--- trunk/numpy/doc/cython/MANIFEST	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/MANIFEST	2008-04-09 01:54:54 UTC (rev 4994)
@@ -0,0 +1,2 @@
+numpyx.pyx
+setup.py

Added: trunk/numpy/doc/cython/Makefile
===================================================================
--- trunk/numpy/doc/cython/Makefile	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/Makefile	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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 $<

Added: trunk/numpy/doc/cython/Python.pxi
===================================================================
--- trunk/numpy/doc/cython/Python.pxi	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/Python.pxi	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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)

Added: trunk/numpy/doc/cython/README.txt
===================================================================
--- trunk/numpy/doc/cython/README.txt	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/README.txt	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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

Added: trunk/numpy/doc/cython/numpy.pxi
===================================================================
--- trunk/numpy/doc/cython/numpy.pxi	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/numpy.pxi	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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()

Added: trunk/numpy/doc/cython/numpyx.pyx
===================================================================
--- trunk/numpy/doc/cython/numpyx.pyx	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/numpyx.pyx	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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)
+

Added: trunk/numpy/doc/cython/run_test.py
===================================================================
--- trunk/numpy/doc/cython/run_test.py	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/run_test.py	2008-04-09 01:54:54 UTC (rev 4994)
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+from numpyx import test
+test()


Property changes on: trunk/numpy/doc/cython/run_test.py
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/numpy/doc/cython/setup.py
===================================================================
--- trunk/numpy/doc/cython/setup.py	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/cython/setup.py	2008-04-09 01:54:54 UTC (rev 4994)
@@ -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,
+      )


Property changes on: trunk/numpy/doc/cython/setup.py
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/numpy/doc/pyrex/README.txt
===================================================================
--- trunk/numpy/doc/pyrex/README.txt	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/pyrex/README.txt	2008-04-09 01:54:54 UTC (rev 4994)
@@ -0,0 +1,3 @@
+WARNING: this code is deprecated and slated for removal soon.  See the
+doc/cython directory for the replacement, which uses Cython (the actively
+maintained version of Pyrex).

Modified: trunk/numpy/doc/pyrex/numpyx.pyx
===================================================================
--- trunk/numpy/doc/pyrex/numpyx.pyx	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/pyrex/numpyx.pyx	2008-04-09 01:54:54 UTC (rev 4994)
@@ -1,4 +1,8 @@
 # -*- Mode: Python -*-  Not really, but close enough
+"""WARNING: this code is deprecated and slated for removal soon.  See the
+doc/cython directory for the replacement, which uses Cython (the actively
+maintained version of Pyrex).
+"""
 
 cimport c_python
 cimport c_numpy

Modified: trunk/numpy/doc/pyrex/setup.py
===================================================================
--- trunk/numpy/doc/pyrex/setup.py	2008-04-09 00:57:23 UTC (rev 4993)
+++ trunk/numpy/doc/pyrex/setup.py	2008-04-09 01:54:54 UTC (rev 4994)
@@ -1,6 +1,12 @@
 #!/usr/bin/env python
-"""Install file for example on how to use Pyrex with Numpy.
+"""
+WARNING: this code is deprecated and slated for removal soon.  See the
+doc/cython directory for the replacement, which uses Cython (the actively
+maintained version of Pyrex).
 
+
+Install file for example on how to use Pyrex with Numpy.
+
 For more details, see:
 http://www.scipy.org/Cookbook/Pyrex_and_NumPy
 http://www.scipy.org/Cookbook/ArrayStruct_and_Pyrex




More information about the Numpy-svn mailing list