summaryrefslogtreecommitdiff
path: root/doc/cython/numpyx.pyx
diff options
context:
space:
mode:
authorStefan van der Walt <stefan@sun.ac.za>2008-08-23 23:17:23 +0000
committerStefan van der Walt <stefan@sun.ac.za>2008-08-23 23:17:23 +0000
commit5c86844c34674e3d580ac2cd12ef171e18130b13 (patch)
tree2fdf1150706c07c7e193eb7483ce58a5074e5774 /doc/cython/numpyx.pyx
parent376d483d31c4c5427510cf3a8c69fc795aef63aa (diff)
downloadnumpy-5c86844c34674e3d580ac2cd12ef171e18130b13.tar.gz
Move documentation outside of source tree. Remove `doc` import from __init__.
Diffstat (limited to 'doc/cython/numpyx.pyx')
-rw-r--r--doc/cython/numpyx.pyx127
1 files changed, 127 insertions, 0 deletions
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'% \
+ (<py.Py_intptr_t><void *>arr,)
+ print 'number of dimensions:',arr.nd
+ print 'address of strides: 0x%0lx'%(<py.Py_intptr_t>arr.strides,)
+ print 'strides:'
+ for i from 0<=i<arr.nd:
+ # print each stride
+ print ' stride %d:'%i,<py.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.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 = (<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(cnp.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)
+