diff options
Diffstat (limited to 'numpy/doc/numpybook/capi.lyx')
-rw-r--r-- | numpy/doc/numpybook/capi.lyx | 24232 |
1 files changed, 24232 insertions, 0 deletions
diff --git a/numpy/doc/numpybook/capi.lyx b/numpy/doc/numpybook/capi.lyx new file mode 100644 index 000000000..04522d13d --- /dev/null +++ b/numpy/doc/numpybook/capi.lyx @@ -0,0 +1,24232 @@ +#LyX 1.5.1 created this file. For more info see http://www.lyx.org/ +\lyxformat 276 +\begin_document +\begin_header +\textclass mybook +\language english +\inputencoding auto +\font_roman default +\font_sans default +\font_typewriter default +\font_default_family default +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 +\graphics default +\paperfontsize default +\spacing onehalf +\papersize default +\use_geometry true +\use_amsmath 2 +\use_esint 0 +\cite_engine basic +\use_bibtopic false +\paperorientation portrait +\leftmargin 1in +\topmargin 1in +\rightmargin 1in +\bottommargin 1in +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\author "" +\author "" +\end_header + +\begin_body + +\begin_layout Part +C-API +\end_layout + +\begin_layout Chapter +New Python Types and C-Structures +\end_layout + +\begin_layout Quotation +Beware of the man who won't be bothered with details. +\end_layout + +\begin_layout Right Address +--- +\emph on +William Feather, Sr. +\end_layout + +\begin_layout Quotation +The truth is out there. +\end_layout + +\begin_layout Right Address +---Chris Carter, The X Files +\end_layout + +\begin_layout Standard +NumPy provides a C-API to enable users to extend the system and get access + to the array object for use in other routines. + The best way to truly understand the C-API is to read the source code. + If you are unfamiliar with (C) source code, however, this can be a daunting + experience at first. + Be assured that the task becomes easier with practice, and you may be surprised + at how simple the C-code can be to understand. + Even if you don't think you can write C-code from scratch, it is much easier + to understand and modify already-written source code then create it +\emph on +de novo +\emph default +. + +\end_layout + +\begin_layout Standard +Python extensions are especially straightforward to understand because they + all have a very similar structure. + Admittedly, NumPy is not a trivial extension to Python, and may take a + little more snooping to grasp. + This is especially true because of the code-generation techniques, which + simplify maintenance of very similar code, but can make the code a little + less readable to beginners. + Still, with a little persistence, the code can be opened to your understanding. + It is my hope, that this guide to the C-API can assist in the process of + becoming familiar with the compiled-level work that can be done with NumPy + in order to squeeze that last bit of necessary speed out of your code. +\end_layout + +\begin_layout Standard +Several new types are defined in the C-code. + Most of these are accessible from Python, but a few are not exposed due + to their limited use. + Every new Python type has an associated PyObject * with an internal structure + that includes a pointer to a +\begin_inset Quotes eld +\end_inset + +method table +\begin_inset Quotes erd +\end_inset + + that defines how the new object behaves in Python. + When you receive a Python object into C code, you always get a pointer + to a +\family typewriter +PyObject +\family default + structure. + Because a +\family typewriter +PyObject +\family default + structure is very generic and defines only +\family typewriter +PyObject_HEAD +\family default +, by itself it is not very interesting. + However, different objects contain more details after the +\family typewriter +PyObject_HEAD +\family default + (but you have to cast to the correct type to access them --- or use accessor + functions or macros). + +\end_layout + +\begin_layout Section +New Python Types Defined +\end_layout + +\begin_layout Standard +Python types are the functional equivalent in C of classes in Python. + By constructing a new Python type you make available a new object for Python. + The ndarray object is an example of a new type defined in C. + New types are defined in C by two basic steps: +\end_layout + +\begin_layout Enumerate +creating a C-structure (usually named Py<Name>Object) that is binary-compatible + with the +\family typewriter +PyObject +\family default + structure itself but holds the additional information needed for that particula +r object; +\end_layout + +\begin_layout Enumerate +populating the +\family typewriter +PyTypeObject +\family default + table (pointed to by the ob_type member of the +\family typewriter +PyObject +\family default + structure) with pointers to functions that implement the desired behavior + for the type. + +\end_layout + +\begin_layout Standard +Instead of special method names which define behavior for Python classes, + there are +\begin_inset Quotes eld +\end_inset + +function tables +\begin_inset Quotes erd +\end_inset + + which point to functions that implement the desired results. + Since Python 2.2, the PyTypeObject itself has become dynamic which allows + C types that can be +\begin_inset Quotes eld +\end_inset + +sub-typed +\begin_inset Quotes erd +\end_inset + + from other C-types in C, and sub-classed in Python. + The children types inherit the attributes and methods from their parent(s). + +\end_layout + +\begin_layout Standard +There are two major new types: the ndarray ( +\family typewriter +PyArray_Type +\family default +) and the ufunc ( +\family typewriter +PyUFunc_Type +\family default +). + Additional types play a supportive role: the +\family typewriter +PyArrayIter_Type +\family default +, the +\family typewriter +PyArrayMultiIter_Type +\family default +, and the +\family typewriter +PyArrayDescr_Type +\family default +. + The +\family typewriter +PyArrayIter_Type +\family default + is the type for a flat iterator for an ndarray (the object that is returned + when getting the flat attribute). + The +\family typewriter +PyArrayMultiIter_Type +\family default + is the type of the object returned when calling +\family typewriter +broadcast +\family default +(). + It handles iteration and broadcasting over a collection of nested sequences. + Also, the +\family typewriter +PyArrayDescr_Type +\family default + is the data-type-descriptor type whose instances describe the data. + Finally, there are 21 new scalar-array types which are new Python scalars + corresponding to each of the fundamental data types available for arrays. + An additional 10 other types are place holders that allow the array scalars + to fit into a hierarchy of actual Python types. + +\end_layout + +\begin_layout Subsection +PyArray_Type +\end_layout + +\begin_layout Standard +The Python type of the ndarray is +\family typewriter +PyArray_Type +\family default + +\begin_inset LatexCommand index +name "PyArray\\_Type" + +\end_inset + +. + In C, every ndarray is a pointer to a +\family typewriter +PyArrayObject +\family default + structure. + The ob_type member of this structure contains a pointer to the +\family typewriter +PyArray_Type +\family default + typeobject. + +\end_layout + +\begin_layout Standard +The +\family typewriter +PyArrayObject +\family default + C-structure contains all of the required information for an array. + All instances of an ndarray (and its subclasses) will have this structure. + For future compatibility, these structure members should normally be accessed + using the provided macros. + If you need a shorter name, then you can make use of +\family typewriter +NPY_AO +\family default + which is defined to be equivalent to +\family typewriter +PyArrayObject +\family default +. +\end_layout + +\begin_layout LyX-Code +typedef struct PyArrayObject { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +char * +\emph default +data; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nd; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp * +\emph default +dimensions; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp * +\emph default +strides; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject * +\emph default +base; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_Descr * +\emph default +descr; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + flags; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject * +\emph default +weakreflist; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArrayObject +\emph default +; +\end_layout + +\begin_layout Description +PyObject_HEAD This is needed by all Python objects. + It consists of (at least) a reference count member ( +\family typewriter +ob_refcnt +\family default +) and a pointer to the typeobject ( +\family typewriter +ob_type +\family default +). + (Other elements may also be present if Python was compiled with special + options see Include/object.h in the Python source tree for more information). + The ob_type member points to a Python type object. + +\end_layout + +\begin_layout Description +data A pointer to the first element of the array. + This pointer can (and normally should) be recast to the data type of the + array. + +\end_layout + +\begin_layout Description +nd An integer providing the number of dimensions for this array. + When nd is 0, the array is sometimes called a rank-0 array. + Such arrays have undefined dimensions and strides and cannot be accessed. + +\family typewriter +NPY_MAXDIMS +\family default + is the largest number of dimensions for any array. +\end_layout + +\begin_layout Description +dimensions An array of integers providing the shape in each dimension as + long as nd +\begin_inset Formula $\geq$ +\end_inset + +1. + The integer is always large enough to hold a pointer on the platform, so + the dimension size is only limited by memory. + +\end_layout + +\begin_layout Description +strides An array of integers providing for each dimension the number of + bytes that must be skipped to get to the next element in that dimension. + +\end_layout + +\begin_layout Description +base This member is used to hold a pointer to another Python object that + is related to this array. + There are two use cases: 1) If this array does not own its own memory, + then base points to the Python object that owns it (perhaps another array + object), 2) If this array has the +\family typewriter +NPY_UPDATEIFCOPY +\family default + flag set, then this array is a working copy of a +\begin_inset Quotes eld +\end_inset + +misbehaved +\begin_inset Quotes erd +\end_inset + + array. + As soon as this array is deleted, the array pointed to by base will be + updated with the contents of this array. + +\end_layout + +\begin_layout Description +descr A pointer to a data-type descriptor object (see below). + The data-type descriptor object is an instance of a new built-in type which + allows a generic description of memory. + There is a descriptor structure for each data type supported. + This descriptor structure contains useful information about the type as + well as a pointer to a table of function pointers to implement specific + functionality. +\end_layout + +\begin_layout Description +flags Flags indicating how the memory pointed to by data is to be interpreted. + Possible flags are +\family typewriter +NPY_C_CONTIGUOUS +\family default +, +\family typewriter +NPY_F_CONTIGUOUS +\family default +, +\family typewriter +NPY_OWNDATA +\family default +, +\family typewriter +NPY_ALIGNED +\family default +, +\family typewriter +NPY_WRITEABLE +\family default +, and +\family typewriter +NPY_UPDATEIFCOPY +\family default +. +\end_layout + +\begin_layout Description +weakreflist This member allows array objects to have weak references (using + the weakref module). + +\end_layout + +\begin_layout Subsection +PyArrayDescr_Type +\end_layout + +\begin_layout Standard +The +\family typewriter +PyArrayDescr_Type +\family default + +\begin_inset LatexCommand index +name "PyArrayDescr\\_Type" + +\end_inset + + is the built-in type of the data-type-descriptor objects used to describe + how the bytes comprising the array are to be interpreted. + There are 21 statically-defined +\family typewriter +PyArray_Descr +\family default + objects for the built-in data-types. + While these participate in reference counting, their reference count should + never reach zero. + There is also a dynamic table of user-defined +\family typewriter +PyArray_Descr +\family default + objects that is also maintained. + Once a data-type-descriptor object is +\begin_inset Quotes eld +\end_inset + +registered +\begin_inset Quotes erd +\end_inset + + it should never be deallocated either. + The function +\family typewriter +PyArray_DescrFromType +\family default +(...) can be used to retrieve a +\family typewriter +PyArray_Descr +\family default + object from an enumerated type-number (either built-in or user-defined). + The format of the structure that lies at the heart of the +\family typewriter +PyArrayDescr_Type +\family default + is. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +PyTypeObject * +\emph default +typeobj; +\end_layout + +\begin_layout LyX-Code + +\emph on +char +\emph default + kind; +\end_layout + +\begin_layout LyX-Code + +\emph on +char +\emph default + type; +\end_layout + +\begin_layout LyX-Code + +\emph on +char +\emph default + byteorder; +\end_layout + +\begin_layout LyX-Code + +\emph on +char +\emph default + hasobject; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + type_num; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + elsize; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + alignment; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ArrayDescr +\emph default + *subarray; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject +\emph default + *fields; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ArrFuncs +\emph default + *f; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArray_Descr +\emph default +; +\end_layout + +\begin_layout Description +typeobj Pointer to a typeobject that is the corresponding Python type for + the elements of this array. + For the builtin types, this points to the corresponding array scalar. + For user-defined types, this should point to a user-defined typeobject. + This typeobject can either inherit from array scalars or not. + If it does not inherit from array scalars, then the +\family typewriter +NPY_USE_GETITEM +\family default + and +\family typewriter +NPY_USE_SETITEM +\family default + flags should be set in the +\family typewriter +hasobject +\family default + flag. +\end_layout + +\begin_layout Description +kind A character code indicating the kind of array (using the array interface + typestring notation). + A 'b' represents Boolean, a 'i' represents signed integer, a 'u' represents + unsigned integer, 'f' represents floating point, 'c' represents complex + floating point, 'S' represents 8-bit character string, 'U' represents 32-bit/ch +aracter unicode string, and 'V' repesents arbitrary. + +\end_layout + +\begin_layout Description +type A traditional character code indicating the data type. + +\end_layout + +\begin_layout Description +byteorder A character indicating the byte-order: '>' (big-endian), '<' (little-e +ndian), '=' (native), '|' (irrelevant, ignore). + All builtin data-types have byteorder '='. + +\end_layout + +\begin_layout Description +hasobject A data-type bit-flag that determines if the data-type exhibits + object-array like behavior. + Each bit in this member is a flag which are named as: +\end_layout + +\begin_deeper +\begin_layout Description +NPY_ITEM_REFCOUNT\InsetSpace ~ +(NPY_ITEM_HASOBJECT) Indicates that items of this data-type + must be reference counted (using +\family typewriter +Py_INCREF +\family default + and +\family typewriter +Py_DECREF +\family default +). + +\end_layout + +\begin_layout Description +NPY_ITEM_LISTPICKLE Indicates arrays of this data-type must be converted + to a list before pickling. + +\end_layout + +\begin_layout Description +NPY_ITEM_IS_POINTER Indicates the item is a pointer to some other data-type +\end_layout + +\begin_layout Description +NPY_NEEDS_INIT Indicates memory for this data-type must be initialized (set + to 0) on creation. + +\end_layout + +\begin_layout Description +NPY_NEEDS_PYAPI Indicates this data-type requires the Python C-API during + access (so don't give up the GIL if array access is going to be needed). + +\end_layout + +\begin_layout Description +NPY_USE_GETITEM On array access use the +\family typewriter +f->getitem +\family default + function pointer instead of the standard conversion to an array scalar. + Must use if you don't define an array scalar to go along with the data-type. + +\end_layout + +\begin_layout Description +NPY_USE_SETITEM When creating a 0-d array from an array scalar use +\family typewriter +f->setitem +\family default + instead of the standard copy from an array scalar. + Must use if you don't define an array scalar to go along with the data-type. + +\end_layout + +\begin_layout Description +NPY_FROM_FIELDS The bits that are inherited for the parent data-type if + these bits are set in any field of the data-type. + Currently ( +\family typewriter +NPY_NEEDS_INIT +\family default + | +\family typewriter +NPY_LIST_PICKLE +\family default + | +\family typewriter +NPY_ITEM_REFCOUNT +\family default + | +\family typewriter +NPY_NEEDS_PYAPI +\family default +). + +\end_layout + +\begin_layout Description +NPY_OBJECT_DTYPE_FLAGS Bits set for the object data-type: ( +\family typewriter +NPY_LIST_PICKLE +\family default + | +\family typewriter +NPY_USE_GETITEM +\family default + | +\family typewriter +NPY_ITEM_IS_POINTER +\family default + | +\family typewriter +NPY_REFCOUNT +\family default + | +\family typewriter +NPY_NEEDS_INIT +\family default + | +\family typewriter +NPY_NEEDS_PYAPI +\family default +). + +\end_layout + +\begin_layout Description +PyDataType_FLAGCHK ( +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + flags) Return true if all the given flags are set for the data-type object. + +\end_layout + +\begin_layout Description +PyDataType_REFCHK ( +\family typewriter +PyArray_Descr* +\family default + dtype) Equivalent to +\family typewriter +PyDataType_FLAGCHK +\family default +( +\emph on +dtype +\emph default +, +\family typewriter +NPY_ITEM_REFCOUNT +\family default +). +\end_layout + +\end_deeper +\begin_layout Description +type_num A number that uniquely identifies the data type. + For new data-types, this number is assigned when the data-type is registered. +\end_layout + +\begin_layout Description +elsize For data types that are always the same size (such as long), this + holds the size of the data type. + For flexible data types where different arrays can have a different elementsize +, this should be 0. +\end_layout + +\begin_layout Description +alignment A number providing alignment information for this data type. + Specifically, it shows how far from the start of a 2-element structure + (whose first element is a +\family typewriter +char +\family default +), the compiler places an item of this type: +\family typewriter +offsetof(struct {char c; type v;}, v) +\end_layout + +\begin_layout Description +subarray If this is non- +\family typewriter +NULL +\family default +, then this data-type descriptor is a C-style contiguous array of another + data-type descriptor. + In other-words, each element that this descriptor describes is actually + an array of some other base descriptor. + This is most useful as the data-type descriptor for a field in another + data-type descriptor. + The fields member should be +\family typewriter +NULL +\family default + if this is non- +\family typewriter +NULL +\family default + (the fields member of the base descriptor can be non- +\family typewriter +NULL +\family default + however). + The +\family typewriter +PyArray_ArrayDescr +\family default + structure is defined using +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_Descr +\emph default + *base; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject +\emph default + *shape; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArray_ArrayDescr; +\end_layout + +\begin_layout Description +\InsetSpace ~ + The elements of this structure are: +\end_layout + +\begin_deeper +\begin_layout Description +base The data-type-descriptor object of the base-type. + +\end_layout + +\begin_layout Description +shape The shape (always C-style contiguous) of the sub-array as a Python + tuple. + +\end_layout + +\end_deeper +\begin_layout Description +fields If this is non-NULL, then this data-type-descriptor has fields described + by a Python dictionary whose keys are names (and also titles if given) + and whose values are tuples that describe the fields. + Recall that a data-type-descriptor always describes a fixed-length set + of bytes. + A field is a named sub-region of that total, fixed-length collection. + A field is described by a tuple composed of another data-type-descriptor + and a byte offset. + Optionally, the tuple may contain a title which is normally a Python string. + These tuples are placed in this dictionary keyed by name (and also title + if given). + +\end_layout + +\begin_layout Description +f A pointer to a structure containing functions that the type needs to implement + internal features. + These functions are not the same thing as the universal functions (ufuncs) + described later. + Their signatures can vary arbitrarily. + Not all of these function pointers must be defined for a given type. + The required members are +\family typewriter +nonzero +\family default +, +\family typewriter +copyswap +\family default +, +\family typewriter +copyswapn +\family default +, +\family typewriter +setitem +\family default +, +\family typewriter +getitem +\family default +, and +\family typewriter +cast +\family default +. + These are assumed to be non- +\family typewriter +NULL +\family default + and +\family typewriter +NULL +\family default + entries will cause a program crash. + The other functions may be +\family typewriter +NULL +\family default + which will just mean reduced functionality for that data-type. + (Also, the nonzero function will be filled in with a default function if + it is +\family typewriter +NULL +\family default + when you register a user-defined data-type). +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + +\emph on + PyArray_VectorUnaryFunc +\emph default + +\emph on +* +\emph default +cast[PyArray_NTYPES]; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_GetItemFunc * +\emph default +getitem; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_SetItemFunc * +\emph default +setitem; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_CopySwapNFunc * +\emph default +copyswapn; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_CopySwapFunc * +\emph default +copyswap; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_CompareFunc * +\emph default +compare; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ArgFunc * +\emph default +argmax; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_DotFunc * +\emph default +dotfunc; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ScanFunc * +\emph default +scanfunc; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_FromStrFunc +\emph default + *fromstr; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_NonzeroFunc * +\emph default +nonzero; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_FillFunc +\emph default + *fill; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_FillWithScalarFunc +\emph default + *fillwithscalar; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_SortFunc +\emph default + *sort[PyArray_NSORTS]; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ArgSortFunc +\emph default + *argsort[PyArray_NSORTS]; +\newline + +\emph on +PyObject +\emph default + *castdict; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArray_ScalarKindFunc +\emph default + *scalarkind; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + **cancastscalarkindto; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + *cancastto; +\end_layout + +\begin_layout LyX-Code + +\shape italic +int +\shape default + listpickle +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArray_ArrFuncs +\emph default +; +\end_layout + +\begin_layout Description +\InsetSpace ~ + The concept of a behaved segment is used in the description of the function + pointers. + A behaved segment is one that is aligned and in native machine byte-order + for the data-type. + The +\family typewriter +nonzero +\family default +, +\family typewriter +copyswap +\family default +, +\family typewriter +copyswapn +\family default +, +\family typewriter +getitem +\family default +, and +\family typewriter +setitem +\family default + functions can (and must) deal with mis-behaved arrays. + The other functions require behaved memory segments. +\end_layout + +\begin_deeper +\begin_layout Description +cast ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + from, +\family typewriter +void* +\family default + to, +\family typewriter +npy_intp +\family default + n, +\family typewriter +void* +\family default + fromarr, +\family typewriter +void* +\family default + toarr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + An array of function pointers to cast from the current type to all of the + other builtin types. + Each function casts a contiguous, aligned, and notswapped buffer pointed + at by +\emph on +from +\emph default + to a contiguous, aligned, and notswapped buffer pointed at by +\emph on +to +\emph default + The number of items to cast is given by +\emph on +n +\emph default +, and the arguments +\emph on +fromarr +\emph default + and +\emph on +toarr +\emph default + are interpreted as PyArrayObjects for flexible arrays to get itemsize informati +on. +\end_layout + +\begin_layout Description +getitem ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that returns a standard Python object from a single + element of the array object +\emph on +arr +\emph default + pointed to by +\emph on +data +\emph default +. + This function must be able to deal with +\begin_inset Quotes eld +\end_inset + +misbehaved +\begin_inset Quotes erd +\end_inset + + (misaligned and/or swapped) arrays correctly. + +\end_layout + +\begin_layout Description +setitem ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + item, +\family typewriter +void* +\family default + data, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that sets the Python object +\emph on +item +\emph default + into the array, +\emph on +arr +\emph default +, at the position pointed to by +\emph on +data +\emph default +. + This function deals with +\begin_inset Quotes eld +\end_inset + +misbehaved +\begin_inset Quotes erd +\end_inset + + arrays. + If successful, a zero is returned, otherwise, a negative one is returned + (and a Python error set). + +\end_layout + +\begin_layout Description +copyswapn ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + dest, +\family typewriter +npy_intp +\family default + dstride, +\family typewriter +void* +\family default + src, +\family typewriter +npy_intp +\family default + sstride, +\family typewriter +npy_intp +\family default + n, +\family typewriter +int +\family default + swap, void *arr) +\end_layout + +\begin_layout Description +copyswap ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + dest, +\family typewriter +void* +\family default + src, +\family typewriter +int +\family default + swap, void *arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + These members are both pointers to functions to copy data from +\emph on +src +\emph default + to +\emph on +dest +\emph default + and +\emph on +swap +\emph default + if indicated. + The value of arr is only used for flexible ( +\family typewriter +NPY_STRING +\family default +, +\family typewriter +NPY_UNICODE +\family default +, and +\family typewriter +NPY_VOID +\family default +) arrays (and is obtained from +\family typewriter +arr->descr->elsize +\family default +). + The second function copies a single value, while the first loops over n + values with the provided strides. + These functions can deal with misbehaved +\emph on +src +\emph default + data. + If +\emph on +src +\emph default + is NULL then no copy is performed. + If +\emph on +swap +\emph default + is 0, then no byteswapping occurs. + It is assumed that +\emph on +dest +\emph default + and +\emph on +src +\emph default + do not overlap. + If they overlap, then use +\family typewriter +memmove +\family default +(...) first followed by +\family typewriter +copyswap(n) +\family default + with NULL valued +\family typewriter +src +\family default +. +\end_layout + +\begin_layout Description +compare ( +\family typewriter +int +\family default +) ( +\family typewriter +const void* +\family default + d1, +\family typewriter +const void* +\family default + d2, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that compares two elements of the array, +\family typewriter +arr +\family default +, pointed to by +\family typewriter +d1 +\family default + and +\family typewriter +d2 +\family default +. + This function requires behaved arrays. + The return value is 1 if * +\family typewriter +d1 +\family default + > * +\family typewriter +d2 +\family default +, 0 if * +\family typewriter +d1 +\family default + == * +\family typewriter +d2 +\family default +, and -1 if * +\family typewriter +d1 +\family default + < * +\family typewriter +d2 +\family default +. + The array object arr is used to retrieve itemsize and field information + for flexible arrays. +\end_layout + +\begin_layout Description +argmax ( +\family typewriter +int +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +npy_intp +\family default + n, +\family typewriter +npy_intp* +\family default + max_ind, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that retrieves the index of the largest of +\family typewriter +n +\family default + elements in +\family typewriter +arr +\family default + beginning at the element pointed to by +\family typewriter +data +\family default +. + This function requires that the memory segment be contiguous and behaved. + The return value is always 0. + The index of the largest element is returned in +\family typewriter +max_ind +\family default +. +\end_layout + +\begin_layout Description +dotfunc ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + ip1, +\family typewriter +npy_intp +\family default + is1, +\family typewriter +void* +\family default + ip2, +\family typewriter +npy_intp +\family default + is2, +\family typewriter +void* +\family default + op, +\family typewriter +npy_intp +\family default + n, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that multiplies two +\family typewriter +n +\family default +-length sequences together, adds them, and places the result in element + pointed to by +\family typewriter +op +\family default + of +\family typewriter +arr +\family default +. + The start of the two sequences are pointed to by +\family typewriter +ip1 +\family default + and +\family typewriter +ip2 +\family default +. + To get to the next element in each sequence requires a jump of +\family typewriter +is1 +\family default + and +\family typewriter +is2 +\family default + +\emph on +bytes +\emph default +, respectively. + This function requires behaved (though not necessarily contiguous) memory. + +\end_layout + +\begin_layout Description +scanfunc ( +\family typewriter +int +\family default +) ( +\family typewriter +FILE* +\family default + fd, +\family typewriter +void* +\family default + ip , +\family typewriter +void* +\family default + sep , +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that scans (scanf style) one element of the correspondi +ng type from the file descriptor +\family typewriter +fd +\family default + into the array memory pointed to by +\family typewriter +ip +\family default +. + The array is assumed to be behaved. + If +\family typewriter +sep +\family default + is not NULL, then a separator string is also scanned from the file before + returning. + The last argument +\family typewriter +arr +\family default + is the array to be scanned into. + A 0 is returned if the scan is successful. + A negative number indicates something went wrong: -1 means the end of file + was reached before the separator string could be scanned, -4 means that + the end of file was reached before the element could be scanned, and -3 + means that the element could not be interpreted from the format string. + Requires a behaved array. +\end_layout + +\begin_layout Description +fromstr ( +\family typewriter +int +\family default +) ( +\family typewriter +char* +\family default + str, +\family typewriter +void* +\family default + ip, +\family typewriter +char** +\family default + endptr, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that converts the string pointed to by +\family typewriter +str +\family default + to one element of the corresponding type and places it in the memory location + pointed to by +\family typewriter +ip +\family default +. + After the conversion is completed, +\family typewriter +*endptr +\family default + points to the rest of the string. + The last argument +\family typewriter +arr +\family default + is the array into which ip points (needed for variable-size data-types). + Returns 0 on success or -1 on failure. + Requires a behaved array. +\end_layout + +\begin_layout Description +nonzero ( +\family typewriter +Bool +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that returns TRUE if the item of +\family typewriter +arr +\family default + pointed to by +\family typewriter +data +\family default + is nonzero. + This function can deal with misbehaved arrays. + +\end_layout + +\begin_layout Description +fill ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +npy_intp +\family default + length, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that fills a contiguous array of given length with + data. + The first two elements of the array must already be filled-in. + From these two values, a delta will be computed and the values from item + 3 to the end will be computed by repeatedly adding this computed delta. + The data buffer must be well-behaved. +\end_layout + +\begin_layout Description +fillwithscalar ( +\family typewriter +void +\family default +)( +\family typewriter +void* +\family default + buffer, +\family typewriter +npy_intp +\family default + length, +\family typewriter +void* +\family default + value, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to a function that fills a contiguous +\family typewriter +buffer +\family default + of the given +\family typewriter +length +\family default + with a single scalar +\family typewriter +value +\family default + whose address is given. + The final argument is the array which is needed to get the itemsize for + variable-length arrays. + +\end_layout + +\begin_layout Description +sort ( +\family typewriter +int +\family default +) ( +\family typewriter +void* +\family default + start, +\family typewriter +npy_intp +\family default + length, +\family typewriter +void* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + An array of function pointers to a particular sorting algorithms. + A particular sorting algorithm is obtained using a key (so far +\family typewriter +PyArray_QUICKSORT +\family default +, +\family typewriter +PyArray_HEAPSORT +\family default +, and +\family typewriter +PyArray_MERGESORT +\family default + are defined). + These sorts are done in-place assuming contiguous and aligned data. + +\end_layout + +\begin_layout Description +argsort ( +\family typewriter +int +\family default +) ( +\family typewriter +void* +\family default + start, +\family typewriter +npy_intp* +\family default + result, +\family typewriter +npy_intp +\family default + length, void *arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + An array of function pointers to sorting algorithms for this data type. + The same sorting algorithms as for sort are available. + The indices producing the sort are returned in result (which must be initialize +d with indices 0 to length-1 inclusive). + +\end_layout + +\begin_layout Description +castdict +\end_layout + +\begin_layout Description +\InsetSpace ~ + Either +\family typewriter +NULL +\family default + or a dictionary containing low-level casting functions for user-defined + data-types. + Each function is wrapped in a +\family typewriter +PyCObject* +\family default + and keyed by the data-type number. + +\end_layout + +\begin_layout Description +scalarkind ( +\family typewriter +PyArray_SCALARKIND +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A function to determine how scalars of this type should be interpreted. + The argument is +\family typewriter +NULL +\family default + or a 0-dimensional array containing the data (if that is needed to determine + the kind of scalar). + The return value must be of type +\family typewriter +PyArray_SCALARKIND +\family default +. + +\end_layout + +\begin_layout Description +cancastscalarkindto +\end_layout + +\begin_layout Description +\InsetSpace ~ + Either +\family typewriter +NULL +\family default + or an array of +\family typewriter +PyArray_NSCALARKINDS +\family default + pointers. + These pointers should each be either +\family typewriter +NULL +\family default + or a pointer to an array of integers (terminated by +\family typewriter +PyArray_NOTYPE +\family default +) indicating data-types that a scalar of this data-type of the specified + kind can be cast to safely (this usually means without losing precision). +\end_layout + +\begin_layout Description +cancastto +\end_layout + +\begin_layout Description +\InsetSpace ~ + Either +\family typewriter +NULL +\family default + or an array of integers (terminated by +\family typewriter +PyArray_NOTYPE +\family default +) indicated data-types that this data-type can be cast to safely (this usually + means without losing precision). +\end_layout + +\begin_layout Description +listpickle +\end_layout + +\begin_layout Description +\InsetSpace ~ + Unused. +\end_layout + +\end_deeper +\begin_layout Standard +The +\family typewriter +PyArray_Type +\family default + typeobject implements many of the features of Python objects including + the tp_as_number, tp_as_sequence, tp_as_mapping, and tp_as_buffer interfaces. + The rich comparison (tp_richcompare) is also used along with new-style + attribute lookup for methods (tp_methods) and properties (tp_getset). + The +\family typewriter +PyArray_Type +\family default + can also be sub-typed. + +\end_layout + +\begin_layout Tip +The tp_as_number methods use a generic approach to call whatever function + has been registered for handling the operation. + The function PyNumeric_SetOps(..) can be used to register functions to handle + particular mathematical operations (for all arrays). + When the umath module is imported, it sets the numeric operations for all + arrays to the corresponding ufuncs. + +\newline +The tp_str and tp_repr methods can also be altered using PyString_SetStringFunc +tion(...). +\end_layout + +\begin_layout Subsection +PyUFunc_Type +\end_layout + +\begin_layout Standard +The ufunc object is implemented by creation of the +\family typewriter +PyUFunc_Type +\family default + +\begin_inset LatexCommand index +name "PyUFunc\\_Type" + +\end_inset + +. + It is a very simple type that implements only basic getattribute behavior, + printing behavior, and has call behavior which allows these objects to + act like functions. + The basic idea behind the ufunc is to hold a reference to fast 1-dimensional + (vector) loops for each data type that supports the operation. + These one-dimensional loops all have the same signature and are the key + to creating a new ufunc. + They are called by the generic looping code as appropriate to implement + the N-dimensional function. + There are also some generic 1-d loops defined for floating and complexfloating + arrays that allow you to define a ufunc using a single scalar function + ( +\emph on +e.g. + +\emph default + atanh). + +\end_layout + +\begin_layout Standard +The core of the ufunc is the +\family typewriter +PyUFuncObject +\family default + which contains all the information needed to call the underlying C-code + loops that perform the actual work. + It has the following structure. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nin; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nout; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nargs; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + identity; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyUFuncGenericFunction * +\emph default +functions; +\end_layout + +\begin_layout LyX-Code + +\emph on +void ** +\emph default +data; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + ntypes; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + check_return; +\end_layout + +\begin_layout LyX-Code + +\emph on +char * +\emph default +name; +\end_layout + +\begin_layout LyX-Code + +\emph on +char * +\emph default +types; +\end_layout + +\begin_layout LyX-Code + +\emph on +char * +\emph default +doc; +\end_layout + +\begin_layout LyX-Code + +\emph on +void * +\emph default +ptr; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject * +\emph default +obj; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject * +\emph default +userloops; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyUFuncObject +\emph default +; +\end_layout + +\begin_layout Description +PyObject_HEAD required for all Python objects. +\end_layout + +\begin_layout Description +nin The number of input arguments. +\end_layout + +\begin_layout Description +nout The number of output arguments. +\end_layout + +\begin_layout Description +nargs The total number of arguments ( +\emph on +nin +\emph default ++ +\emph on +nout +\emph default +). + This must be less than +\family typewriter +NPY_MAXARGS +\family default +. +\end_layout + +\begin_layout Description +identity Either +\family typewriter +PyUFunc_One +\family default +, +\family typewriter +PyUFunc_Zero +\family default +, or +\family typewriter +PyUFunc_None +\family default + to indicate the identity for this operation. + It is only used for a reduce-like call on an empty array. +\end_layout + +\begin_layout Description +functions ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + extradata ) +\end_layout + +\begin_layout Description +\InsetSpace ~ + An array of function pointers --- one for each data type supported by the + ufunc. + This is the vector loop that is called to implement the underlying function + +\emph on +dims +\emph default +[0] times. + The first argument, +\emph on +args +\emph default +, is an array of +\emph on +nargs +\emph default + pointers to behaved memory. + Pointers to the data for the input arguments are first, followed by the + pointers to the data for the output arguments. + How many bytes must be skipped to get to the next element in the sequence + is specified by the corresponding entry in the +\emph on +steps +\emph default + array. + The last argument allows the loop to receive extra information. + This is commonly used so that a single, generic vector loop can be used + for multiple functions. + In this case, the actual scalar function to call is passed in as +\emph on +extradata +\emph default +. + The size of this function pointer array is ntypes. + +\end_layout + +\begin_layout Description +data Extra data to be passed to the 1-d vector loops or +\family typewriter +NULL +\family default + if no extra-data is needed. + This C-array must be the same size ( +\emph on +i.e. + +\emph default + ntypes) as the functions array. + +\family typewriter +NULL +\family default + is used if extra_data is not needed. + Several C-API calls for UFuncs are just 1-d vector loops that make use + of this extra data to receive a pointer to the actual function to call. + +\end_layout + +\begin_layout Description +ntypes The number of supported data types for the ufunc. + This number specifies how many different 1-d loops (of the builtin data + types) are available. + +\end_layout + +\begin_layout Description +check_return Obsolete and unused. + However, it is set by the corresponding entry in the main ufunc creation + routine: +\family typewriter +PyUFunc_FromFuncAndData +\family default +(...). +\end_layout + +\begin_layout Description +name A string name for the ufunc. + This is used dynamically to build the __doc__ attribute of ufuncs. +\end_layout + +\begin_layout Description +types An array of +\emph on +nargs +\series bold +\emph default + +\begin_inset Formula $\times$ +\end_inset + + +\series default +\emph on +ntypes +\emph default + 8-bit type_numbers which contains the type signature for the function for + each of the supported (builtin) data types. + For each of the +\emph on +ntypes +\emph default + functions, the corresponding set of type numbers in this array shows how + the +\emph on +args +\emph default + argument should be interpreted in the 1-d vector loop. + These type numbers do not have to be the same type and mixed-type ufuncs + are supported. + +\end_layout + +\begin_layout Description +doc Documentation for the ufunc. + Should not contain the function signature as this is generated dynamically + when __doc__ is retrieved. +\end_layout + +\begin_layout Description +ptr Any dynamically allocated memory. + Currently, this is used for dynamic ufuncs created from a python function + to store room for the types, data, and name members. +\end_layout + +\begin_layout Description +obj For ufuncs dynamically created from python functions, this member holds + a reference to the underlying Python function. +\end_layout + +\begin_layout Description +userloops A dictionary of user-defined 1-d vector loops (stored as CObject + ptrs) for user-defined types. + A loop may be registered by the user for any user-defined type. + It is retrieved by type number. + User defined type numbers are always larger than +\family typewriter +NPY_USERDEF +\family default +. + +\end_layout + +\begin_layout Subsection +PyArrayIter_Type +\end_layout + +\begin_layout Standard +This +\begin_inset LatexCommand index +name "PyArrayIter\\_Type" + +\end_inset + + is an iterator object that makes it easy to loop over an N-dimensional + array. + It is the object returned from the flat attribute of an ndarray. + It is also used extensively throughout the implementation internals to + loop over an N-dimensional array. + The tp_as_mapping interface is implemented so that the iterator object + can be indexed (using 1-d indexing), and a few methods are implemented + through the tp_methods table. + This object implements the next method and can be used anywhere an iterator + can be used in Python. +\end_layout + +\begin_layout Standard +The C-structure corresponding to an object of +\family typewriter +PyArrayIter_Type +\family default + is the +\family typewriter +PyArrayIterObject +\family default +. + The +\family typewriter +PyArrayIterObject +\family default + is used to keep track of a pointer into an N-dimensional array. + It contains associated information used to quickly march through the array. + The pointer can be adjusted in three basic ways: 1) advance to the +\begin_inset Quotes eld +\end_inset + +next +\begin_inset Quotes erd +\end_inset + + position in the array in a C-style contiguous fashion, 2) advance to an + arbitrary N-dimensional coordinate in the array, and 3) advance to an arbitrary + one-dimensional index into the array. + The members of the +\family typewriter +PyArrayIterObject +\family default + structure are used in these calculations. + Iterator objects keep their own dimension and strides information about + an array. + This can be adjusted as needed for +\begin_inset Quotes eld +\end_inset + +broadcasting, +\begin_inset Quotes erd +\end_inset + + or to loop over only specific dimensions. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nd_m1; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + index; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + size; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + coordinates +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + dims_m1 +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + strides +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + backstrides +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + factors +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArrayObject * +\emph default +ao; +\end_layout + +\begin_layout LyX-Code + +\emph on +char * +\emph default +dataptr; +\end_layout + +\begin_layout LyX-Code + +\emph on +Bool +\emph default + contiguous; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArrayIterObject +\emph default +; +\end_layout + +\begin_layout Description +nd_m1 +\begin_inset Formula $N-1$ +\end_inset + + where +\begin_inset Formula $N$ +\end_inset + + is the number of dimensions in the underlying array. +\end_layout + +\begin_layout Description +index The current 1-d index into the array. +\end_layout + +\begin_layout Description +size The total size of the underlying array. +\end_layout + +\begin_layout Description +coordinates An +\begin_inset Formula $N$ +\end_inset + +-dimensional index into the array. +\end_layout + +\begin_layout Description +dims_m1 The size of the array minus 1 in each dimension. +\end_layout + +\begin_layout Description +strides The strides of the array. + How many bytes needed to jump to the next element in each dimension. + +\end_layout + +\begin_layout Description +backstrides How many bytes needed to jump from the end of a dimension back + to its beginning. + Note that +\emph on +backstrides +\emph default +[k]= +\emph on +strides +\emph default +[k]*d +\emph on +ims_m1 +\emph default +[k], but it is stored here as an optimization. +\end_layout + +\begin_layout Description +factors This array is used in computing an N-d index from a 1-d index. + It contains needed products of the dimensions. + +\end_layout + +\begin_layout Description +ao A pointer to the underlying ndarray this iterator was created to represent. +\end_layout + +\begin_layout Description +dataptr This member points to an element in the ndarray indicated by the + index. +\end_layout + +\begin_layout Description +contiguous This flag is true if the underlying array is +\family typewriter +NPY_C_CONTIGUOUS +\family default +. + It is used to simplify calculations when possible. + +\end_layout + +\begin_layout Standard +How to use an array iterator on a C-level is explained more fully in later + sections. + Typically, you do not need to concern yourself with the internal structure + of the iterator object, and merely interact with it through the use of + the macros +\family typewriter +PyArray_ITER_NEXT +\family default +(it), +\family typewriter +PyArray_ITER_GOTO +\family default +(it, dest), or +\family typewriter +PyArray_ITER_GOTO1D +\family default +(it, index). + All of these macros require the argument +\emph on +it +\emph default + to be a +\family typewriter +PyArrayIterObject* +\family default +. + +\end_layout + +\begin_layout Subsection +PyArrayMultiIter_Type +\end_layout + +\begin_layout Standard +This type provides an iterator that encapsulates the concept of broadcasting. + It allows +\begin_inset Formula $N$ +\end_inset + + arrays to be broadcast together so that the loop progresses in C-style + contiguous fashion over the broadcasted array. + The corresponding C-structure is the +\family typewriter +PyArrayMultiIterObject +\family default + whose memory layout must begin any object, +\emph on +obj +\emph default +, passed in to the +\family typewriter +PyArray_Broadcast +\family default +(obj) function. + Broadcasting is performed by adjusting array iterators so that each iterator + represents the broadcasted shape and size, but has its strides adjusted + so that the correct element from the array is used at each iteration. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + numiter; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + size; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + index; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nd; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + dimensions +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code + +\emph on +PyArrayIterObject * +\emph default +iters +\emph on +[NPY_MAXDIMS] +\emph default +; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArrayMultiIterObject +\emph default +; +\end_layout + +\begin_layout Description +PyObject_HEAD Needed at the start of every Python object (holds reference + count and type identification). +\end_layout + +\begin_layout Description +numiter The number of arrays that need to be broadcast to the same shape. +\end_layout + +\begin_layout Description +size The total broadcasted size. +\end_layout + +\begin_layout Description +index The current (1-d) index into the broadcasted result. +\end_layout + +\begin_layout Description +nd The number of dimensions in the broadcasted result. +\end_layout + +\begin_layout Description +dimensions The shape of the broadcasted result (only +\family typewriter +nd +\family default + slots are used). +\end_layout + +\begin_layout Description +iters An array of iterator objects that holds the iterators for the arrays + to be broadcast together. + On return, the iterators are adjusted for broadcasting. + +\end_layout + +\begin_layout Subsection +PyArrayFlags_Type +\end_layout + +\begin_layout Standard +When the flags attribute is retrieved from Python, a special builtin object + of this type is constructed. + This special type makes it easier to work with the different flags by accessing + them as attributes or by accessing them as if the object were a dictionary + with the flag names as entries. + +\end_layout + +\begin_layout Subsection +ScalarArrayTypes +\end_layout + +\begin_layout Standard +There is a Python type for each of the different built-in data types that + can be present in the array Most of these are simple wrappers around the + corresponding data type in C. + The C-names for these types are +\series bold +Py +\series default +<TYPE> +\series bold +ArrType_Type +\series default + where <TYPE> can be +\end_layout + +\begin_layout Quote + +\series bold +Bool +\series default +, +\series bold +Byte +\series default +, +\series bold +Short +\series default +, +\series bold +Int +\series default +, +\series bold +Long +\series default +, +\series bold +LongLong +\series default +, +\series bold +UByte +\series default +, +\series bold +UShort +\series default +, +\series bold +UInt +\series default +, +\series bold +ULong +\series default +, +\series bold +ULongLong +\series default +, +\series bold +Float +\series default +, +\series bold +Double +\series default +, +\series bold +LongDouble +\series default +, +\series bold +CFloat +\series default +, +\series bold +CDouble +\series default +, +\series bold +CLongDouble +\series default +, +\series bold +String +\series default +, +\series bold +Unicode +\series default +, +\series bold +Void +\series default +, and +\series bold +Object +\series default +. + +\end_layout + +\begin_layout Standard +These type names are part of the C-API and can therefore be created in extension + C-code. + There is also a +\family typewriter +PyIntpArrType_Type +\family default + and a +\family typewriter +PyUIntpArrType_Type +\family default + that are simple substitutes for one of the integer types that can hold + a pointer on the platform. + The structure of these scalar objects is not exposed to C-code. + The function +\family typewriter +PyArray_ScalarAsCtype +\family default +(..) can be used to extract the C-type value from the array scalar and the + function +\family typewriter +PyArray_Scalar +\family default +(...) can be used to construct an array scalar from a C-value. + +\end_layout + +\begin_layout Section +Other C-Structures +\end_layout + +\begin_layout Standard +A few new C-structures were found to be useful in the development of NumPy. + These C-structures are used in at least one C-API call and are therefore + documented here. + The main reason these structures were defined is to make it easy to use + the Python ParseTuple C-API to convert from Python objects to a useful + C-Object. + +\end_layout + +\begin_layout Subsection +PyArray_Dims +\end_layout + +\begin_layout Standard +This structure is very useful when shape and/or strides information is supposed + to be interpreted. + The structure is +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp * +\emph default +ptr; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + len; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArray_Dims +\emph default +; +\end_layout + +\begin_layout Standard +The members of this structure are +\end_layout + +\begin_layout Description +ptr A pointer to a list of ( +\family typewriter +npy_intp +\family default +) integers which usually represent array shape or array strides. + +\end_layout + +\begin_layout Description +len The length of the list of integers. + It is assumed safe to access +\emph on +ptr +\emph default +[0] to +\emph on +ptr +\emph default +[len-1]. + +\end_layout + +\begin_layout Subsection +PyArray_Chunk +\end_layout + +\begin_layout Standard +This is equivalent to the buffer object structure in Python up to the ptr + member. + On 32-bit platforms ( +\emph on +i.e. + +\emph default + if +\family typewriter +NPY_SIZEOF_INT +\family default +== +\family typewriter +NPY_SIZEOF_INTP +\family default +) or in Python 2.5, the len member also matches an equivalent member of the + buffer object. + It is useful to represent a generic single-segment chunk of memory. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD +\end_layout + +\begin_layout LyX-Code + +\emph on +PyObject * +\emph default +base; +\end_layout + +\begin_layout LyX-Code + +\emph on +void * +\emph default +ptr; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp +\emph default + len; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + flags; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArray_Chunk +\emph default +; +\end_layout + +\begin_layout Standard +The members are +\end_layout + +\begin_layout Description +PyObject_HEAD Necessary for all Python objects. + Included here so that the +\family typewriter +PyArray_Chunk +\family default + structure matches that of the buffer object (at least to the len member). + +\end_layout + +\begin_layout Description +base The Python object this chunk of memory comes from. + Needed so that memory can be accounted for properly. +\end_layout + +\begin_layout Description +ptr A pointer to the start of the single-segment chunk of memory. + +\end_layout + +\begin_layout Description +len The length of the segment in bytes. +\end_layout + +\begin_layout Description +flags Any data flags ( +\emph on +e.g. + +\emph default + +\family typewriter +NPY_WRITEABLE +\family default +) that should be used to interpret the memory. + +\end_layout + +\begin_layout Subsection +PyArrayInterface +\end_layout + +\begin_layout Standard +The +\family typewriter +PyArrayInterface +\family default + +\begin_inset LatexCommand index +name "PyArrayInterface" + +\end_inset + + structure is defined so that NumPy and other extension modules can use + the rapid array interface protocol. + The +\series bold +__array_struct__ +\series default + method of an object that supports the rapid array interface protocol should + return a +\family typewriter +PyCObject +\family default + that contains a pointer to a +\family typewriter +PyArrayInterface +\family default + structure with the relevant details of the array. + After the new array is created, the attribute should be +\family typewriter +DECREF +\family default +'d which will free the +\family typewriter +PyArrayInterface +\family default + structure. + Remember to +\family typewriter +INCREF +\family default + the object (whose +\series bold +__array_struct__ +\series default + attribute was retrieved) and point the base member of the new +\family typewriter +PyArrayObject +\family default + to this same object. + In this way the memory for the array will be managed correctly. + +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + two; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + nd; +\end_layout + +\begin_layout LyX-Code + +\emph on +char +\emph default + typekind; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + itemsize; +\end_layout + +\begin_layout LyX-Code + +\emph on +int +\emph default + flags; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp * +\emph default +shape; +\end_layout + +\begin_layout LyX-Code + +\emph on +npy_intp * +\emph default +strides; +\end_layout + +\begin_layout LyX-Code + +\emph on +void * +\emph default +data; +\end_layout + +\begin_layout LyX-Code + PyObject *descr; +\end_layout + +\begin_layout LyX-Code +} +\emph on +PyArrayInterface +\emph default +; +\end_layout + +\begin_layout Description +two the integer 2 as a sanity check. +\end_layout + +\begin_layout Description +nd the number of dimensions in the array. +\end_layout + +\begin_layout Description +typekind A character indicating what kind of array is present according + to the typestring convention with 't' -> bitfield, 'b' -> Boolean, 'i' + -> signed integer, 'u' -> unsigned integer, 'f' -> floating point, 'c' + -> complex floating point, 'O' -> object, 'S' -> string, 'U' -> unicode, + 'V' -> void. +\end_layout + +\begin_layout Description +itemsize the number of bytes each item in the array requires. +\end_layout + +\begin_layout Description +flags any of the bits +\family typewriter +NPY_C_CONTIGUOUS +\family default + (1), +\family typewriter +NPY_F_CONTIGUOUS +\family default + (2), +\family typewriter +NPY_ALIGNED +\family default + (0x100), +\family typewriter +NPY_NOTSWAPPED +\family default + (0x200), or +\family typewriter +NPY_WRITEABLE +\family default + (0x400) to indicate something about the data. + The +\family typewriter +NPY_ALIGNED +\family default +, +\family typewriter +NPY_C_CONTIGUOUS +\family default +, and +\family typewriter +NPY_F_CONTIGUOUS +\family default + flags can actually be determined from the other parameters. + The flag +\family typewriter +NPY_ARR_HAS_DESCR +\family default + (0x800) can also be set to indicate to objects consuming the version 3 + array interface that the descr member of the structure is present (it will + be ignored by objects consuming version 2 of the array interface). + +\end_layout + +\begin_layout Description +shape An array containing the size of the array in each dimension. +\end_layout + +\begin_layout Description +strides An array containing the number of bytes to jump to get to the next + element in each dimension. +\end_layout + +\begin_layout Description +data A pointer +\emph on +to +\emph default + the first element of the array. +\end_layout + +\begin_layout Description +descr A Python object describing the data-type in more detail (currently + an array_description list of tuples). + This can be +\family typewriter +NULL +\family default + if +\emph on +typekind +\emph default + and +\emph on +itemsize +\emph default + provide enough information. + +\end_layout + +\begin_layout Subsection +Internally used structures +\end_layout + +\begin_layout Standard +Internally, the code uses some additional Python objects primarily for memory + management. + These types are not accessible directly from Python, and are not exposed + to the C-API. + They are included here only for completeness and assistance in understanding + the code. + +\end_layout + +\begin_layout Subsubsection +PyUFuncLoopObject +\end_layout + +\begin_layout Standard +A loose wrapper for a C-structure that contains the information needed for + looping. + This is useful if you are trying to understand the ufunc looping code. + The +\family typewriter +PyUFuncLoopObject +\family default + is the associated C-structure. + It is defined in the +\family typewriter +ufuncobject.h +\family default + header. +\end_layout + +\begin_layout Subsubsection +PyUFuncReduceObject +\end_layout + +\begin_layout Standard +A loose wrapper for the C-structure that contains the information needed + for reduce-like methods of ufuncs. + This is useful if you are trying to understand the reduce, accumulate, + and reduce-at code. + The +\family typewriter +PyUFuncReduceObject +\family default + is the associated C-structure. + It is defined in the +\family typewriter +ufuncobject.h +\family default + header. +\end_layout + +\begin_layout Subsubsection +PyUFunc_Loop1d +\end_layout + +\begin_layout Standard +A simple linked-list of C-structures containing the information needed to + define a 1-d loop for a ufunc for every defined signature of a user-defined + data-type. + +\end_layout + +\begin_layout Subsubsection +PyArrayMapIter_Type +\end_layout + +\begin_layout Standard +Advanced indexing is handled with this Python type. + It is simply a loose wrapper around the C-structure containing the variables + needed for advanced array indexing. + The associated C-structure, +\family typewriter +PyArrayMapIterObject +\family default +, is useful if you are trying to understand the advanced-index mapping code. + It is defined in the +\family typewriter +arrayobject.h +\family default + header. + This type is not exposed to Python and could be replaced with a C-structure. + As a Python type it takes advantage of reference-counted memory management. +\end_layout + +\begin_layout Chapter +Complete API +\end_layout + +\begin_layout Quotation +The test of a first-rate intelligence is the ability to hold two opposed + ideas in the mind at the same time, and still retain the ability to function. +\end_layout + +\begin_layout Right Address +--- +\emph on +F. + Scott Fitzgerald +\end_layout + +\begin_layout Quotation +For a successful technology, reality must take precedence over public relations, + for Nature cannot be fooled. + +\end_layout + +\begin_layout Right Address +--- +\emph on +Richard P. + Feynman +\end_layout + +\begin_layout Section +Configuration defines +\end_layout + +\begin_layout Standard +When NumPy is built, a configuration file is constructed and placed as config.h + in the NumPy include directory. + This configuration file ensures that specific macros are defined and defines + other macros based on whether or not your system has certain features. + It is included by the arrayobject.h file. + +\end_layout + +\begin_layout Subsection +Guaranteed to be defined +\end_layout + +\begin_layout Standard +The +\series bold +SIZEOF_ +\series default +<CTYPE> constants are defined so that sizeof information is available to + the pre-processor. + +\end_layout + +\begin_layout Description +CHAR_BIT The number of bits of a char. + The char is the unit of all sizeof definitions +\end_layout + +\begin_layout Description +SIZEOF_SHORT sizeof(short) +\end_layout + +\begin_layout Description +SIZEOF_INT sizeof(int) +\end_layout + +\begin_layout Description +SIZEOF_LONG sizeof(long) +\end_layout + +\begin_layout Description +SIZEOF_LONG_LONG sizeof(longlong) where longlong is defined appropriately + on the platform (A macro defines +\series bold +SIZEOF_LONGLONG +\series default + as well.) +\end_layout + +\begin_layout Description +SIZEOF_PY_LONG_LONG +\end_layout + +\begin_layout Description +SIZEOF_FLOAT sizeof(float) +\end_layout + +\begin_layout Description +SIZEOF_DOUBLE sizeof(double) +\end_layout + +\begin_layout Description +SIZEOF_LONG_DOUBLE sizeof(longdouble) (A macro defines +\series bold +SIZEOF_LONGDOUBLE +\series default + as well.) +\end_layout + +\begin_layout Description +SIZEOF_PY_INTPTR_T Size of a pointer on this platform (sizeof(void *)) (A + macro defines SIZEOF_INTP as well.) +\end_layout + +\begin_layout Subsection +Possible defines +\end_layout + +\begin_layout Standard +These defines will cause the compilation to ignore compatibility code that + is placed in NumPy and use the system code instead. + If they are not defined, then the system does not have that capability. +\end_layout + +\begin_layout Description +HAVE_LONGDOUBLE_FUNCS System has C99 long double math functions. +\end_layout + +\begin_layout Description +HAVE_FLOAT_FUNCS System has C99 float math functions. +\end_layout + +\begin_layout Description +HAVE_INVERSE_HYPERBOLIC System has inverse hyperbolic functions: asinh, + acosh, and atanh. +\end_layout + +\begin_layout Description +HAVE_INVERSE_HYPERBOLIC_FLOAT System has C99 float extensions to inverse + hyperbolic functions: asinhf, acoshf, atanhf +\end_layout + +\begin_layout Description +HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE System has C99 long double extensions + to inverse hyperbolic functions: asinhl, acoshl, atanhl. +\end_layout + +\begin_layout Description +HAVE_ISNAN System has an isnan function. +\end_layout + +\begin_layout Description +HAVE_ISINF System has an isinf function. + +\end_layout + +\begin_layout Description +HAVE_LOG1P System has the log1p function: +\begin_inset Formula $\log\left(x+1\right)$ +\end_inset + +. +\end_layout + +\begin_layout Description +HAVE_EXPM1 System has the expm1 function: +\begin_inset Formula $\exp\left(x\right)-1$ +\end_inset + +. +\end_layout + +\begin_layout Description +HAVE_RINT System has the rint function. + +\end_layout + +\begin_layout Section +Array Data Types +\end_layout + +\begin_layout Standard +The standard array can have 21 different data types (and has some support + for adding your own types). + These data types all have an enumerated type, an enumerated type-character, + and a corresponding array scalar Python type object (placed in a hierarchy). + There are also standard C typedefs to make it easier to manipulate elements + of the given data type. + For the numeric types, there are also bit-width equivalent C typedefs and + named typenumbers that make it easier to select the precision desired. + +\end_layout + +\begin_layout Warning +The names for the types in c code follows c naming conventions more closely. + The Python names for these types follow Python conventions. + Thus, NPY_FLOAT picks up a 32-bit float in C, but +\begin_inset Quotes eld +\end_inset + +float_ +\begin_inset Quotes erd +\end_inset + + in python corresponds to a 64-bit double. + The bit-width names can be used in both Python and C for clarity. +\end_layout + +\begin_layout Subsection +Enumerated Types +\end_layout + +\begin_layout Standard +There is a list of enumerated types defined providing the basic 21 data + types plus some useful generic names. + Whenever the code requires a type number, one of these enumerated types + is requested. + The types are all called +\series bold +NPY_ +\series default +<NAME> where <NAME> can be +\end_layout + +\begin_layout Quote + +\series bold +BOOL +\series default +, +\series bold +BYTE +\series default +, +\series bold +UBYTE +\series default +, +\series bold +SHORT +\series default +, +\series bold +USHORT +\series default +, +\series bold +INT +\series default +, +\series bold +UINT +\series default +, +\series bold +LONG +\series default +, +\series bold +ULONG +\series default +, +\series bold +LONGLONG +\series default +, +\series bold +ULONGLONG +\series default +, +\series bold +FLOAT +\series default +, +\series bold +DOUBLE +\series default +, +\series bold +LONGDOUBLE +\series default +, +\series bold +CFLOAT +\series default +, +\series bold +CDOUBLE +\series default +, +\series bold +CLONGDOUBLE +\series default +, +\series bold +OBJECT +\series default +, +\series bold +STRING +\series default +, +\series bold +UNICODE +\series default +, +\series bold +VOID +\end_layout + +\begin_layout Quote + +\series bold +NTYPES +\series default +, +\series bold +NOTYPE +\series default +, +\series bold +USERDEF +\series default +, +\series bold +DEFAULT_TYPE +\end_layout + +\begin_layout Standard +The various character codes indicating certain types are also part of an + enumerated list. + References to type characters (should they be needed at all) should always + use these enumerations. + The form of them is +\series bold +NPY_ +\series default +<NAME> +\series bold +LTR +\series default + where <NAME> can be +\end_layout + +\begin_layout Quote + +\series bold +BOOL +\series default +, +\series bold +BYTE +\series default +, +\series bold +UBYTE +\series default +, +\series bold +SHORT +\series default +, +\series bold +USHORT +\series default +, +\series bold +INT +\series default +, +\series bold +UINT +\series default +, +\series bold +LONG +\series default +, +\series bold +ULONG +\series default +, +\series bold +LONGLONG +\series default +, +\series bold +ULONGLONG +\series default +, +\series bold +FLOAT +\series default +, +\series bold +DOUBLE +\series default +, +\series bold +LONGDOUBLE +\series default +, +\series bold +CFLOAT +\series default +, +\series bold +CDOUBLE +\series default +, +\series bold +CLONGDOUBLE +\series default +, +\series bold +OBJECT +\series default +, +\series bold +STRING +\series default +, +\series bold +VOID +\series default + +\end_layout + +\begin_layout Quote + +\series bold +INTP +\series default +, +\series bold +UINTP +\end_layout + +\begin_layout Quote + +\series bold +GENBOOL +\series default +, +\series bold +SIGNED +\series default +, +\series bold +UNSIGNED +\series default +, +\series bold +FLOATING +\series default +, +\series bold +COMPLEX +\end_layout + +\begin_layout Standard +The latter group of <NAME>s corresponds to letters used in the array interface + typestring specification. + +\end_layout + +\begin_layout Subsection +Defines +\end_layout + +\begin_layout Subsubsection +Max and min values for integers +\end_layout + +\begin_layout Description +NPY_MAX_INT +\series medium +<bits> +\end_layout + +\begin_layout Description +NPY_MAX_UINT +\series medium +<bits> +\end_layout + +\begin_layout Description +NPY_MIN_INT +\series medium +<bits> +\series default + +\end_layout + +\begin_layout Description +\InsetSpace ~ + These are defined for <bits> = 8, 16, 32, 64, 128, and 256 and provide + the maximum (minimum) value of the corresponding (unsigned) integer type. + Note: the actual integer type may not be available on all platforms (i.e. + 128-bit and 256-bit integers are rare). + +\end_layout + +\begin_layout Description +NPY_MIN_ +\series medium +<type> +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is defined for <type> = +\series bold +BYTE +\series default +, +\series bold +SHORT +\series default +, +\series bold +INT +\series default +, +\series bold +LONG +\series default +, +\series bold +LONGLONG +\series default +, +\series bold +INTP +\end_layout + +\begin_layout Description +NPY_MAX_ +\series medium +<type> +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is defined for all defined for <type> = +\series bold +BYTE +\series default +, +\series bold +UBYTE +\series default +, +\series bold +SHORT +\series default +, +\series bold +USHORT +\series default +, +\series bold +INT +\series default +, +\series bold +UINT +\series default +, +\series bold +LONG +\series default +, +\series bold +ULONG +\series default +, +\series bold +LONGLONG +\series default +, +\series bold +ULONGLONG +\series default +, +\series bold +INTP +\series default +, +\series bold +UINTP +\end_layout + +\begin_layout Subsubsection +Number of bits in data types +\end_layout + +\begin_layout Standard +All +\series bold +NPY_SIZEOF_ +\series default +<CTYPE> constants have corresponding +\series bold +NPY_BITSOF_ +\series default +<CTYPE> constants defined. + The +\series bold +NPY_BITSOF_ +\series default +<CTYPE> constants provide the number of bits in the data type. + Specifically, the available <CTYPE>s are +\end_layout + +\begin_layout Quote + +\series bold +BOOL +\series default +, +\series bold +CHAR +\series default +, +\series bold +SHORT +\series default +, +\series bold +INT +\series default +, +\series bold +LONG +\series default +, +\series bold +LONGLONG +\series default +, +\series bold +FLOAT +\series default +, +\series bold +DOUBLE +\series default +, +\series bold +LONGDOUBLE +\end_layout + +\begin_layout Subsubsection +Bit-width references to enumerated typenums +\end_layout + +\begin_layout Standard +All of the numeric data types (integer, floating point, and complex) have + constants that are defined to be a specific enumerated type number. + Exactly which enumerated type a bit-width type refers to is platform dependent. + In particular, the constants available are +\series bold +PyArray_ +\series default +<NAME><BITS> where <NAME> is +\series bold +INT +\series default +, +\series bold +UINT +\series default +, +\series bold +FLOAT +\series default +, +\series bold +COMPLEX +\series default + and <BITS> can be 8, 16, 32, 64, 80, 96, 128, 160, 192, 256, and 512. + Obviously not all bit-widths are available on all platforms for all the + kinds of numeric types. + Commonly 8-, 16-, 32-, 64-bit integers; 32-, 64-bit floats; and 64-, 128-bit + complex types are available. + +\end_layout + +\begin_layout Subsubsection +Integer that can hold a pointer +\end_layout + +\begin_layout Standard +The constants +\series bold +PyArray_INTP +\series default + and +\series bold +PyArray_UINTP +\series default + refer to an enumerated integer type that is large enough to hold a pointer + on the platform. + Index arrays should always be converted to +\series bold +PyArray_INTP +\series default +, because the dimension of the array is of type npy_intp. + +\end_layout + +\begin_layout Subsection +C-type names +\end_layout + +\begin_layout Standard +There are standard variable types for each of the numeric data types and + the bool data type. + Some of these are already available in the C-specification. + You can create variables in extension code with these types. + +\end_layout + +\begin_layout Subsubsection +Boolean +\end_layout + +\begin_layout Description +npy_bool unsigned char; The constants NPY_FALSE and NPY_TRUE are also defined. + +\end_layout + +\begin_layout Subsubsection +(Un)Signed Integer +\end_layout + +\begin_layout Standard +Unsigned versions of the integers can be defined by pre-pending a 'u' to + the front of the integer name. + +\end_layout + +\begin_layout Description +npy_(u)byte (unsigned) char +\end_layout + +\begin_layout Description +npy_(u)short (unsigned) short +\end_layout + +\begin_layout Description +npy_(u)int (unsigned) int +\end_layout + +\begin_layout Description +npy_(u)long (unsigned) long int +\end_layout + +\begin_layout Description +npy_(u)longlong (unsigned long long int) +\end_layout + +\begin_layout Description +npy_(u)intp (unsigned) Py_intptr_t (an integer that is the size of a pointer + on the platform). + +\end_layout + +\begin_layout Subsubsection +(Complex) Floating point +\end_layout + +\begin_layout Description +npy_(c)float float +\end_layout + +\begin_layout Description +npy_(c)double double +\end_layout + +\begin_layout Description +npy_(c)longdouble long double +\end_layout + +\begin_layout Standard +complex types are structures with +\series bold +.real +\series default + and +\series bold +.imag +\series default + members (in that order). +\end_layout + +\begin_layout Subsubsection +Bit-width names +\end_layout + +\begin_layout Standard +There are also typedefs for signed integers, unsigned integers, floating + point, and complex floating point types of specific bit-widths. + The available type names are +\end_layout + +\begin_layout Quote + +\series bold +npy_int +\series default +<bits>, +\series bold +npy_uint +\series default +<bits>, +\series bold +npy_float +\series default +<bits>, and +\series bold +npy_complex +\series default +<bits> +\end_layout + +\begin_layout Standard +where <bits> is the number of bits in the type and can be +\series bold +8 +\series default +, +\series bold +16 +\series default +, +\series bold +32 +\series default +, +\series bold +64 +\series default +, 128, and 256 for integer types; 16, +\series bold +32 +\series default +, +\series bold +64 +\series default +, 80, 96, 128, and 256 for floating-point types; and 32, +\series bold +64 +\series default +, +\series bold +128 +\series default +, 160, 192, and 512 for complex-valued types. + Which bit-widths are available is platform dependent. + The bolded bit-widths are usually available on all platforms. + +\end_layout + +\begin_layout Subsection +Printf Formatting +\end_layout + +\begin_layout Standard +For help in printing, the following strings are defined as the correct format + specifier in printf and related commands. +\end_layout + +\begin_layout Quote + +\series bold +NPY_LONGLONG_FMT +\series default +, +\series bold +NPY_ULONGLONG_FMT +\series default +, +\series bold +NPY_INTP_FMT +\series default +, +\series bold +NPY_UINTP_FMT +\series default +, +\series bold +NPY_LONGDOUBLE_FMT +\end_layout + +\begin_layout Section +Array API +\begin_inset LatexCommand index +name "ndarray!C-API|(" + +\end_inset + + +\begin_inset LatexCommand index +name "C-API!array|(" + +\end_inset + + +\end_layout + +\begin_layout Subsection +Array structure and data access +\end_layout + +\begin_layout Standard +These macros all access the PyArrayObject structure members. + The input argument, obj, can be any +\family typewriter +PyObject* +\family default + that is directly interpretable as a +\family typewriter +PyArrayObject* +\family default + (any instance of the +\series bold +PyArray_Type +\series default + and its sub-types). + +\end_layout + +\begin_layout Description +PyArray_DATA ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +PyArray_BYTES ( +\family typewriter +char* +\family default +) ( +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + These two macros are similar and obtain the pointer to the data-buffer + for the array. + The first macro can (and should be) assigned to a particular pointer where + the second is for generic processing. + If you have not guaranteed a contiguous and/or aligned array then be sure + you understand how to access the data in the array to avoid memory and/or + alignment problems. + +\end_layout + +\begin_layout Description +PyArray_DIMS ( +\family typewriter +npy_intp* +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +PyArray_STRIDES ( +\family typewriter +npy_intp* +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +PyArray_DIM ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +int +\family default + n) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the shape in the +\emph on +n +\emph default + +\begin_inset Formula $^{\textrm{th}}$ +\end_inset + + dimension. +\end_layout + +\begin_layout Description +PyArray_STRIDE ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +int +\family default + n) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the stride in the +\emph on +n +\emph default + +\begin_inset Formula $^{\textrm{th}}$ +\end_inset + + dimension. +\end_layout + +\begin_layout Description +PyArray_BASE ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +PyArray_DESCR ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +PyArray_FLAGS ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +PyArray_ITEMSIZE ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the itemsize for the elements of this array. +\end_layout + +\begin_layout Description +PyArray_TYPE ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the (builtin) typenumber for the elements of this array. + +\end_layout + +\begin_layout Description +PyArray_GETITEM ( +\family typewriter +PyObject +\family default + *) ( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +void* +\family default + itemptr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Get a Python object from the ndarray, +\emph on +arr +\emph default +, at the location pointed to by itemptr. + Return +\family typewriter +NULL +\family default + on failure. + +\end_layout + +\begin_layout Description +PyArray_SETITEM ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +void* +\family default + itemptr, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert obj and place it in the ndarray, +\emph on +arr +\emph default +, at the place pointed to by itemptr. + Return -1 if an error occurs or 0 on success. + +\end_layout + +\begin_layout Description +PyArray_SIZE ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns the total size (in number of elements) of the array. +\end_layout + +\begin_layout Description +PyArray_Size ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns 0 if +\emph on +obj +\emph default + is not a sub-class of bigndarray. + Otherwise, returns the total number of elements in the array. + Safer version of +\family typewriter +PyArray_SIZE +\family default +( +\emph on +obj +\emph default +). +\end_layout + +\begin_layout Description +PyArray_NBYTES ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns the total number of bytes consumed by the array. + +\end_layout + +\begin_layout Subsubsection +Data access +\end_layout + +\begin_layout Standard +These functions and macros provide easy access to elements of the ndarray + from C. + These work for all arrays. + You may need to take care when accessing the data in the array, however, + if it is not in machine byte-order, misaligned, or not writeable. + In other words, be sure to respect the state of the flags unless you know + what you are doing, or have previously guaranteed an array that is writeable, + aligned, and in machine byte-order using PyArray_FromAny. + If you wish to handle all types of arrays, the copyswap function for each + type is useful for handling misbehaved arrays. + Some platforms (e.g. + Solaris) do not like misaligned data and will crash if you de-reference + a misaligned pointer. + Other platforms (e.g. + x86 Linux) will just work more slowly with misaligned data. + +\end_layout + +\begin_layout Description +PyArray_GetPtr ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + aobj, +\family typewriter +npy_intp* +\family default + ind) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a pointer to the data of the ndarray, +\emph on +aobj +\emph default +, at the N-dimensional index given by the c-array, +\emph on +ind +\emph default +, (which must be at least +\emph on +aobj +\emph default +->nd in size). + You may want to typecast the returned pointer to the data type of the ndarray. +\end_layout + +\begin_layout Description +PyArray_GETPTR1 ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +<npy_intp> +\family default + i) +\end_layout + +\begin_layout Description +PyArray_GETPTR2 ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +<npy_intp> +\family default + i, +\family typewriter +<npy_intp> +\family default + j) +\end_layout + +\begin_layout Description +PyArray_GETPTR3 ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +<npy_intp> +\family default + i, +\family typewriter +<npy_intp> +\family default + j, +\family typewriter +<npy_intp> +\family default + k) +\end_layout + +\begin_layout Description +PyArray_GETPTR4 ( +\family typewriter +void* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +<npy_intp> +\family default + i, +\family typewriter +<npy_intp> +\family default + j, +\family typewriter +<npy_intp> +\family default + k, +\family typewriter +<npy_intp> +\family default + l) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Quick, inline access to the element at the given coordinates in the ndarray, + +\emph on +obj +\emph default +, which must have respectively 1, 2, 3, or 4 dimensions (this is not checked). + The corresponding +\emph on +i +\emph default +, +\emph on +j +\emph default +, +\emph on +k +\emph default +, and +\emph on +l +\emph default + coordinates can be any integer but will be interpreted as +\family typewriter +npy_intp +\family default +. + You may want to typecast the returned pointer to the data type of the ndarray. + +\end_layout + +\begin_layout Subsection +Creating arrays +\end_layout + +\begin_layout Subsubsection +From scratch +\end_layout + +\begin_layout Description +PyArray_NewFromDescr ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyTypeObject* +\family default + subtype, +\family typewriter +PyArray_Descr* +\family default + descr, +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +npy_intp* +\family default + strides, +\family typewriter +void* +\family default + data, +\family typewriter +int +\family default + flags, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is the main array creation function. + Most new arrays are created with this flexible function. + The returned object is an object of Python-type +\emph on +subtype +\emph default +, which must be a subtype of +\family typewriter +PyArray_Type +\family default +. + The array has +\emph on +nd +\emph default + dimensions, described by +\emph on +dims +\emph default +. + The data-type descriptor of the new array is +\emph on +descr +\emph default +. + If +\emph on +subtype +\emph default + is not +\family typewriter +&PyArray_Type +\family default + ( +\emph on +e.g. + +\emph default + a Python subclass of the ndarray), then +\emph on +obj +\emph default + is the object to pass to the +\series bold +__array_finalize__ +\series default + method of the subclass. + If +\emph on +data +\emph default + is +\family typewriter +NULL +\family default +, then new memory will be allocated and +\emph on +flags +\emph default + can be non-zero to indicate a Fortran-style contiguous array. + If +\emph on +data +\emph default + is not +\family typewriter +NULL +\family default +, then it is assumed to point to the memory to be used for the array and + the +\emph on +flags +\emph default + argument is used as the new flags for the array (except the state of +\family typewriter +NPY_OWNDATA +\family default + and +\family typewriter +UPDATEIFCOPY +\family default + flags of the new array will be reset). + In addition, if +\emph on +data +\emph default + is non-NULL, then +\emph on +strides +\emph default + can also be provided. + If +\emph on +strides +\emph default + is +\family typewriter +NULL +\family default +, then the array strides are computed as C-style contiguous (default) or + Fortran-style contiguous ( +\emph on +flags +\emph default + is nonzero for +\emph on +data +\emph default += +\family typewriter +NULL +\family default + or +\emph on +flags +\emph default + & +\family typewriter +NPY_F_CONTIGUOUS +\family default + is nonzero non-NULL +\emph on +data +\emph default +). + Any provided +\emph on +dims +\emph default + and +\emph on +strides +\emph default + are copied into newly allocated dimension and strides arrays for the new + array object. +\end_layout + +\begin_layout Description +PyArray_New ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyTypeObject* +\family default + subtype, +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + type_num, +\family typewriter +npy_intp* +\family default + strides, +\family typewriter +void* +\family default + data, +\family typewriter +int +\family default + itemsize, +\family typewriter +int +\family default + flags, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is similar to +\family typewriter +PyArray +\family default +\series bold +_ +\family typewriter +\series default +DescrNew +\family default +(...) except you specify the data-type descriptor with +\emph on +type_num +\emph default + and +\emph on +itemsize +\emph default +, where +\emph on +type_num +\emph default + corresponds to a builtin (or user-defined) type. + If the type always has the same number of bytes, then itemsize is ignored. + Otherwise, itemsize specifies the particular size of this array. + +\end_layout + +\begin_layout Warning +If data is passed to +\family typewriter +PyArray_NewFromDescr +\family default + or +\family typewriter +PyArray_New +\family default +, this memory must not be deallocated until the new array is deleted. + If this data came from another Python object, this can be accomplished + using +\family typewriter +Py_INCREF +\family default + on that object and setting the base member of the new array to point to + that object. + If strides are passed in they must be consistent with the dimensions, the + itemsize, and the data of the array. +\end_layout + +\begin_layout Description +PyArray_SimpleNew ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create a new unitialized array of type, +\emph on +typenum +\emph default +, whose size in each of +\emph on +nd +\emph default + dimensions is given by the integer array, +\emph on +dims +\emph default +. + This function cannot be used to create a flexible-type array (no itemsize + given). +\end_layout + +\begin_layout Description +PyArray_SimpleNewFromData ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + typenum, +\family typewriter +void* +\family default + data) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create an array wrapper around +\emph on +data +\emph default + pointed to by the given pointer. + The array flags will have a default that the data area is well-behaved + and C-style contiguous. + The shape of the array is given by the +\emph on +dims +\emph default + c-array of length +\emph on +nd +\emph default +. + The data-type of the array is indicated by +\emph on +typenum +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_SimpleNewFromDescr ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +PyArray_Descr* +\family default + descr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create a new array with the provided data-type descriptor, +\emph on +descr +\emph default +, of the shape deteremined by +\emph on +nd +\emph default + and +\emph on +dims +\emph default +. +\end_layout + +\begin_layout Description +PyArray_FILLWBYTE ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + val) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Fill the array pointed to by +\emph on +obj +\emph default +---which must be a (subclass of) bigndarray---with the contents of +\emph on +val +\emph default + (evaluated as a byte). +\end_layout + +\begin_layout Description +PyArray_Zeros ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a new +\emph on +nd +\emph default +-dimensional array with shape given by +\emph on +dims +\emph default + and data type given by +\emph on +dtype +\emph default +. + If +\emph on +fortran +\emph default + is non-zero, then a Fortran-order array is created, otherwise a C-order + array is created. + Fill the memory with zeros (or the 0 object if +\emph on +dtype +\emph default + corresponds to +\family typewriter +PyArray_OBJECT +\family default +). + +\end_layout + +\begin_layout Description +PyArray_ZEROS ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + type_num, +\family typewriter +int +\family default + fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Macro form of +\family typewriter +PyArray_Zeros +\family default + which takes a type-number instead of a data-type object. +\end_layout + +\begin_layout Description +PyArray_Empty ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a new +\emph on +nd +\emph default +-dimensional array with shape given by +\emph on +dims +\emph default + and data type given by +\emph on +dtype +\emph default +. + If +\emph on +fortran +\emph default + is non-zero, then a Fortran-order array is created, otherwise a C-order + array is created. + The array is uninitialized unless the data type corresponds to +\family typewriter +PyArray_OBJECT +\family default + in which case the array is filled with +\family typewriter +Py_None +\family default +. + +\end_layout + +\begin_layout Description +PyArray_EMPTY ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Macro form of +\family typewriter +PyArray_Empty +\family default + which takes a type-number, +\emph on +typenum +\emph default +, instead of a data-type object. +\end_layout + +\begin_layout Description +PyArray_Arange ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +double +\family default + start, +\family typewriter +double +\family default + stop, +\family typewriter +double +\family default + step, +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a new 1-dimensional array of data-type, +\emph on +typenum +\emph default +, that ranges from +\emph on +start +\emph default + to +\emph on +stop +\emph default + (exclusive) in increments of +\emph on +step +\emph default +. + Equivalent to +\series bold +arange +\series default +( +\emph on +start +\emph default +, +\emph on +stop +\emph default +, +\emph on +step +\emph default +, dtype). +\end_layout + +\begin_layout Description +PyArray_ArangeObj ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + start, +\family typewriter +PyObject* +\family default + stop, +\family typewriter +PyObject* +\family default + step, +\family typewriter +PyArray_Descr* +\family default + descr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a new 1-dimensional array of data-type determined by +\family typewriter +descr +\family default +, that ranges from +\family typewriter +start +\family default + to +\family typewriter +stop +\family default + (exclusive) in increments of +\family typewriter +step +\family default +. + Equivalent to arange( +\family typewriter +start +\family default +, +\family typewriter +stop +\family default +, +\family typewriter +step +\family default +, +\family typewriter +typenum +\family default +). + +\end_layout + +\begin_layout Subsubsection +From other objects +\end_layout + +\begin_layout Description +PyArray_FromAny ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + min_depth, +\family typewriter +int +\family default + max_depth, +\family typewriter +int +\family default + requirements, +\family typewriter +PyObject* +\family default + context) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is the main function used to obtain an array from any nested sequence, + or object that exposes the array interface, +\family typewriter +op +\family default +. + The parameters allow specification of the required +\emph on +type +\emph default +, the minimum ( +\emph on +min_depth +\emph default +) and maximum ( +\emph on +max_depth +\emph default +) number of dimensions acceptable, and other +\emph on +requirements +\emph default + for the array. + The +\emph on +dtype +\emph default + argument needs to be a +\family typewriter +PyArray_Descr +\family default + structure indicating the desired data-type (including required byteorder). + The +\emph on +dtype +\emph default + argument may be NULL, indicating that any data-type (and byteorder) is + acceptable. + If you want to use +\family typewriter +NULL +\family default + for the +\emph on +dtype +\emph default + and ensure the array is notswapped then use +\family typewriter +PyArray_CheckFromAny +\family default +. + A value of 0 for either of the depth parameters causes the parameter to + be ignored. + Any of the following array flags can be added ( +\emph on +e.g. + +\emph default + using |) to get the +\emph on +requirements +\emph default + argument. + If your code can handle general ( +\emph on +e.g. + +\emph default + strided, byte-swapped, or unaligned arrays) then +\emph on +requirements +\emph default + may be 0. + Also, if +\emph on +op +\emph default + is not already an array (or does not expose the array interface), then + a new array will be created (and filled from +\emph on +op +\emph default + using the sequence protocol). + The new array will have +\family typewriter +NPY_DEFAULT +\family default + as its flags member. + The +\emph on +context +\emph default + argument is passed to the +\series bold +__array__ +\series default + method of +\emph on +op +\emph default + and is only used if the array is constructed that way. + +\end_layout + +\begin_deeper +\begin_layout Description +NPY_C_CONTIGUOUS Make sure the returned array is C-style contiguous +\end_layout + +\begin_layout Description +NPY_F_CONTIGUOUS Make sure the returned array is Fortran-style contiguous. + +\end_layout + +\begin_layout Description +NPY_ALIGNED Make sure the returned array is aligned on proper boundaries + for its data type. + An aligned array has the data pointer and every strides factor as a multiple + of the alignment factor for the data-type-descriptor. +\end_layout + +\begin_layout Description +NPY_WRITEABLE Make sure the returned array can be written to. + +\end_layout + +\begin_layout Description +NPY_ENSURECOPY Make sure a copy is made of +\emph on +op +\emph default +. + If this flag is not present, data is not copied if it can be avoided. + +\end_layout + +\begin_layout Description +NPY_ENSUREARRAY Make sure the result is a base-class ndarray or bigndarray. + By default, if +\emph on +op +\emph default + is an instance of a subclass of the bigndarray, an instance of that same + subclass is returned. + If this flag is set, an ndarray object will be returned instead. +\end_layout + +\begin_layout Description +NPY_FORCECAST Force a cast to the output type even if it cannot be done + safely. + Without this flag, a data cast will occur only if it can be done safely, + otherwise an error is reaised. + +\end_layout + +\begin_layout Description +NPY_UPDATEIFCOPY If +\emph on +op +\emph default + is already an array, but does not satisfy the requirements, then a copy + is made (which will satisfy the requirements). + If this flag is present and a copy (of an object that is already an array) + must be made, then the corresponding +\family typewriter +NPY_UPDATEIFCOPY +\family default + flag is set in the returned copy and +\emph on +op +\emph default + is made to be read-only. + When the returned copy is deleted (presumably after your calculations are + complete), its contents will be copied back into +\emph on +op +\emph default + and the +\emph on +op +\emph default + array will be made writeable again. + If +\emph on +op +\emph default + is not writeable to begin with, then an error is raised. + If +\emph on +op +\emph default + is not already an array, then this flag has no effect. +\end_layout + +\begin_layout Description +NPY_BEHAVED +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +NPY_WRITEABLE +\end_layout + +\begin_layout Description +NPY_CARRAY +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_BEHAVED +\end_layout + +\begin_layout Description +NPY_CARRAY_RO +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_FARRAY +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_BEHAVED +\end_layout + +\begin_layout Description +NPY_FARRAY_RO +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_DEFAULT +\family typewriter +NPY_CARRAY +\end_layout + +\begin_layout Description +NPY_IN_ARRAY +\family typewriter +NPY_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_IN_FARRAY +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_INOUT_ARRAY +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_INOUT_FARRAY +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_OUT_ARRAY +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +NPY_UPDATEIFCOPY +\end_layout + +\begin_layout Description +NPY_OUT_FARRAY +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +UPDATEIFCOPY +\end_layout + +\end_deeper +\begin_layout Description +PyArray_CheckFromAny ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + min_depth, +\family typewriter +int +\family default + max_depth, +\family typewriter +int +\family default + requirements, +\family typewriter +PyObject* +\family default + context) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Nearly identical to +\family typewriter +PyArray_FromAny +\family default +(...) except +\emph on +requirements +\emph default + can contain +\family typewriter +NPY_NOTSWAPPED +\family default + (over-riding the specification in +\emph on +dtype +\emph default +) and +\family typewriter +NPY_ELEMENTSTRIDES +\family default + which indicates that the array should be aligned in the sense that the + strides are multiples of the element size. + +\end_layout + +\begin_layout Description +NPY_NOTSWAPPED Make sure the returned array has a data-type descriptor that + is in machine byte-order, over-riding any specification in the +\emph on +dtype +\emph default + argument. + Normally, the byte-order requirement is determined by the +\emph on +dtype +\emph default + argument. + If this flag is set and the dtype argument does not indicate a machine + byte-order descriptor (or is NULL and the object is already an array with + a data-type descriptor that is not in machine byte-order), then a new data-type + descriptor is created and used with its byte-order field set to native. +\end_layout + +\begin_layout Description +NPY_BEHAVED_NS +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_NOTSWAPPED +\end_layout + +\begin_layout Description +NPY_ELEMENTSTRIDES Make sure the returned array has strides that are multiples + of the element size. + +\end_layout + +\begin_layout Description +PyArray_FromArray ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + newtype, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Special case of +\family typewriter +PyArray_FromAny +\family default + for when +\emph on +op +\emph default + is already an array but it needs to be of a specific +\emph on +newtype +\emph default + (including byte-order) or has certain +\emph on +requirements +\emph default +. +\end_layout + +\begin_layout Description +PyArray_FromStructInterface ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns an ndarray object from a Python object that exposes the +\series bold +__array_struct__ +\series default + method and follows the array interface protocol. + If the object does not contain this method then a borrowed reference to + +\family typewriter +Py_NotImplemented +\family default + is returned. +\end_layout + +\begin_layout Description +PyArray_FromInterface ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns an ndarray object from a Python object that exposes the +\series bold +__array_shape__ +\series default + and +\series bold +__array_typestr__ +\series default + methods following the array interface protocol. + If the object does not contain one of these method then a borrowed reference + to +\family typewriter +Py_NotImplemented +\family default + is returned. +\end_layout + +\begin_layout Description +PyArray_FromArrayAttr ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +PyObject* +\family default + context) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an ndarray object from a Python object that exposes the +\series bold +__array__ +\series default + method. + The +\series bold +__array__ +\series default + method can take 0, 1, or 2 arguments ([dtype, context]) where +\emph on +context +\emph default + is used to pass information about where the +\series bold +__array__ +\series default + method is being called from (currently only used in ufuncs). + +\end_layout + +\begin_layout Description +PyArray_ContiguousFromAny ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + min_depth, +\family typewriter +int +\family default + max_depth) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function returns a (C-style) contiguous and behaved function array + from any nested sequence or array interface exporting object, +\emph on +op +\emph default +, of (non-flexible) type given by the enumerated +\emph on +typenum +\emph default +, of minimum depth +\emph on +min_depth +\emph default +, and of maximum depth +\emph on +max_depth +\emph default +. + Equivalent to a call to +\family typewriter +PyArray_FromAny +\family default + with requirements set to +\family typewriter +NPY_DEFAULT +\family default + and the type_num member of the type argument set to +\emph on +typenum +\emph default +. +\end_layout + +\begin_layout Description +PyArray_FromObject (PyObject *) (PyObject * op, int typenum, int min_depth, + int max_depth) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an aligned and in native-byteorder array from any nested sequence + or array-interface exporting object, op, of a type given by the enumerated + typenum. + The minimum number of dimensions the array can have is given by min_depth + while the maximum is max_depth. + This is equivalent to a call to PyArray_FromAny with requirements set to + BEHAVED. + +\end_layout + +\begin_layout Description +PyArray_EnsureArray ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function +\series bold +steals a reference +\series default + to +\family typewriter +op +\family default + and makes sure that +\family typewriter +op +\family default + is a base-class ndarray. + It special cases array scalars, but otherwise calls +\series bold +PyArray_FromAny +\series default +( +\family typewriter +op +\family default +, NULL, 0, 0, NPY_ENSUREARRAY). +\end_layout + +\begin_layout Description +PyArray_FromString ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +char* +\family default + string, +\family typewriter +npy_intp +\family default + slen, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +npy_intp +\family default + num, +\family typewriter +char* +\family default + sep) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a one-dimensional ndarray of a single type from a binary or (ASCII) + text +\family typewriter +string +\family default + of length +\family typewriter +slen +\family default +. + The data-type of the array to-be-created is given by +\family typewriter +dtype +\family default +. + If num is -1, then +\series bold +copy +\series default + the entire string and return an appropriately sized array, otherwise, +\family typewriter +num +\family default + is the number of items to +\series bold +copy +\series default + from the string. + If +\family typewriter +sep +\family default + is NULL (or +\begin_inset Quotes eld +\end_inset + + +\begin_inset Quotes erd +\end_inset + +), then interpret the string as bytes of binary data, otherwise convert + the sub-strings separated by +\family typewriter +sep +\family default + to items of data-type +\family typewriter +dtype +\family default +. + Some data-types may not be readable in text mode and an error will be raised + if that occurs. + All errors return NULL. + +\end_layout + +\begin_layout Description +PyArray_FromFile ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +FILE* +\family default + fp, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +npy_intp +\family default + num, +\family typewriter +char* +\family default + sep) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a one-dimensional ndarray of a single type from a binary or text + file. + The open file pointer is +\family typewriter +fp +\family default +, the data-type of the array to be created is given by +\family typewriter +dtype +\family default +. + This must match the data in the file. + If +\family typewriter +num +\family default + is -1, then read until the end of the file and return an appropriately + sized array, otherwise, +\family typewriter +num +\family default + is the number of items to read. + If +\family typewriter +sep +\family default + is NULL (or +\begin_inset Quotes eld +\end_inset + + +\begin_inset Quotes erd +\end_inset + +), then read from the file in binary mode, otherwise read from the file + in text mode with +\family typewriter +sep +\family default + providing the item separator. + Some array types cannot be read in text mode in which case an error is + raised. +\end_layout + +\begin_layout Description +PyArray_FromBuffer ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + buf, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +npy_intp +\family default + count, +\family typewriter +npy_intp +\family default + offset) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Construct a one-dimensional ndarray of a single type from an object, +\family typewriter +buf +\family default +, that exports the (single-segment) buffer protocol (or has an attribute + __buffer__ that returns an object that exports the buffer protocol). + A writeable buffer will be tried first followed by a read-only buffer. + The NPY_WRITEABLE flag of the returned array will reflect which one was + successful. + The data is assumed to start at +\family typewriter +offset +\family default + bytes from the start of the memory location for the object. + The type of the data in the buffer will be interpreted depending on the + data-type descriptor, +\family typewriter +dtype. + +\family default + If +\family typewriter +count +\family default + is negative then it will be determined from the size of the buffer and + the requested itemsize, otherwise, +\family typewriter +count +\family default + represents how many elements should be converted from the buffer. + +\end_layout + +\begin_layout Description +PyArray_CopyInto ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + dest, +\family typewriter +PyArrayObject* +\family default + src) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Copy from the source array, +\family typewriter +src +\family default +, into the destination array, +\family typewriter +dest +\family default +, performing a data-type conversion if necessary. + If an error occurs return -1 (otherwise 0). + The shape of +\family typewriter +src +\family default + must be broadcastable to the shape of +\family typewriter +dest +\family default +. + The data areas of dest and src must not overlap. + +\end_layout + +\begin_layout Description +PyArray_MoveInto ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + dest, +\family typewriter +PyArrayObject* +\family default + src) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Move data from the source array, +\family typewriter +src +\family default +, into the destination array, +\family typewriter +dest +\family default +, performing a data-type conversion if necessary. + If an error occurs return -1 (otherwise 0). + The shape of +\family typewriter +src +\family default + must be broadcastable to the shape of +\family typewriter +dest +\family default +. + The data areas of dest and src may overlap. + +\end_layout + +\begin_layout Description +PyArray_GETCONTIGUOUS ( +\family typewriter +PyArrayObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + If +\family typewriter +op +\family default + is already (C-style) contiguous and well-behaved then just return a reference, + otherwise return a (contiguous and well-behaved) copy of the array. + The parameter op must be a (sub-class of an) ndarray and no checking for + that is done. +\end_layout + +\begin_layout Description +PyArray_FROM_O ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert +\family typewriter +obj +\family default + to an ndarray. + The argument can be any nested sequence or object that exports the array + interface. + This is a macro form of +\family typewriter +PyArray_FromAny +\family default + using +\family typewriter +NULL +\family default +, 0, 0, 0 for the other arguments. + Your code must be able to handle any data-type descriptor and any combination + of data-flags to use this macro. + +\end_layout + +\begin_layout Description +PyArray_FROM_OF ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Similar to +\family typewriter +PyArray_FROM_O +\family default + except it can take an argument of +\emph on +requirements +\emph default + indicating properties the resulting array must have. + Available requirements that can be enforced are +\family typewriter +NPY_CONTIGUOUS +\family default +, +\family typewriter +NPY_F_CONTIGUOUS +\family default +, +\family typewriter +NPY_ALIGNED +\family default +, +\family typewriter +NPY_WRITEABLE +\family default +, +\family typewriter +NPY_NOTSWAPPED +\family default +, +\family typewriter +NPY_ENSURECOPY +\family default +, +\family typewriter +NPY_UPDATEIFCOPY +\family default +, +\family typewriter +NPY_FORCECAST +\family default +, and +\family typewriter +NPY_ENSUREARRAY +\family default +. + Standard combinations of flags can also be used: +\end_layout + +\begin_layout Description +PyArray_FROM_OT ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Similar to +\family typewriter +PyArray_FROM_O +\family default + except it can take an argument of +\emph on +typenum +\emph default + specifying the type-number the returned array. +\end_layout + +\begin_layout Description +PyArray_FROM_OTF ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Combination of +\family typewriter +PyArray_FROM_OF +\family default + and +\family typewriter +PyArray_FROM_OT +\family default + allowing both a +\emph on +typenum +\emph default + and a +\emph on +flags +\emph default + argument to be provided.. +\end_layout + +\begin_layout Description +PyArray_FROMANY ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + min, +\family typewriter +int +\family default + max, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Similar to +\family typewriter +PyArray_FromAny +\family default + except the data-type is specified using a typenumber. + +\family typewriter +PyArray_DescrFromType +\family default +( +\emph on +typenum +\emph default +) is passed directly to +\family typewriter +PyArray_FromAny +\family default +. + This macro also adds +\family typewriter +NPY_DEFAULT +\family default + to requirements if +\family typewriter +NPY_ENSURECOPY +\family default + is passed in as requirements. + +\end_layout + +\begin_layout Description +PyArray_CheckAxis ( +\family typewriter +PyObject* +\family default +)( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int* +\family default + axis, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Encapsulate the functionality of functions and methods that take the axis= + keyword and work properly with None as the axis argument. + The input array is +\family typewriter +obj +\family default +, while +\family typewriter +*axis +\family default + is a converted integer (so that >=MAXDIMS is the None value), and +\family typewriter +requirements +\family default + gives the needed properties of +\family typewriter +obj +\family default +. + The output is a converted version of the input so that requirements are + met and if needed a flattening has occurred. + On output negative values of +\family typewriter +*axis +\family default + are converted and the new value is checked to ensure consistency with the + shape of +\family typewriter +obj +\family default +. +\end_layout + +\begin_layout Subsection +Dealing with types +\end_layout + +\begin_layout Subsubsection +General check of Python Type +\end_layout + +\begin_layout Description +PyArray_Check (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is a Python object whose type is a sub-type of +\family typewriter +PyArray_Type +\family default +. + +\end_layout + +\begin_layout Description +PyArray_CheckExact (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is a Python object with type +\family typewriter +PyArray_Type +\family default +. +\end_layout + +\begin_layout Description +PyArray_HasArrayInterface (op, out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + If +\family typewriter +op +\family default + implements any part of the array interface, then +\family typewriter +out +\family default + will contain a new reference to the newly created ndarray using the interface + or +\family typewriter +out +\family default + will contain +\family typewriter +NULL +\family default + if an error during conversion occurs. + Otherwise, out will contain a borrowed reference to +\family typewriter +Py_NotImplemented +\family default + and no error condition is set. + +\end_layout + +\begin_layout Description +PyArray_HasArrayInterfaceType (op, type, context, out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + If +\family typewriter +op +\family default + implements any part of the array interface, then +\family typewriter +out +\family default + will contain a new reference to the newly created ndarray using the interface + or +\family typewriter +out +\family default + will contain +\family typewriter +NULL +\family default + if an error during conversion occurs. + Otherwise, out will contain a borrowed reference to Py_NotImplemented and + no error condition is set. + This version allows setting of the type and context in the part of the + array interface that looks for the +\series bold +__array__ +\series default + attribute. + +\end_layout + +\begin_layout Description +PyArray_IsZeroDim (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is an instance of (a subclass of) +\family typewriter +PyArray_Type +\family default + and has 0 dimensions. +\end_layout + +\begin_layout Description +PyArray_IsScalar (op, cls) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is an instance of +\family typewriter +Py<cls>ArrType_Type +\family default +. +\end_layout + +\begin_layout Description +PyArray_CheckScalar (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is either an array scalar (an instance of a sub-type of +\family typewriter +PyGenericArr_Type +\family default +), or an instance of (a sub-class of) +\family typewriter +PyArray_Type +\family default + whose dimensionality is 0. +\end_layout + +\begin_layout Description +PyArray_IsPythonScalar (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is a builtin Python +\begin_inset Quotes eld +\end_inset + +scalar +\begin_inset Quotes erd +\end_inset + + object (int, float, complex, str, unicode, long, bool). +\end_layout + +\begin_layout Description +PyArray_IsAnyScalar (op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is either a Python scalar or an array scalar (an instance of a sub-type + of +\family typewriter +PyGenericArr_Type +\family default +). + +\end_layout + +\begin_layout Subsubsection +Data-type checking +\end_layout + +\begin_layout Standard +For the typenum macros, the argument is an integer representing an enumerated + array data type. + For the array type checking macros the argument must be a +\family typewriter +PyObject* +\family default + that can be directly interpreted as a +\family typewriter +PyArrayObject* +\family default +. + +\end_layout + +\begin_layout Description +PyTypeNum_ISUNSIGNED (num) +\end_layout + +\begin_layout Description +PyDataType_ISUNSIGNED (descr) +\end_layout + +\begin_layout Description +PyArray_ISUNSIGNED (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents an unsigned integer. +\end_layout + +\begin_layout Description +PyTypeNum_ISSIGNED (num) +\end_layout + +\begin_layout Description +PyDataType_ISSIGNED (descr) +\end_layout + +\begin_layout Description +PyArray_ISSIGNED (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents a signed integer. +\end_layout + +\begin_layout Description +PyTypeNum_ISINTEGER (num) +\end_layout + +\begin_layout Description +PyDataType_ISINTEGER (descr) +\end_layout + +\begin_layout Description +PyArray_ISINTEGER (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents any integer. +\end_layout + +\begin_layout Description +PyTypeNum_ISFLOAT (num) +\end_layout + +\begin_layout Description +PyDataType_ISFLOAT (descr) +\end_layout + +\begin_layout Description +PyArray_ISFLOAT (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents any floating point number. +\end_layout + +\begin_layout Description +PyTypeNum_ISCOMPLEX (num) +\end_layout + +\begin_layout Description +PyDataType_ISCOMPLEX (descr) +\end_layout + +\begin_layout Description +PyArray_ISCOMPLEX (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents any complex floating point number. +\end_layout + +\begin_layout Description +PyTypeNum_ISNUMBER (num) +\end_layout + +\begin_layout Description +PyDataType_ISNUMBER (descr) +\end_layout + +\begin_layout Description +PyArray_ISNUMBER (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents any integer, floating point, or complex floating point + number. +\end_layout + +\begin_layout Description +PyTypeNum_ISSTRING (num) +\end_layout + +\begin_layout Description +PyDataType_ISSTRING (descr) +\end_layout + +\begin_layout Description +PyArray_ISSTRING (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents a string data type. +\end_layout + +\begin_layout Description +PyTypeNum_ISPYTHON (num) +\end_layout + +\begin_layout Description +PyDataType_ISPYTHON (descr) +\end_layout + +\begin_layout Description +PyArray_ISPYTHON (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents an enumerated type corresponding to one of the standard + Python scalar (bool, int, float, or complex). + +\end_layout + +\begin_layout Description +PyTypeNum_ISFLEXIBLE (num) +\end_layout + +\begin_layout Description +PyDataType_ISFLEXIBLE (descr) +\end_layout + +\begin_layout Description +PyArray_ISFLEXIBLE (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents one of the flexible array types ( +\family typewriter +NPY_STRING +\family default +, +\family typewriter +NPY_UNICODE +\family default +, or +\family typewriter +NPY_VOID +\family default +). +\end_layout + +\begin_layout Description +PyTypeNum_ISUSERDEF (num) +\end_layout + +\begin_layout Description +PyDataType_ISUSERDEF (descr) +\end_layout + +\begin_layout Description +PyArray_ISUSERDEF (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents a user-defined type. +\end_layout + +\begin_layout Description +PyTypeNum_ISEXTENDED (num) +\end_layout + +\begin_layout Description +PyDataType_ISEXTENDED (descr) +\end_layout + +\begin_layout Description +PyArray_ISEXTENDED (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type is either flexible or user-defined. +\end_layout + +\begin_layout Description +PyTypeNum_ISOBJECT (num) +\end_layout + +\begin_layout Description +PyDataType_ISOBJECT (descr) +\end_layout + +\begin_layout Description +PyArray_ISOBJECT (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents object data type. +\end_layout + +\begin_layout Description +PyTypeNum_ISBOOL (num) +\end_layout + +\begin_layout Description +PyDataType_ISBOOL (descr) +\end_layout + +\begin_layout Description +PyArray_ISBOOL (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type represents Boolean data type. +\end_layout + +\begin_layout Description +PyDataType_HASFIELDS (descr) +\end_layout + +\begin_layout Description +PyArray_HASFIELDS (obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type has fields associated with it. +\end_layout + +\begin_layout Description +PyArray_ISNOTSWAPPED (m) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of the ndarray +\emph on +m +\emph default + is in machine byte-order according to the array's data-type descriptor. +\end_layout + +\begin_layout Description +PyArray_ISBYTESWAPPED (m) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of the ndarray +\emph on +m +\emph default + is +\series bold +not +\series default + in machine byte-order according to the array's data-type descriptor. + +\end_layout + +\begin_layout Description +PyArray_EquivTypes ( +\family typewriter +Bool +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + type1, +\family typewriter +PyArray_Descr* +\family default + type2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return +\family typewriter +NPY_TRUE +\family default + if +\emph on +type1 +\emph default + and +\emph on +type2 +\emph default + actually represent equivalent types for this platform (the fortran member + of each type is ignored). + For example, on 32-bit platforms, +\family typewriter +NPY_LONG +\family default + and +\family typewriter +NPY_INT +\family default + are equivalent. + Otherwise return +\family typewriter +NPY_FALSE +\family default +. +\end_layout + +\begin_layout Description +PyArray_EquivArrTypes ( +\family typewriter +Bool +\family default +) ( +\family typewriter +PyArrayObject* +\family default + a1, +\family typewriter +PyArrayObject +\family default +* a2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return +\family typewriter +NPY_TRUE +\family default + if +\emph on +a1 +\emph default + and +\emph on +a2 +\emph default + are arrays with equivalent types for this platform. + +\end_layout + +\begin_layout Description +PyArray_EquivTypenums ( +\family typewriter +Bool +\family default +) ( +\family typewriter +int +\family default + typenum1, +\family typewriter +int +\family default + typenum2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Special case of +\family typewriter +PyArray_EquivTypes +\family default +(...) that does not accept flexible data types but may be easier to call. + +\end_layout + +\begin_layout Description +PyArray_EquivByteorders (int) (<byteorder> b1, <byteorder> b2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + True if byteorder characters ( +\family typewriter +NPY_LITTLE +\family default +, +\family typewriter +NPY_BIG +\family default +, +\family typewriter +NPY_NATIVE +\family default +, +\family typewriter +NPY_IGNORE +\family default +) are either equal or equivalent as to their specification of a native byte + order. + Thus, on a little-endian machine +\family typewriter +NPY_LITTLE +\family default + and +\family typewriter +NPY_NATIVE +\family default + are equivalent where they are not equivalent on a big-endian machine. + +\end_layout + +\begin_layout Subsubsection +Converting data types +\end_layout + +\begin_layout Description +PyArray_Cast ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr, +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Mainly for backwards compatibility to the Numeric C-API and for simple + casts to non-flexible types. + Return a new array object with the elements of +\emph on +arr +\emph default + cast to the data-type +\emph on +typenum +\emph default + which must be one of the enumerated types and not a flexible type. +\end_layout + +\begin_layout Description +PyArray_CastToType ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr, +\family typewriter +PyArray_Descr* +\family default + type, +\family typewriter +int +\family default + fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a new array of the +\emph on +type +\emph default + specified, casting the elements of +\emph on +arr +\emph default + as appropriate. + The fortran argument specifies the ordering of the output array. + +\end_layout + +\begin_layout Description +PyArray_CastTo ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + out, +\family typewriter +PyArrayObject* +\family default + in) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Cast the elements of the array +\emph on +in +\emph default + into the array +\emph on +out +\emph default +. + The output array should be writeable, have an integer-multiple of the number + of elements in the input array (more than one copy can be placed in out), + and have a data type that is one of the builtin types. + Returns 0 on success and -1 if an error occurs. +\end_layout + +\begin_layout Description +PyArray_GetCastFunc ( +\family typewriter +PyArray_VectorUnaryFunc* +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + from, +\family typewriter +int +\family default + totype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the low-level casting function to cast from the given descriptor + to the builtin type number. + If no casting function exists return +\family typewriter +NULL +\family default + and set an error. + Using this function instead of direct access to +\emph on +from +\emph default +->f->cast will allow support of any user-defined casting functions added + to a descriptors casting dictionary. + +\end_layout + +\begin_layout Description +PyArray_CanCastSafely ( +\family typewriter +int +\family default +) ( +\family typewriter +int +\family default + fromtype, +\family typewriter +int +\family default + totype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns non-zero if an array of data type +\emph on +fromtype +\emph default + can be cast to an array of data type +\emph on +totype +\emph default + without losing information. + An exception is that 64-bit integers are allowed to be cast to 64-bit floating + point values even though this can lose precision on large integers so as + not to proliferate the use of long doubles without explict requests. + Flexible array types are not checked according to their lengths with this + function. + +\end_layout + +\begin_layout Description +PyArray_CanCastTo ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + fromtype, +\family typewriter +PyArray_Descr* +\family default + totype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns non-zero if an array of data type +\emph on +fromtype +\emph default + (which can include flexible types) can be cast safely to an array of data + type +\emph on +totype +\emph default + (which can include flexible types). + This is basically a wrapper around +\family typewriter +PyArray_CanCastSafely +\family default + with additional support for size checking if +\emph on +fromtype +\emph default + and +\emph on +totype +\emph default + are +\family typewriter +NPY_STRING +\family default + or +\family typewriter +NPY_UNICODE +\family default +. +\end_layout + +\begin_layout Description +PyArray_ObjectType ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +int +\family default + mintype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function is useful for determining a common type that two or more + arrays can be converted to. + It only works for non-flexible array types as no itemsize information is + passed. + The +\emph on +mintype +\emph default + argument represents the minimum type acceptable, and +\emph on +op +\emph default + represents the object that will be converted to an array. + The return value is the enumerated typenumber that represents the data-type + that +\emph on +op +\emph default + should have. +\end_layout + +\begin_layout Description +PyArray_ArrayType ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + mintype, +\family typewriter +PyArray_Descr* +\family default + outtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function works similarly to +\family typewriter +PyArray_ObjectType +\family default +(...) except it handles flexible arrays. + The +\emph on +mintype +\emph default + argument can have an itemsize member and the +\emph on +outtype +\emph default + argument will have an itemsize member at least as big but perhaps bigger + depending on the object +\emph on +op +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_ConvertToCommonType ( +\family typewriter +PyArrayObject** +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +int* +\family default + n) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert a sequence of Python objects contained in +\emph on +op +\emph default + to an array of ndarrays each having the same data type. + The type is selected based on the typenumber (larger type number is chosen + over a smaller one) ignoring objects that are only scalars. + The length of the sequence is returned in +\emph on +n +\emph default +, and an +\emph on +n +\emph default +-length array of +\family typewriter +PyArrayObject +\family default + pointers is the return value (or +\family typewriter +NULL +\family default + if an error occurs). + The returned array must be freed by the caller of this routine (using +\family typewriter +PyDataMem_FREE +\family default +) and all the array objects in it +\family typewriter +DECREF +\family default +'d or a memory-leak will occur. + The example template-code below shows a typically usage. +\end_layout + +\begin_layout LyX-Code +mps = PyArray_ConvertToCommonType(obj, &n); +\end_layout + +\begin_layout LyX-Code +if (mps==NULL) return NULL; +\end_layout + +\begin_layout LyX-Code +<code> +\end_layout + +\begin_layout LyX-Code +<before return> +\end_layout + +\begin_layout LyX-Code +for (i=0; i<n; i++) Py_DECREF(mps[i]); +\end_layout + +\begin_layout LyX-Code +PyDataMem_FREE(mps); +\end_layout + +\begin_layout LyX-Code +<return> +\end_layout + +\begin_layout Description +PyArray_Zero ( +\family typewriter +char* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to newly created memory of size +\emph on +arr +\emph default +->itemsize that holds the representation of 0 for that type. + The returned pointer, +\emph on +ret +\emph default +, +\series bold +must be freed +\series default + using +\family typewriter +\emph on +PyDataMem_FREE +\family default +\emph default +(ret) when it is not needed anymore. +\end_layout + +\begin_layout Description +PyArray_One ( +\family typewriter +char* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to newly created memory of size +\emph on +arr +\emph default +->itemsize that holds the representation of 1 for that type. + The returned pointer, +\emph on +ret +\emph default +, +\series bold +must be freed +\series default + using +\family typewriter +PyDataMem_FREE +\family default +(ret) when it is not needed anymore. +\end_layout + +\begin_layout Description +PyArray_ValidType ( +\family typewriter +int +\family default +) ( +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns +\family typewriter +NPY_TRUE +\family default + if +\family typewriter +\emph on +typenum +\family default +\emph default + represents a valid type-number (builtin or user-defined or character code). + Otherwise, this function returns +\family typewriter +NPY_FALSE +\family default +. +\end_layout + +\begin_layout Subsubsection +New data types +\end_layout + +\begin_layout Description +PyArray_InitArrFuncs ( +\family typewriter +void +\family default +) ( +\family typewriter +PyArray_ArrFuncs* +\family default + f) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Initialize all function pointers and members to +\family typewriter +NULL +\family default +. +\end_layout + +\begin_layout Description +PyArray_RegisterDataType ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Register a data-type as a new user-defined data type for arrays. + The type must have most of its entries filled in. + This is not always checked and errors can produce segfaults. + In particular, the typeobj member of the +\family typewriter +dtype +\family default + structure must be filled with a Python type that has a fixed-size element-size + that corresponds to the elsize member of +\emph on +dtype +\emph default +. + Also the +\family typewriter +f +\family default + member must have the required functions: nonzero, copyswap, copyswapn, + getitem, setitem, and cast (some of the cast functions may be +\family typewriter +NULL +\family default + if no support is desired). + To avoid confusion, you should choose a unique character typecode but this + is not enforced and not relied on internally. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + A user-defined type number is returned that uniquely identifies the type. + A pointer to the new structure can then be obtained from +\family typewriter +PyArray_DescrFromType +\family default + using the returned type number. + A -1 is returned if an error occurs. + If this +\family typewriter +\emph on +dtype +\family default +\emph default + has already been registered (checked only by the address of the pointer), + then return the previously-assigned type-number. + +\end_layout + +\begin_layout Description +PyArray_RegisterCastFunc ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + descr, +\family typewriter +int +\family default + totype, +\family typewriter +PyArray_VectorUnaryFunc* +\family default + castfunc) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Register a low-level casting function, +\emph on +castfunc +\emph default +, to convert from the data-type, +\emph on +descr +\emph default +, to the given data-type number, +\emph on +totype +\emph default +. + Any old casting function is over-written. + A +\family typewriter +0 +\family default + is returned on success or a +\family typewriter +-1 +\family default + on failure. + +\end_layout + +\begin_layout Description +PyArray_RegisterCanCast ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + descr, +\family typewriter +int +\family default + totype, +\family typewriter +PyArray_SCALARKIND +\family default + scalar) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Register the data-type number, +\emph on +totype +\emph default +, as castable from data-type object, +\emph on +descr +\emph default +, of the given +\emph on +scalar +\emph default + kind. + Use +\emph on +scalar +\emph default + = +\family typewriter +NPY_NOSCALAR +\family default + to register that an array of data-type +\emph on +descr +\emph default + can be cast safely to a data-type whose type_number is +\emph on +totype +\emph default +. + +\end_layout + +\begin_layout Subsubsection +Special functions for PyArray_OBJECT +\end_layout + +\begin_layout Description +PyArray_INCREF ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Used for an array, +\emph on +op +\emph default +, that contains any Python objects. + It increments the reference count of every object in the array according + to the data-type of +\emph on +op +\emph default +. + A -1 is returned if an error occurs, otherwise 0 is returned. +\end_layout + +\begin_layout Description +PyArray_Item_INCREF ( +\family typewriter +void +\family default +) ( +\family typewriter +char* +\family default + ptr, +\family typewriter +PyArray_Descr* +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A function to INCREF all the objects at the location +\emph on +ptr +\emph default + according to the data-type +\emph on +dtype +\emph default +. + If +\emph on +ptr +\emph default + is the start of a record with an object at any offset, then this will (recursiv +ely) increment the reference count of all object-like items in the record. +\end_layout + +\begin_layout Description +PyArray_XDECREF ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Used for an array, +\emph on +op +\emph default +, that contains any Python objects. + It decrements the reference count of every object in the array according + to the data-type of +\emph on +op +\emph default +. + Normal return value is 0. + A -1 is returned if an error occurs. +\end_layout + +\begin_layout Description +PyArray_Item_XDECREF ( +\family typewriter +void +\family default +) ( +\family typewriter +char* +\family default + ptr, +\family typewriter +PyArray_Descr* +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A function to XDECREF all the object-like items at the loacation +\emph on +ptr +\emph default + as recorded in the data-type, +\emph on +dtype +\emph default +. + This works recursively so that if +\family typewriter +dtype +\family default + itself has fields with data-types that contain object-like items, all the + object-like fields will be XDECREF +\family typewriter +'d +\family default +. + +\end_layout + +\begin_layout Description +PyArray_FillObjectArray ( +\family typewriter +void +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Fill a newly created array with a single value obj at all locations in + the structure with object data-types. + No checking is performed but +\emph on +arr +\emph default + must be of data-type +\family typewriter +PyArray_OBJECT +\family default + and be single-segment and uninitialized (no previous objects in position). + Use +\family typewriter +PyArray_DECREF +\family default +( +\emph on +arr +\emph default +) if you need to decrement all the items in the object array prior to calling + this function. + +\end_layout + +\begin_layout Subsection +Array flags +\end_layout + +\begin_layout Subsubsection +Basic Array Flags +\end_layout + +\begin_layout Standard +An ndarray can have a data segment that is not a simple contiguous chunk + of well-behaved memory you can manipulate. + It may not be aligned with word boundaries (very important on some platforms). + It might have its data in a different byte-order than the machine recognizes. + It might not be writeable. + It might be in Fortan-contiguous order. + The array flags are used to indicate what can be said about data associated + with an array. +\end_layout + +\begin_layout Description +NPY_C_CONTIGUOUS The data area is in C-style contiguous order (last index + varies the fastest). +\end_layout + +\begin_layout Description +NPY_F_CONTIGUOUS The data area is in Fortran-style contiguous order (first + index varies the fastest). +\end_layout + +\begin_layout Description +NPY_OWNDATA The data area is owned by this array. +\end_layout + +\begin_layout Description +NPY_ALIGNED The data area is aligned appropriately (for all strides). +\end_layout + +\begin_layout Description +NPY_WRITEABLE The data area can be written to. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + Notice that the above 3 flags are are defined so that a new, well-behaved + array has these flags defined as true. + +\end_layout + +\begin_layout Description +NPY_UPDATEIFCOPY The data area represents a (well-behaved) copy whose informatio +n should be transferred back to the original when this array is deleted. +\end_layout + +\begin_layout Subsubsection +Combinations of array flags +\end_layout + +\begin_layout Description +NPY_BEHAVED +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +NPY_WRITEABLE +\end_layout + +\begin_layout Description +NPY_CARRAY +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_BEHAVED +\end_layout + +\begin_layout Description +NPY_CARRAY_RO +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_FARRAY +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_BEHAVED +\end_layout + +\begin_layout Description +NPY_FARRAY_RO +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Description +NPY_DEFAULT +\family typewriter +NPY_CARRAY +\end_layout + +\begin_layout Description +NPY_UPDATE_ALL +\family typewriter +NPY_C_CONTIGUOUS +\family default + | +\family typewriter +NPY_F_CONTIGUOUS +\family default + | +\family typewriter +NPY_ALIGNED +\end_layout + +\begin_layout Subsubsection +Flag-like constants +\end_layout + +\begin_layout Standard +These constants are used in PyArray_FromAny (and its macro forms) to specify + desired properties of the new array. +\end_layout + +\begin_layout Description +NPY_FORCECAST Cast to the desired type, even if it can't be done without + losing information. +\end_layout + +\begin_layout Description +NPY_ENSURECOPY Make sure the resulting array is a copy of the original. +\end_layout + +\begin_layout Description +NPY_ENSUREARRAY Make sure the resulting object is an actual ndarray (or + bigndarray), and not a sub-class. +\end_layout + +\begin_layout Description +NPY_NOTSWAPPED Only used in +\family typewriter +PyArray_CheckFromAny +\family default + to over-ride the byteorder of the data-type object passed in. + +\end_layout + +\begin_layout Description +NPY_BEHAVED_NS +\family typewriter +NPY_ALIGNED +\family default + | +\family typewriter +NPY_WRITEABLE +\family default + | +\family typewriter +NPY_NOTSWAPPED +\end_layout + +\begin_layout Subsubsection +Flag checking +\end_layout + +\begin_layout Standard +For all of these macros +\emph on +arr +\emph default + must be an instance of a (subclass of) +\family typewriter +PyArray_Type +\family default +, but no checking is done. +\end_layout + +\begin_layout Description +PyArray_CHKFLAGS (arr, flags) +\end_layout + +\begin_layout Description +\InsetSpace ~ + The first parameter, arr, must be an ndarray or subclass. + The parameter, +\emph on +flags +\emph default +, should be an integer consisting of bitwise combinations of the possible + flags an array can have: +\family typewriter +NPY_C_CONTIGUOUS +\family default +, +\family typewriter +NPY_F_CONTIGUOUS +\family default +, +\family typewriter +NPY_OWNDATA +\family default +, +\family typewriter +NPY_ALIGNED +\family default +, +\family typewriter +NPY_WRITEABLE +\family default +, +\family typewriter +NPY_UPDATEIFCOPY +\family default +. +\end_layout + +\begin_layout Description +PyArray_ISCONTIGUOUS (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +arr +\emph default + is C-style contiguous. +\end_layout + +\begin_layout Description +PyArray_ISFORTRAN (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +arr +\emph default + is Fortran-style contiguous. +\end_layout + +\begin_layout Description +PyArray_ISWRITEABLE (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + can be written to +\end_layout + +\begin_layout Description +PyArray_ISALIGNED (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is properly aligned on the machine. +\end_layout + +\begin_layout Description +PyArray_ISBEHAVED (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evalutes true if the data area of +\emph on +arr +\emph default + is aligned and writeable and in machine byte-order according to its descriptor. +\end_layout + +\begin_layout Description +PyArray_ISBEHAVED_RO (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is aligned and in machine byte-order. +\end_layout + +\begin_layout Description +PyArray_ISCARRAY (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is C-style contiguous, and +\family typewriter +PyArray_ISBEHAVED +\family default +( +\emph on +arr +\emph default +) is true. +\end_layout + +\begin_layout Description +PyArray_ISFARRAY (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is Fortran-style contiguous and +\family typewriter +PyArray_ISBEHAVED +\family default +( +\emph on +arr +\emph default +) is true. +\end_layout + +\begin_layout Description +PyArray_ISCARRAY_RO (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is C-style contiguous, aligned, and in machine byte-order. + +\end_layout + +\begin_layout Description +PyArray_ISFARRAY_RO (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + is Fortran-style contiguous, aligned, and in machine byte-order +\series bold +. + +\end_layout + +\begin_layout Description +PyArray_ISONESEGMENT (arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if the data area of +\emph on +arr +\emph default + consists of a single (C-style or Fortran-style) contiguous segment. +\end_layout + +\begin_layout Description +PyArray_UpdateFlags ( +\family typewriter +void +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr, +\family typewriter +int +\family default + flagmask) +\end_layout + +\begin_layout Description +\InsetSpace ~ + The +\family typewriter +NPY_C_CONTIGUOUS +\family default +, +\family typewriter +NPY_ALIGNED +\family default +, and +\family typewriter +NPY_F_CONTIGUOUS +\family default + array flags can be +\begin_inset Quotes eld +\end_inset + +calculated +\begin_inset Quotes erd +\end_inset + + from the array object itself. + This routine updates one or more of these flags of +\emph on +arr +\emph default + as specified in +\emph on +flagmask +\emph default + by performing the required calculation. + +\end_layout + +\begin_layout Warning +It is important to keep the flags updated (using PyArray_UpdateFlags can + help) whenever a manipulation with an array is performed that might cause + them to change. + Later calculations in NumPy that rely on the state of these flags do not + repeat the calculation to update them. + +\end_layout + +\begin_layout Subsection +Array method alternative API +\end_layout + +\begin_layout Subsubsection +Conversion +\end_layout + +\begin_layout Description +PyArray_GetField ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + offset) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +getfield +\series default +( +\emph on +dtype +\emph default +, +\emph on +offset +\emph default +). + Return a new array of the given +\emph on +dtype +\emph default + using the data in the current array at a specified +\emph on +offset +\emph default + in bytes. + The +\emph on +offset +\emph default + plus the itemsize of the new array type must be less than +\emph on +self +\emph default +->descr->elsize or an error is raised. + The same shape and strides as the original array are used. + Therefore, this function has the effect of returning a field from a record + array. + But, it can also be used to select specific bytes or groups of bytes from + any array type. + +\end_layout + +\begin_layout Description +PyArray_SetField ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +int +\family default + offset, +\family typewriter +PyObject* +\family default + val) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +setfield +\series default +( +\emph on +val +\emph default +, +\emph on +dtype +\emph default +, +\emph on +offset +\emph default +). + Set the field starting at +\emph on +offset +\emph default + in bytes and of the given +\emph on +dtype +\emph default + to +\emph on +val +\emph default +. + The +\emph on +offset +\emph default + plus +\emph on +dtype +\emph default +->elsize must be less than +\emph on +self +\emph default +->descr->elsize or an error is raised. + Otherwise, the +\emph on +val +\emph default + argument is converted to an array and copied into the field pointed to. + If necessary, the elements of +\emph on +val +\emph default + are repeated to fill the destination array, But, the number of elements + in the destination must be an integer multiple of the number of elements + in +\emph on +val +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_Byteswap ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +Bool +\family default + inplace) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +byteswap +\series default +( +\emph on +inplace +\emph default +). + Return an array whose data area is byteswapped. + If +\emph on +inplace +\emph default + is non-zero, then do the byteswap inplace and return a reference to self. + Otherwise, create a byteswapped copy and leave self unchanged. +\end_layout + +\begin_layout Description +PyArray_NewCopy ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + old, +\family typewriter +NPY_ORDER +\family default + order) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +copy +\series default +( +\emph on +fortran +\emph default +). + Make a copy of the +\emph on +old +\emph default + array. + The returned array is always aligned and writeable with data interpreted + the same as the old array. + If +\emph on +order +\emph default + is +\family typewriter +NPY_CORDER +\family default +, then a C-style contiguous array is returned. + If +\emph on +order +\emph default + is +\family typewriter +NPY_FORTRANORDER +\family default +, then a Fortran-style contiguous array is returned. + If +\emph on +order is +\emph default + +\family typewriter +NPY_ANYORDER +\family default +, then the array returned is Fortran-style contiguous only if the old one + is; otherwise, it is C-style contiguous. + +\end_layout + +\begin_layout Description +PyArray_ToList ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +tolist +\series default +(). + Return a nested Python list from +\emph on +self +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_ToString (PyObject*) (PyArrayObject* self, NPY_ORDER order) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +tostring +\series default +( +\emph on +order +\emph default +). + Return the bytes of this array in a Python string. + +\end_layout + +\begin_layout Description +PyArray_ToFile ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +FILE* +\family default + fp, +\family typewriter +char* +\family default + sep, +\family typewriter +char* +\family default + format) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Write the contents of +\emph on +self +\emph default + to the file pointer +\emph on +fp +\emph default + in C-style contiguous fashion. + Write the data as binary bytes if +\family typewriter +\emph on +sep +\family default +\emph default + is the string +\begin_inset Quotes eld +\end_inset + + +\begin_inset Quotes erd +\end_inset + + or +\family typewriter +NULL +\family default +. + Otherwise, write the contents of +\emph on +self +\emph default + as text using the +\family typewriter +\emph on +sep +\family default +\emph default + string as the item separator. + Each item will be printed to the file. + If the +\emph on +format +\emph default + string is not +\family typewriter +NULL +\family default + or +\begin_inset Quotes eld +\end_inset + + +\begin_inset Quotes erd +\end_inset + +, then it is a Python print statement format string showing how the items + are to be written. +\end_layout + +\begin_layout Description +PyArray_Dump ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + self, +\family typewriter +PyObject* +\family default + file, +\family typewriter +int +\family default + protocol) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Pickle the object in +\emph on +self +\emph default + to the given +\emph on +file +\emph default + (either a string or a Python file object). + If +\emph on +file +\emph default + is a Python string it is considered to be the name of a file which is then + opened in binary mode. + The given +\emph on +protocol +\emph default + is used (if +\emph on +protocol +\emph default + is negative, or the highest available is used). + This is a simple wrapper around cPickle.dump( +\emph on +self +\emph default +, +\emph on +file +\emph default +, +\emph on +protocol +\emph default +). +\end_layout + +\begin_layout Description +PyArray_Dumps ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + self, +\family typewriter +int +\family default + protocol) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Pickle the object in +\emph on +self +\emph default + to a Python string and return it. + Use the Pickle +\emph on +protocol +\emph default + provided (or the highest available if +\emph on +protocol +\emph default + is negative). + +\end_layout + +\begin_layout Description +PyArray_FillWithScalar ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Fill the array, +\emph on +arr +\emph default +, with the given scalar object, +\emph on +obj +\emph default +. + The object is first converted to the data type of +\emph on +arr +\emph default +, and then copied into every location. + A -1 is returned if an error occurs, otherwise 0 is returned. +\end_layout + +\begin_layout Description +PyArray_View ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Descr* +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +view +\series default +( +\emph on +dtype +\emph default +). + Return a new view of the array +\emph on +self +\emph default + as possibly a different data-type, +\emph on +dtype +\emph default +. + If +\emph on +dtype +\emph default + is +\family typewriter +NULL +\family default +, then the returned array will have the same data type as +\emph on +self +\emph default +. + The new data-type must be consistent with the size of +\emph on +self +\emph default +. + Either the itemsizes must be identical, or +\emph on +self +\emph default + must be single-segment and the total number of bytes must be the same. + In the latter case the dimensions of the returned array will be altered + in the last (or first for Fortran-style contiguous arrays) dimension. + The data area of the returned array and self is exactly the same. +\end_layout + +\begin_layout Subsubsection +Shape Manipulation +\end_layout + +\begin_layout Description +PyArray_Newshape ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Dims* +\family default + newshape) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Result will be a new array (pointing to the same memory location as +\emph on +self +\emph default + if possible), but having a shape given by +\emph on +newshape +\emph default +. + If the new shape is not compatible with the strides of +\emph on +self +\emph default +, then a copy of the array with the new specified shape will be returned. + +\end_layout + +\begin_layout Description +PyArray_Reshape ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + shape) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\family typewriter +\emph on +self +\family default +\emph default +. +\series bold +reshape +\series default +( +\family typewriter +\emph on +shape +\family default +\emph default +) where +\emph on +shape +\emph default + is a sequence. + Converts +\emph on +shape +\emph default + to a +\family typewriter +PyArray_Dims +\family default + structure and calls +\family typewriter +PyArray_Newshape +\family default + internally. + +\end_layout + +\begin_layout Description +PyArray_Squeeze ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +squeeze +\series default +(). + Return a new view of +\emph on +self +\emph default + with all of the dimensions of length 1 removed from the shape. + +\end_layout + +\begin_layout Warning +matrix objects are always 2-dimensional. + Therefore, +\family typewriter +PyArray_Squeeze +\family default + has no effect on arrays of matrix sub-class. + +\end_layout + +\begin_layout Description +PyArray_SwapAxes ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + a1, +\family typewriter +int +\family default + a2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +swapaxes +\series default +( +\emph on +a1 +\emph default +, +\emph on +a2 +\emph default +). + The returned array is a new view of the data in +\emph on +self +\emph default + with the given axes, +\emph on +a1 +\emph default + and +\emph on +a2 +\emph default +, swapped. +\end_layout + +\begin_layout Description +PyArray_Resize ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Dims* +\family default + newshape, +\family typewriter +int +\family default + refcheck, NPY_ORDER fortran) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +resize +\series default +( +\emph on +newshape +\emph default +, refcheck +\family typewriter += +\family default +\emph on +refcheck +\emph default +, order= +\shape italic +fortran +\shape default +). + This function only works on single-segment arrays. + It changes the shape of +\emph on +self +\emph default + inplace and will reallocate the memory for +\emph on +self +\emph default + if +\emph on +newshape +\emph default + has a different total number of elements then the old shape. + If reallocation is necessary, then +\emph on +self +\emph default + must own its data, have +\emph on +self +\emph default +- +\family typewriter +>base==NULL +\family default +, have +\emph on +self +\emph default +- +\family typewriter +>weakrefs==NULL +\family default +, and (unless refcheck is 0) not be referenced by any other array. + A reference to the new array is returned. + The +\shape italic +fortran +\shape default + argument can be NPY_ANYORDER, NPY_CORDER, or NPY_FORTRANORDER. + This argument is used if the number of dimension is (or is being resized + to be) greater than 2. + It currently has no effect. + Eventually it could be used to determine how the resize operation should + view the data when constructing a differently-dimensioned array. + +\end_layout + +\begin_layout Description +PyArray_Transpose ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyArray_Dims* +\family default + permute) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +transpose +\series default +( +\emph on +permute +\emph default +). + Permute the axes of the ndarray object +\emph on +self +\emph default + according to the data structure +\emph on +permute +\emph default + and return the result. + If +\emph on +permute +\emph default + is +\family typewriter +NULL +\family default +, then the resulting array has its axes reversed. + For example if +\emph on +self +\emph default + has shape +\begin_inset Formula $10\times20\times30$ +\end_inset + +, and +\emph on +permute +\family typewriter +\emph default +.ptr +\family default + is (0,2,1) the shape of the result is +\begin_inset Formula $10\times30\times20.$ +\end_inset + + If +\emph on +permute +\emph default + is +\family typewriter +NULL +\family default +, the shape of the result is +\begin_inset Formula $30\times20\times10.$ +\end_inset + + +\end_layout + +\begin_layout Description +PyArray_Flatten ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +NPY_ORDER +\family default + order) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +flatten +\series default +( +\emph on +order +\emph default +). + Return a 1-d copy of the array. + If +\emph on +order +\emph default + is +\family typewriter +NPY_FORTRANORDER +\family default + the elements are scanned out in Fortran order (first-dimension varies the + fastest). + If +\emph on +order +\emph default + is +\family typewriter +NPY_CORDER +\family default +, the elements of +\family typewriter +self +\family default + are scanned in C-order (last dimension varies the fastest). + If +\emph on +order +\emph default + +\family typewriter +NPY_ANYORDER +\family default +, then the result of +\family typewriter +PyArray_ISFORTRAN +\family default +( +\emph on +self +\emph default +) is used to determine which order to flatten. +\end_layout + +\begin_layout Description +PyArray_Ravel ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +NPY_ORDER +\family default + order) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +.ravel( +\emph on +order +\emph default +). + Same basic functionality as +\family typewriter +PyArray_Flatten +\family default +( +\emph on +self +\emph default +, +\emph on +order +\emph default +) except if +\emph on +order +\emph default + is 0 and +\emph on +self +\emph default + is C-style contiguous, the shape is altered but no copy is performed. +\end_layout + +\begin_layout Subsubsection +Item selection and manipulation +\end_layout + +\begin_layout Description +PyArray_TakeFrom ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + indices, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + ret, +\family typewriter +NPY_CLIPMODE +\family default + clipmode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +take +\series default +( +\emph on +indices +\emph default +, +\emph on +axis +\emph default +, +\emph on +ret +\emph default +, +\emph on +clipmode +\emph default +) except +\emph on +axis +\emph default +=None in Python is obtained by setting +\emph on +axis +\emph default += +\family typewriter +NPY_MAXDIMS +\family default + in C. + Extract the items from self indicated by the integer-valued +\emph on +indices +\emph default + along the given +\emph on +axis. + +\emph default + The clipmode argument can be +\family typewriter +NPY_RAISE +\family default +, +\family typewriter +NPY_WRAP +\family default +, or +\family typewriter +NPY_CLIP +\family default + to indicate what to do with out-of-bound indices. + The +\emph on +ret +\emph default + argument can specify an output array rather than having one created internally. + +\end_layout + +\begin_layout Description +PyArray_PutTo ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + values, +\family typewriter +PyObject* +\family default + indices, +\family typewriter +NPY_CLIPMODE +\family default + clipmode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +.put( +\emph on +values +\emph default +, +\emph on +indices +\emph default +, +\emph on +clipmode +\emph default +). + Put +\emph on +values +\emph default + into +\emph on +self +\emph default + at the corresponding (flattened) +\emph on +indices +\emph default +. + If +\emph on +values +\emph default + is too small it will be repeated as necessary. + +\end_layout + +\begin_layout Description +PyArray_PutMask ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + values, +\family typewriter +PyObject* +\family default + mask) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Place the +\emph on +values +\emph default + in +\emph on +self +\emph default + wherever corresponding positions (using a flattened context) in +\emph on +mask +\emph default + are true. + The +\emph on +mask +\emph default + and +\emph on +self +\emph default + arrays must have the same total number of elements. + If +\emph on +values +\emph default + is too small, it will be repeated as necessary. +\end_layout + +\begin_layout Description +PyArray_Repeat ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + op, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +repeat +\series default +( +\emph on +op +\emph default +, +\emph on +axis +\emph default +). + Copy the elements of +\emph on +self +\emph default +, +\emph on +op +\emph default + times along the given +\emph on +axis +\emph default +. + Either +\emph on +op +\emph default + is a scalar integer or a sequence of length +\emph on +self +\emph default +->dimensions[ +\emph on +axis +\emph default +] indicating how many times to repeat each item along the axis. +\end_layout + +\begin_layout Description +PyArray_Choose ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArrayObject* +\family default + ret, +\family typewriter +NPY_CLIPMODE +\family default + clipmode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +choose +\series default +( +\emph on +op +\emph default +, +\emph on +ret +\emph default +, +\emph on +clipmode +\emph default +). + Create a new array by selecting elements from the sequence of arrays in + +\emph on +op +\emph default + based on the integer values in +\emph on +self +\emph default +. + The arrays must all be broadcastable to the same shape and the entries + in +\emph on +self +\emph default + should be between 0 and len( +\emph on +op +\emph default +). + The output is placed in +\emph on +ret +\emph default + unless it is +\family typewriter +NULL +\family default + in which case a new output is created. + The +\emph on +clipmode +\emph default + argument determines behavior for when entries in +\emph on +self +\emph default + are not between 0 and len( +\emph on +op +\emph default +). +\end_layout + +\begin_deeper +\begin_layout Description +NPY_RAISE raise a ValueError; +\end_layout + +\begin_layout Description +NPY_WRAP wrap values <0 by adding len( +\emph on +op +\emph default +) and values >=len( +\emph on +op +\emph default +) by subtracting len( +\emph on +op +\emph default +) until they are in range; +\end_layout + +\begin_layout Description +NPY_CLIP all values are clipped to the region [0, len( +\emph on +op +\emph default +) ). +\end_layout + +\end_deeper +\begin_layout Description +PyArray_Sort ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +sort +\series default +( +\emph on +axis +\emph default +). + Return an array with the items of +\emph on +self +\emph default + sorted along +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Description +PyArray_ArgSort ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +argsort +\series default +( +\emph on +axis +\emph default +). + Return an array of indices such that selection of these indices along the + given +\family typewriter +axis +\family default + would return a sorted version of +\emph on +self +\emph default +. + If +\emph on +self +\emph default +->descr is a data-type with fields defined, then self->descr->names is used + to determine the sort order. + A comparison where the first field is equal will use the second field and + so on. + To alter the sort order of a record array, create a new data-type with + a different order of names and construct a view of the array with that + new data-type. + +\end_layout + +\begin_layout Description +PyArray_LexSort ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + sort_keys, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Given a sequence of arrays ( +\emph on +sort_keys +\emph default +) of the same shape, return an array of indices (similar to +\family typewriter +PyArray_ArgSort +\family default +(...)) that would sort the arrays lexicographically. + A lexicographic sort specifies that when two keys are found to be equal, + the order is based on comparison of subsequent keys. + A merge sort (which leaves equal entries unmoved) is required to be defined + for the types. + The sort is accomplished by sorting the indices first using the first +\emph on +sort_key +\emph default + and then using the second +\emph on +sort_key +\emph default + and so forth. + This is equivalent to the lexsort( +\emph on +sort_keys +\emph default +, +\emph on +axis +\emph default +) Python command. + Because of the way the merge-sort works, be sure to understand the order + the +\emph on +sort_keys +\emph default + must be in (reversed from the order you would use when comparing two elements). +\end_layout + +\begin_layout Description +\InsetSpace ~ + If these arrays are all collected in a record array, then +\family typewriter +PyArray_Sort +\family default +(...) can also be used to sort the array directly. + +\end_layout + +\begin_layout Description +PyArray_SearchSorted ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + values) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +searchsorted +\series default +( +\emph on +values +\emph default +). + Assuming +\emph on +self +\emph default + is a 1-d array in ascending order representing bin boundaries then the + output is an array the same shape as +\emph on +values +\emph default + of bin numbers, giving the bin into which each item in +\emph on +values +\emph default + would be placed. + No checking is done on whether or not self is in ascending order. +\end_layout + +\begin_layout Description +PyArray_Diagonal ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + offset, +\family typewriter +int +\family default + axis1, +\family typewriter +int +\family default + axis2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +diagonal +\series default +( +\emph on +offset +\emph default +, +\emph on +axis1 +\emph default +, +\emph on +axis2 +\emph default +). + Return the +\emph on +offset +\emph default + diagonals of the 2-d arrays defined by +\emph on +axis1 +\emph default + and +\emph on +axis2 +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_Nonzero ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +nonzero +\series default +(). + Returns a tuple of index arrays that select elements of +\emph on +self +\emph default + that are nonzero. + If (nd= +\family typewriter +PyArray_NDIM +\family default +( +\family typewriter +self +\family default +))==1, then a single index array is returned. + The index arrays have data type +\family typewriter +NPY_INTP +\family default +. + If a tuple is returned (nd +\begin_inset Formula $\neq$ +\end_inset + +1), then its length is nd. + +\end_layout + +\begin_layout Description +PyArray_Compress ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + condition, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +compress +\series default +( +\emph on +condition +\emph default +, +\emph on +axis +\emph default +). + Return the elements along +\emph on +axis +\emph default + corresponding to elements of +\emph on +condition +\emph default + that are true. + +\end_layout + +\begin_layout Subsubsection +Calculation +\end_layout + +\begin_layout Tip +Pass in NPY_MAXDIMS for axis in order to achieve the same effect that is + obtained by passing in axis = None in Python (treating the array as a 1-d + array). + +\end_layout + +\begin_layout Description +PyArray_ArgMax ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +argmax +\series default +( +\emph on +axis +\emph default +). + Return the index of the largest element of +\emph on +self +\emph default + along +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Description +PyArray_ArgMin ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +argmin +\series default +( +\emph on +axis +\emph default +). + Return the index of the smallest element of +\emph on +self +\emph default + along +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Max ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +max +\series default +( +\emph on +axis +\emph default +). + Return the largest element of +\emph on +self +\emph default + along the given +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Min ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +min +\series default +( +\emph on +axis +\emph default +). + Return the smallest element of +\emph on +self +\emph default + along the given +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Ptp ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +ptp +\series default +( +\emph on +axis +\emph default +). + Return the difference between the largest element of +\emph on +self +\emph default + along +\emph on +axis +\emph default + and the smallest element of +\emph on +self +\emph default + along +\emph on +axis +\emph default +. +\end_layout + +\begin_layout Note +The rtype argument specifies the data-type the reduction should take place + over. + This is important if the data-type of the array is not +\begin_inset Quotes eld +\end_inset + +large +\begin_inset Quotes erd +\end_inset + + enough to handle the output. + By default, all integer data-types are made at least as large as NPY_LONG + for the +\begin_inset Quotes eld +\end_inset + +add +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +multiply +\begin_inset Quotes erd +\end_inset + + ufuncs (which form the basis for mean, sum, cumsum, prod, and cumprod functions +). +\end_layout + +\begin_layout Description +PyArray_Mean ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +mean +\series default +( +\emph on +axis +\emph default +, +\emph on +rtype +\emph default +). + Returns the mean of the elements along the given +\emph on +axis +\emph default +, using the enumerated type +\emph on +rtype +\emph default + as the data type to sum in. + Default sum behavior is obtained using +\family typewriter +PyArray_NOTYPE +\family default + for +\emph on +rtype +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Trace ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + offset, +\family typewriter +int +\family default + axis1, +\family typewriter +int +\family default + axis2, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +trace +\series default +( +\emph on +offset +\emph default +, +\emph on +axis1 +\emph default +, +\emph on +axis2 +\emph default +, +\emph on +rtype +\emph default +). + Return the sum (using +\emph on +rtype +\emph default + as the data type of summation) over the +\emph on +offset +\emph default + diagonal elements of the 2-d arrays defined by +\emph on +axis1 +\emph default + and +\emph on +axis2 +\emph default + variables. + A positive offset chooses diagonals above the main diagonal. + A negative offset selects diagonals below the main diagonal. + +\end_layout + +\begin_layout Description +PyArray_Clip ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +PyObject* +\family default + min, +\family typewriter +PyObject* +\family default + max) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +clip +\series default +( +\emph on +min +\emph default +, +\emph on +max +\emph default +). + Clip an array, +\emph on +self +\emph default +, so that values larger than +\emph on +max +\emph default + are fixed to +\emph on +max +\emph default + and values less than +\emph on +min +\emph default + are fixed to +\emph on +min +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Conjugate ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +conjugate +\series default +() and +\emph on +self +\emph default +. +\series bold +conj +\series default +() Return the complex conjugate of +\emph on +self +\emph default +. + If +\emph on +self +\emph default + is not of complex data type, then return +\emph on +self +\emph default + with an reference. +\end_layout + +\begin_layout Description +PyArray_Round ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + decimals, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +round +\series default +( +\emph on +decimals +\emph default +, +\emph on +out +\emph default +). + Returns the array with elements rounded to the nearest decimal place. + The decimal place is defined as the +\begin_inset Formula $10^{-\textrm{decimals}}$ +\end_inset + + digit so that negative +\emph on +decimals +\emph default + cause rounding to the nearest 10's, 100's, etc. + If out is +\family typewriter +NULL +\family default +, then the output array is created, otherwise the output is placed in +\family typewriter +\emph on +out +\family default +\emph default + which must be the correct size and type. + +\end_layout + +\begin_layout Description +PyArray_Std ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +std +\series default +( +\emph on +axis +\emph default +, +\emph on +rtype +\emph default +). + Return the standard deviation using data along +\emph on +axis +\emph default + converted to data type +\emph on +rtype +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_Sum ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +sum +\series default +( +\family typewriter +\emph on +axis +\family default +\emph default +, +\family typewriter +\emph on +rtype +\family default +\emph default +). + Return 1-d vector sums of elements in +\emph on +self +\emph default + along +\emph on +axis +\emph default +. + Perform the sum after converting data to data type +\emph on +rtype +\emph default +. +\end_layout + +\begin_layout Description +PyArray_CumSum ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +cumsum +\series default +( +\family typewriter +\emph on +axis +\family default +\emph default +, +\family typewriter +\emph on +rtype +\family default +\emph default +). + Return cumulative 1-d sums of elements in +\emph on +self +\emph default + along +\emph on +axis +\emph default +. + Perform the sum after converting data to data type +\emph on +rtype +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Prod ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +prod +\series default +( +\emph on +axis +\emph default +, +\emph on +rtype +\emph default +). + Return 1-d products of elements in +\emph on +self +\emph default + along +\emph on +axis +\emph default +. + Perform the product after converting data to data type +\emph on +rtype +\emph default +. +\end_layout + +\begin_layout Description +PyArray_CumProd ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +int +\family default + rtype, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +cumprod +\series default +( +\emph on +axis +\emph default +, +\emph on +rtype +\emph default +). + Return 1-d cumulative products of elements in +\family typewriter +self +\family default + along +\family typewriter +axis +\family default +. + Perform the product after converting data to data type +\family typewriter +rtype +\family default +. +\end_layout + +\begin_layout Description +PyArray_All ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +all +\series default +( +\emph on +axis +\emph default +). + Return an array with True elements for every 1-d sub-array of +\family typewriter +self +\family default + defined by +\family typewriter +axis +\family default + in which all the elements are True. + +\end_layout + +\begin_layout Description +PyArray_Any ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + self, +\family typewriter +int +\family default + axis, +\family typewriter +PyArrayObject* +\family default + out) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Equivalent to +\emph on +self +\emph default +. +\series bold +any +\series default +( +\emph on +axis +\emph default +). + Return an array with True elements for every 1-d sub-array of +\emph on +self +\emph default + defined by +\emph on +axis +\emph default + in which any of the elements are True. + +\end_layout + +\begin_layout Subsection +Functions +\end_layout + +\begin_layout Subsubsection +Array Functions +\end_layout + +\begin_layout Description +PyArray_AsCArray ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject** +\family default + op, +\family typewriter +void* +\family default + ptr, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + nd, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + itemsize) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Sometimes it is useful to access a multidimensional array as a C-style + multi-dimensional array so that algorithms can be implemented using C's + a[i][j][k] syntax. + This routine returns a pointer, +\emph on +ptr +\emph default +, that simulates this kind of C-style array, for 1-, 2-, and 3-d ndarrays. + +\end_layout + +\begin_deeper +\begin_layout Description +op The address to any Python object. + This Python object will be replaced with an equivalent well-behaved, C-style + contiguous, ndarray of the given data type specifice by the last two arguments. + Be sure that stealing a reference in this way to the input object is justified. + +\end_layout + +\begin_layout Description +ptr The address to a (ctype* for 1-d, ctype** for 2-d or ctype*** for 3-d) + variable where ctype is the equivalent C-type for the data type. + On return, +\emph on +ptr +\emph default + will be addressable as a 1-d, 2-d, or 3-d array. + +\end_layout + +\begin_layout Description +dims An output array that contains the shape of the array object. + This array gives boundaries on any looping that will take place. + +\end_layout + +\begin_layout Description +nd The dimensionality of the array (1, 2, or 3). + +\end_layout + +\begin_layout Description +typenum The expected data type of the array. + +\end_layout + +\begin_layout Description +itemsize This argument is only needed when +\emph on +typenum +\emph default + represents a flexible array. + Otherwise it should be 0. + +\end_layout + +\end_deeper +\begin_layout Note +The simulation of a C-style array is not complete for 2-d and 3-d arrays. + For example, the simulated arrays of pointers cannot be passed to subroutines + expecting specific, statically-defined 2-d and 3-d arrays. + To pass to functions requiring those kind of inputs, you must statically + define the required array and copy data. + +\end_layout + +\begin_layout Description +PyArray_Free ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +void* +\family default + ptr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Must be called with the same objects and memory locations returned from + +\family typewriter +PyArray_AsCArray +\family default +(...). + This function cleans up memory that otherwise would get leaked. +\end_layout + +\begin_layout Description +PyArray_Concatenate ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Join the sequence of objects in +\emph on +obj +\emph default + together along +\emph on +axis +\emph default + into a single array. + If the dimensions or types are not compatible an error is raised. +\end_layout + +\begin_layout Description +PyArray_InnerProduct ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj1, +\family typewriter +PyObject* +\family default + obj2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Compute a product-sum over the last dimensions of +\emph on +obj1 +\emph default + and +\emph on +obj2 +\emph default +. + Neither array is conjugated. + +\end_layout + +\begin_layout Description +PyArray_MatrixProduct ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj1, +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Compute a product-sum over the last dimension of +\emph on +obj1 +\emph default + and the second-to-last dimension of +\emph on +obj2 +\emph default +. + For 2-d arrays this is a matrix-product. + Neither array is conjugated. + +\end_layout + +\begin_layout Description +PyArray_CopyAndTranspose ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject +\family default +* op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A specialized copy and transpose function that works only for 2-d arrays. + The returned array is a transposed copy of +\emph on +op +\emph default +. +\end_layout + +\begin_layout Description +PyArray_Correlate ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + op1, +\family typewriter +PyObject* +\family default + op2, +\family typewriter +int +\family default + mode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Compute the 1-d correlation of the 1-d arrays +\emph on +op1 +\emph default + and +\emph on +op2 +\emph default +. + The correlation is computed at each output point by multiplying +\emph on +op1 +\emph default + by a shifted version of +\emph on +op2 +\emph default + and summing the result. + As a result of the shift, needed values outside of the defined range of + +\emph on +op1 +\emph default + and +\emph on +op2 +\emph default + are interpreted as zero. + The mode determines how many shifts to return: 0 - return only shifts that + did not need to assume zero-values; 1 - return an object that is the same + size as +\emph on +op1 +\emph default +, 2 - return all possible shifts (any overlap at all is accepted). + +\end_layout + +\begin_layout Description +PyArray_Where ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + condition, +\family typewriter +PyObject* +\family default + x, +\family typewriter +PyObject* +\family default + y) +\end_layout + +\begin_layout Description +\InsetSpace ~ + If both +\family typewriter +x +\family default + and +\family typewriter +y +\family default + are +\family typewriter +NULL +\family default +, then return +\family typewriter +PyArray_Nonzero +\family default +( +\family typewriter +\emph on +condition +\family default +\emph default +). + Otherwise, both +\emph on +x +\emph default + and +\emph on +y +\emph default + must be given and the object returned is shaped like +\emph on +condition +\emph default + and has elements of +\emph on +x +\emph default + and +\emph on +y +\emph default + where +\emph on +condition +\emph default + is respectively True or False. + +\end_layout + +\begin_layout Subsubsection +Other functions +\end_layout + +\begin_layout Description +PyArray_CheckStrides ( +\family typewriter +Bool +\family default +) ( +\family typewriter +int +\family default + elsize, +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp +\family default + numbytes, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +npy_intp* +\family default + newstrides) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Determine if +\emph on +newstrides +\emph default + is a strides array consistent with the memory of an +\emph on +nd +\emph default +-dimensional array with shape +\family typewriter +dims +\family default + and element-size, +\emph on +elsize +\emph default +. + The +\emph on +newstrides +\emph default + array is checked to see if jumping by the provided number of bytes in each + direction will ever mean jumping more than +\emph on +numbytes +\emph default + which is the assumed size of the available memory segment. + If +\emph on +numbytes +\emph default + is 0, then an equivalent +\emph on +numbytes +\emph default + is computed assuming +\emph on +nd +\emph default +, +\emph on +dims +\emph default +, and +\emph on +elsize +\emph default + refer to a single-segment array. + Return +\family typewriter +NPY_TRUE +\family default + if +\emph on +newstrides +\emph default + is acceptable, otherwise return +\family typewriter +NPY_FALSE +\family default +. +\end_layout + +\begin_layout Description +PyArray_MultiplyList ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +npy_intp* +\family default + seq, +\family typewriter +int +\family default + n) +\end_layout + +\begin_layout Description +PyArray_MultiplyIntList ( +\family typewriter +int +\family default +) ( +\family typewriter +int* +\family default + seq, +\family typewriter +int +\family default + n) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Both of these routines multiply an +\emph on +n +\emph default +-length array, +\emph on +seq +\emph default +, of integers and return the result. + No overflow checking is performed. +\end_layout + +\begin_layout Description +PyArray_CompareLists ( +\family typewriter +int +\family default +) ( +\family typewriter +npy_intp* +\family default + l1, +\family typewriter +npy_intp* +\family default + l2, +\family typewriter +int +\family default + n) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Given two +\emph on +n +\emph default +-length arrays of integers, +\emph on +l1 +\emph default +, and +\emph on +l2 +\emph default +, return 1 if the lists are identical; otherwise, return 0. + +\end_layout + +\begin_layout Subsection +Array Iterators +\end_layout + +\begin_layout Standard +An array iterator is a simple way to access the elements of an N-dimensional + array quickly and efficiently. + Section +\begin_inset LatexCommand ref +reference "sec:array_iterator" + +\end_inset + + provides more description and examples of this useful approach to looping + over an array. + +\end_layout + +\begin_layout Description +PyArray_IterNew ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an array iterator object from the array, +\emph on +arr +\emph default +. + This is equivalent to +\emph on +arr +\emph default +. +\series bold +flat +\series default +. + The array iterator object makes it easy to loop over an N-dimensional non-conti +guous array in C-style contiguous fashion. + +\end_layout + +\begin_layout Description +PyArray_IterAllButAxis ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +int +\family default + *axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an array iterator that will iterate over all axes but the one provided + in +\emph on +*axis +\emph default +. + The returned iterator cannot be used with +\family typewriter +PyArray_ITER_GOTO1D +\family default +. + This iterator could be used to write something similar to what ufuncs do + wherein the loop over the largest axis is done by a separate sub-routine. + If +\emph on +*axis +\emph default + is negative then +\emph on +*axis +\emph default + will be set to the axis having the smallest stride and that axis will be + used. + +\end_layout + +\begin_layout Description +PyArray_BroadcastToShape ( +\family typewriter +PyObject* +\family default +)( +\family typewriter +PyObject* +\family default + arr, +\family typewriter +npy_intp +\family default + *dimensions, +\family typewriter +int +\family default + nd) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an array iterator that is broadcast to iterate as an array of the + shape provided by +\emph on +dimensions +\emph default + and +\emph on +nd +\emph default +. + +\end_layout + +\begin_layout Description +PyArrayIter_Check ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates true if +\emph on +op +\emph default + is an array iterator (or instance of a subclass of the array iterator type). + +\end_layout + +\begin_layout Description +PyArray_ITER_RESET ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + iterator) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Reset an +\emph on +iterator +\emph default + to the beginning of the array. +\end_layout + +\begin_layout Description +PyArray_ITER_NEXT ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + iterator) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Incremement the index and the dataptr members of the +\emph on +iterator +\emph default + to point to the next element of the array. + If the array is not (C-style) contiguous, also increment the N-dimensional + coordinates array. +\end_layout + +\begin_layout Description +PyArray_ITER_DATA ( +\family typewriter +void* +\family default +)( +\family typewriter +PyObject* +\family default + iterator) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A pointer to the current element of the array. + +\end_layout + +\begin_layout Description +PyArray_ITER_GOTO ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + iterator, +\family typewriter +npy_intp* +\family default + destination) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Set the +\emph on +iterator +\emph default + index, dataptr, and coordinates members to the location in the array indicated + by the N-dimensional c-array, +\emph on +destination +\emph default +, which must have size at least +\emph on +iterator +\emph default +->nd_m1+1. +\end_layout + +\begin_layout Description +PyArray_ITER_GOTO1D ( +\family typewriter +PyObject* +\family default + iterator, +\family typewriter +npy_intp +\family default + index) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Set the +\emph on +iterator +\emph default + index and dataptr to the location in the array indicated by the integer + +\emph on +index +\emph default + which points to an element in the C-styled flattened array. + +\end_layout + +\begin_layout Description +PyArray_ITER_NOTDONE ( +\family typewriter +int +\family default +)( +\family typewriter +PyObject* +\family default + iterator) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates TRUE as long as the iterator has not looped through all of the + elements, otherwise it evaluates FALSE. + +\end_layout + +\begin_layout Subsection +Broadcasting (multi-iterators) +\end_layout + +\begin_layout Description +PyArray_MultiIterNew ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + num, ...) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A simplified interface to broadcasting. + This function takes the number of arrays to broadcast and then +\emph on +num +\emph default + extra ( +\family typewriter +PyObject* +\family default +) arguments. + These arguments are converted to arrays and iterators are created. + +\family typewriter +PyArray_Broadcast +\family default + is then called on the resulting multi-iterator object. + The resulting, broadcasted mult-iterator object is then returned. + A broadcasted operation can then be performed using a single loop and using + +\family typewriter +PyArray_MultiIter_NEXT +\family default +(..) +\end_layout + +\begin_layout Description +PyArray_MultiIter_RESET ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + multi) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Reset all the iterators to the beginning in a multi-iterator object, +\emph on +multi +\emph default +. +\end_layout + +\begin_layout Description +PyArray_MultiIter_NEXT ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + multi) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Advance each iterator in a multi-iterator object, +\emph on +multi +\emph default +, to its next (broadcasted) element. +\end_layout + +\begin_layout Description +PyArray_MultiIter_DATA ( +\family typewriter +void* +\family default +)( +\family typewriter +PyObject* +\family default + multi, +\family typewriter +int +\family default + i) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the data-pointer of the +\emph on +i +\emph default + +\begin_inset Formula $^{\textrm{th}}$ +\end_inset + + iterator in a multi-iterator object. + +\end_layout + +\begin_layout Description +PyArray_MultiIter_NEXTi ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + multi, +\family typewriter +int +\family default + i) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Advance the pointer of only the +\emph on +i +\emph default + +\begin_inset Formula $^{\textrm{th}}$ +\end_inset + + iterator. +\end_layout + +\begin_layout Description +PyArray_MultiIter_GOTO ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + multi, +\family typewriter +npy_intp* +\family default + destination) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Advance each iterator in a multi-iterator object, +\emph on +multi +\emph default +, to the given +\begin_inset Formula $N$ +\end_inset + +-dimensional +\emph on +destination +\emph default + where +\begin_inset Formula $N$ +\end_inset + + is the number of dimensions in the broadcasted array. + +\end_layout + +\begin_layout Description +PyArray_MultiIter_GOTO1D ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + multi, +\family typewriter +npy_intp +\family default + index) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Advance each iterator in a multi-iterator object, +\emph on +multi +\emph default +, to the corresponding location of the +\emph on +index +\emph default + into the flattened broadcasted array. + +\end_layout + +\begin_layout Description +PyArray_MultiIter_NOTDONE ( +\family typewriter +int +\family default +)( +\family typewriter +PyObject* +\family default + multi) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates TRUE as long as the multi-iterator has not looped through all + of the elements (of the broadcasted result), otherwise it evaluates FALSE. + +\end_layout + +\begin_layout Description +PyArray_Broadcast ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayMultiIterObject* +\family default + mit) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function encapsulates the broadcasting rules. + The +\emph on +mit +\emph default + container should already contain iterators for all the arrays that need + to be broadcast. + On return, these iterators will be adjusted so that iteration over each + simultaneously will accomplish the broadcasting. + A negative number is returned if an error occurs. + +\end_layout + +\begin_layout Description +PyArray_RemoveSmallest ( +\family typewriter +int +\family default +) ( +\family typewriter +PyArrayMultiIterObject* +\family default + mit) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function takes a multi-iterator object that has been previously +\begin_inset Quotes eld +\end_inset + +broadcasted, +\begin_inset Quotes erd +\end_inset + + finds the dimension with the smallest +\begin_inset Quotes eld +\end_inset + +sum of strides +\begin_inset Quotes erd +\end_inset + + in the broadcasted result and adapts all the iterators so as not to iterate + over that dimension (by effectively making them of length-1 in that dimension). + The corresponding dimension is returned unless +\emph on +mit +\emph default +->nd is 0, then -1 is returned. + This function is useful for constructing ufunc-like routines that broadcast + their inputs correctly and then call a strided 1-d version of the routine + as the inner-loop. + This 1-d version is usually optimized for speed and for this reason the + loop should be performed over the axis that won't require large stride + jumps. + +\end_layout + +\begin_layout Subsection +Array Scalars +\end_layout + +\begin_layout Description +PyArray_Return ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyArrayObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function checks to see if +\emph on +arr +\emph default + is a 0-dimensional array and, if so, returns the appropriate array scalar. + It should be used whenever 0-dimensional arrays could be returned to Python. +\end_layout + +\begin_layout Description +PyArray_Scalar ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +PyArray_Descr* +\family default + dtype, +\family typewriter +PyObject* +\family default + itemsize) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an array scalar object of the given enumerated +\emph on +typenum +\emph default + and +\emph on +itemsize +\emph default + by +\series bold +copying +\series default + from memory pointed to by +\emph on +data +\emph default +. + If +\emph on +swap +\emph default + is nonzero then this function will byteswap the data if appropriate to + the data-type because array scalars are always in correct machine-byte + order. +\end_layout + +\begin_layout Description +PyArray_ToScalar ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +void* +\family default + data, +\family typewriter +PyArrayObject* +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an array scalar object of the type and itemsize indicated by the + array object +\emph on +arr +\emph default + copied from the memory pointed to by +\emph on +data +\emph default + and swapping if the data in +\emph on +arr +\emph default + is not in machine byte-order. +\end_layout + +\begin_layout Description +PyArray_FromScalar ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + scalar, +\family typewriter +PyArray_Descr* +\family default + outcode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a 0-dimensional array of type determined by +\emph on +outcode +\emph default + from +\emph on +scalar +\emph default + which should be an array-scalar object. + If +\emph on +outcode +\emph default + is NULL, then the type is determined from +\family typewriter +\emph on +scalar +\family default +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_ScalarAsCtype ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + scalar, +\family typewriter +void* +\family default + ctypeptr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return in +\emph on +ctypeptr +\emph default + a pointer to the actual value in an array scalar. + There is no error checking so +\emph on +scalar +\emph default + must be an array-scalar object, and ctypeptr must have enough space to + hold the correct type. + For flexible-sized types, a pointer to the data is copied into the memory + of +\emph on +ctypeptr +\emph default +, for all other types, the actual data is copied into the address pointed + to by +\emph on +ctypeptr +\emph default +. + +\end_layout + +\begin_layout Description +PyArray_CastScalarToCtype ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + scalar, +\family typewriter +void* +\family default + ctypeptr, +\family typewriter +PyArray_Descr* +\family default + outcode) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the data (cast to the data type indicated by +\emph on +outcode +\emph default +) from the array-scalar, +\emph on +scalar +\emph default +, into the memory pointed to by +\emph on +ctypeptr +\emph default + (which must be large enough to handle the incoming memory). + +\end_layout + +\begin_layout Description +PyArray_TypeObjectFromType ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + type) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns a scalar type-object from a type-number, +\emph on +type +\emph default +. + Equivalent to +\family typewriter +PyArray_DescrFromType +\family default +( +\emph on +type +\emph default +)->typeobj except for reference counting and error-checking. + Returns a new reference to the typeobject on success or +\family typewriter +NULL +\family default + on failure. +\end_layout + +\begin_layout Description +PyArray_ScalarKind ( +\family typewriter +NPY_SCALARKIND +\family default +) ( +\family typewriter +int +\family default + typenum, +\family typewriter +PyArrayObject** +\family default + arr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the kind of scalar represented by +\emph on +typenum +\emph default + and the array in +\emph on +*arr +\emph default + (if +\emph on +arr +\emph default + is not +\family typewriter +NULL +\family default +). + The array is assumed to be rank-0 and only used if +\emph on +typenum +\emph default + represents a signed integer. + If +\emph on +arr +\emph default + is not +\family typewriter +NULL +\family default + and the first element is negative then +\family typewriter +NPY_INTNEG_SCALAR +\family default + is returned, otherwise +\family typewriter +NPY_INTPOS_SCALAR +\family default + is returned. + The possible return values are +\family typewriter +NPY_ +\family default +<kind> +\family typewriter +_SCALAR +\family default + where <kind> can be +\series bold +INTPOS +\series default +, +\series bold +INTNEG +\series default +, +\series bold +FLOAT +\series default +, +\series bold +COMPLEX +\series default +, +\series bold +BOOL +\series default +, or +\series bold +OBJECT +\series default +. + +\family typewriter +NPY_NOSCALAR +\family default + is also an enumerated value +\family typewriter +NPY_SCALARKIND +\family default + variables can take on. + +\end_layout + +\begin_layout Description +PyArray_CanCoerceScalar ( +\family typewriter +int +\family default +) ( +\family typewriter +char +\family default + thistype, +\family typewriter +char +\family default + neededtype, +\family typewriter +NPY_SCALARKIND +\family default + scalar) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Implements the rules for scalar coercion. + Scalars are only silently coerced from thistype to neededtype if this function + returns nonzero. + If scalar is +\family typewriter +NPY_NOSCALAR +\family default +, then this function is equivalent to +\family typewriter +PyArray_CanCastSafely +\family default +. + The rule is that scalars of the same KIND can be coerced into arrays of + the same KIND. + This rule means that high-precision scalars will never cause low-precision + arrays of the same KIND to be upcast. + +\end_layout + +\begin_layout Subsection +Data-type descriptors +\end_layout + +\begin_layout Warning +Data-type objects must be reference counted so be aware of the action on + the data-type reference of different C-API calls. + The standard rule is that when a data-type object is returned it is a new + reference. + Functions that take +\family typewriter +PyArray_Descr* +\family default + objects and return arrays steal references to the data-type their inputs + unless otherwise noted. + Therefore, you must own a reference to any data-type object used as input + to such a function. + +\end_layout + +\begin_layout Description +PyArrayDescr_Check ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates as true if +\emph on +obj +\emph default + is a data-type object ( +\family typewriter +PyArray_Descr* +\family default +). +\end_layout + +\begin_layout Description +PyArray_DescrNew ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a new data-type object copied from +\emph on +obj +\emph default + (the fields reference is just updated so that the new object points to + the same fields dictionary if any). + +\end_layout + +\begin_layout Description +PyArray_DescrNewFromType ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create a new data-type object from the built-in (or user-registered) data-type + indicated by +\emph on +typenum +\emph default +. + All builtin types should not have any of their fields changed. + This creates a new copy of the +\family typewriter +PyArray_Descr +\family default + structure so that you can fill it in as appropriate. + This function is especially needed for flexible data-types which need to + have a new elsize member in order to be meaningful in array construction. + +\end_layout + +\begin_layout Description +PyArray_DescrNewByteorder ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +PyArray_Descr* +\family default + obj, +\family typewriter +char +\family default + newendian) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create a new data-type object with the byteorder set according to +\emph on +newendian +\emph default +. + All referenced data-type objects (in subdescr and fields members of the + data-type object) are also changed (recursively). + If a byteorder of +\family typewriter +NPY_IGNORE +\family default + is encountered it is left alone. + If newendian is +\family typewriter +NPY_SWAP +\family default +, then all byte-orders are swapped. + Other valid newendian values are +\family typewriter +NPY_NATIVE +\family default +, +\family typewriter +NPY_LITTLE +\family default +, and +\family typewriter +NPY_BIG +\family default + which all cause the returned data-typed descriptor (and all it's referenced + data-type descriptors) to have the corresponding byte-order. +\end_layout + +\begin_layout Description +PyArray_DescrFromObject ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +PyArray_Descr* +\family default + mintype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Determine an appropriate data-type object from the object +\emph on +op +\emph default + (which should be a +\begin_inset Quotes eld +\end_inset + +nested +\begin_inset Quotes erd +\end_inset + + sequence object) and the minimum data-type descriptor mintype (which can + be +\family typewriter +NULL +\family default +). + Similar in behavior to array( +\emph on +op +\emph default +).dtype. + Don't confuse this function with +\family typewriter +PyArray_DescrConverter +\family default +. + This function essentially looks at all the objects in the (nested) sequence + and determines the data-type from the elements it finds. + +\end_layout + +\begin_layout Description +PyArray_DescrFromScalar ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +PyObject* +\family default + scalar) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a data-type object from an array-scalar object. + No checking is done to be sure that +\emph on +scalar +\emph default + is an array scalar. + If no suitable data-type can be determined, then a data-type of NPY_OBJECT + is returned by default. + +\end_layout + +\begin_layout Description +PyArray_DescrFromType ( +\family typewriter +PyArray_Descr* +\family default +) ( +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns a data-type object corresponding to +\emph on +typenum +\emph default +. + The +\emph on +typenum +\emph default + can be one of the enumerated types, a character code for one of the enumerated + types, or a user-defined type. + +\end_layout + +\begin_layout Description +PyArray_DescrConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Descr** +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any compatible Python object, +\emph on +obj +\emph default +, to a data-type object in +\emph on +dtype +\emph default +. + A large number of Python objects can be converted to data-type objects. + See Chapter +\begin_inset LatexCommand ref +reference "cha:Data-descriptor-objects" + +\end_inset + + for a complete description. + This version of the converter converts None objects to a +\family typewriter +NPY_DEFAULT_TYPE +\family default + data-type object. + This function can be used with the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + character code in PyArg_ParseTuple processing. + +\end_layout + +\begin_layout Description +PyArray_DescrConverter2 ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Descr** +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any compatible Python object, +\emph on +obj +\emph default +, to a data-type object in +\emph on +dtype +\emph default +. + This version of the converter converts None objects so that the returned + data-type is +\family typewriter +NULL +\family default +. + This function can also be used with the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + character in PyArg_ParseTuple processing. +\end_layout + +\begin_layout Description +Pyarray_DescrAlignConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Descr** +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Like +\family typewriter +PyArray_DescrConverter +\family default + except it aligns C-struct-like objects on word-boundaries as the compiler + would. +\end_layout + +\begin_layout Description +Pyarray_DescrAlignConverter2 ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Descr** +\family default + dtype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Like +\family typewriter +PyArray_DescrConverter2 +\family default + except it aligns C-struct-like objects on word-boundaries as the compiler + would. +\end_layout + +\begin_layout Description +PyArray_FieldNames ( +\family typewriter +PyObject* +\family default +)( +\family typewriter +PyObject* +\family default + dict) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Take the fields dictionary, +\family typewriter +\emph on +dict +\family default +\emph default +, such as the one attached to a data-type object and construct an ordered-list + of field names such as is stored in the names field of the +\family typewriter +PyArray_Descr +\family default + object. + +\end_layout + +\begin_layout Subsection +Conversion Utilities +\end_layout + +\begin_layout Subsubsection +For use with +\family typewriter +PyArg_ParseTuple +\end_layout + +\begin_layout Standard +All of these functions can be used in +\family typewriter +PyArg_ParseTuple +\family default +(...) with the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + format specifier to automatically convert any Python object to the required + C-object. + All of these functions return +\family typewriter +NPY_SUCCEED +\family default + if successful and +\family typewriter +NPY_FAIL +\family default + if not. + The first argument to all of these function is a Python object. + The second argument is the +\series bold +address +\series default + of the C-type to convert the Python object to. + +\end_layout + +\begin_layout Warning +Be sure to understand what steps you should take to manage the memory when + using these conversion functions. + These functions can require freeing memory, and/or altering the reference + counts of specific objects based on your use. +\end_layout + +\begin_layout Description +PyArray_Converter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyObject** +\family default + address) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any Python object to a +\family typewriter +PyArrayObject +\family default +. + If +\family typewriter +PyArray_Check +\family default +( +\family typewriter +\emph on +obj +\family default +\emph default +) is TRUE then its reference count is incremented and a reference placed + in +\emph on +address +\emph default +. + If +\emph on +obj +\emph default + is not an array, then convert it to an array using +\family typewriter +PyArray_FromAny +\family default +. + No matter what is returned, you must DECREF the object returned by this + routine in +\emph on +address +\emph default + when you are done with it. + +\end_layout + +\begin_layout Description +PyArray_OutputConverter ( +\family typewriter +int +\family default +)( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArrayObject** +\family default + address) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is a default converter for output arrays given to functions. + If +\emph on +obj +\emph default + is +\family typewriter +Py_None +\family default + or +\family typewriter +NULL +\family default +, then +\emph on +*address +\emph default + will be +\family typewriter +NULL +\family default + but the call will succeed. + If +\family typewriter +PyArray_Check +\family default +( +\emph on +obj +\emph default +) is TRUE then it is returned in +\emph on +*address +\emph default + without incrementing its reference count. + +\end_layout + +\begin_layout Description +PyArray_IntpConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Dims* +\family default + seq) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any Python sequence, +\emph on +obj +\emph default +, smaller than +\family typewriter +NPY_MAXDIMS +\family default + to a C-array of +\family typewriter +npy_intp +\family default +. + The Python object could also be a single number. + The +\emph on +seq +\emph default + variable is a pointer to a structure with members ptr and len. + On successful return, +\emph on +seq +\emph default +->ptr contains a pointer to memory that must be freed to avoid a memory + leak. + The restriction on memory size allows this converter to be conveniently + used for sequences intended to be interpreted as array shapes. + +\end_layout + +\begin_layout Description +PyArray_BufferConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +PyArray_Chunk* +\family default + buf) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any Python object, +\emph on +obj +\emph default +, with a (single-segment) buffer interface to a variable with members that + detail the object's use of its chunk of memory. + The +\emph on +buf +\emph default + variable is a pointer to a structure with base, ptr, len, and flags members. + The +\family typewriter +PyArray_Chunk +\family default + structure is binary compatibile with the Python's buffer object (through + its len member on 32-bit platforms and its ptr member on 64-bit platforms + or in Python 2.5). + On return, the base member is set to +\emph on +obj +\emph default + (or its base if +\emph on +obj +\emph default + is already a buffer object pointing to another object). + If you need to hold on to the memory be sure to INCREF the base member. + The chunk of memory is pointed to by +\emph on +buf +\emph default +->ptr member and has length +\emph on +buf +\emph default +->len. + The flags member of +\emph on +buf +\emph default + is +\family typewriter +NPY_BEHAVED_RO +\family default + with the +\family typewriter +NPY_WRITEABLE +\family default + flag set if +\emph on +obj +\emph default + has a writeable buffer interface. + +\end_layout + +\begin_layout Description +PyArray_AxisConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject +\family default +* obj, +\family typewriter +int* +\family default + axis) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert a Python object, +\emph on +obj +\emph default +, representing an axis argument to the proper value for passing to the functions + that take an integer axis. + Specifically, if +\emph on +obj +\emph default + is None, +\emph on +axis +\emph default + is set to +\family typewriter +NPY_MAXDIMS +\family default + which is interpreted correctly by the C-API functions that take axis arguments. +\end_layout + +\begin_layout Description +PyArray_BoolConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +Bool* +\family default + value) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any Python object, +\emph on +obj +\emph default +, to +\family typewriter +NPY_TRUE +\family default + or +\family typewriter +NPY_FALSE +\family default +, and place the result in +\emph on +value +\emph default +. +\end_layout + +\begin_layout Description +PyArray_ByteorderConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +char* +\family default + endian) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert Python strings into the corresponding byte-order character: '>', + '<', 's', '=', or '|'. + +\end_layout + +\begin_layout Description +PyArray_SortkindConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +NPY_SORTKIND* +\family default + sort) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert Python strings into one of +\family typewriter +NPY_QUICKSORT +\family default + (starts with 'q' or 'Q') , +\family typewriter +NPY_HEAPSORT +\family default + (starts with 'h' or 'H'), or +\family typewriter +NPY_MERGESORT +\family default + (starts with 'm' or 'M'). + +\end_layout + +\begin_layout Description +PyArray_SearchsideConverter ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +NPY_SEARCHSIDE* +\family default + side) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert Python strings into one of +\family typewriter +NPY_SEARCHLEFT +\family default + (starts with 'l' or 'L'), or +\family typewriter +NPY_SEARCHRIGHT +\family default + (starts with 'r' or 'R'). + +\end_layout + +\begin_layout Subsubsection +Other conversions +\end_layout + +\begin_layout Description +PyArray_PyIntAsInt ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert all kinds of Python objects (including arrays and array scalars) + to a standard integer. + On error, -1 is returned and an exception set. + You may find useful the macro: +\end_layout + +\begin_layout LyX-Code +#define error_converting(x) (((x) == -1) && PyErr_Occurred() +\end_layout + +\begin_layout Description +PyArray_PyIntAsIntp ( +\family typewriter +npy_intp +\family default +) ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert all kinds of Python objects (including arrays and array scalars) + to a (platform-pointer-sized) integer. + On error, -1 is returned and an exception set. + +\end_layout + +\begin_layout Description +PyArray_IntpFromSequence ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + seq, +\family typewriter +npy_intp* +\family default + vals, +\family typewriter +int +\family default + maxvals) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert any Python sequence (or single Python number) passed in as +\emph on +seq +\emph default + to (up to) +\emph on +maxvals +\emph default + pointer-sized integers and place them in the +\emph on +vals +\emph default + array. + The sequence can be smaller then +\emph on +maxvals +\emph default + as the number of converted objects is returned. + +\end_layout + +\begin_layout Description +PyArray_TypestrConvert ( +\family typewriter +int +\family default +) ( +\family typewriter +int +\family default + itemsize, +\family typewriter +int +\family default + gentype) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Convert typestring characters (with +\emph on +itemsize +\emph default +) to basic enumerated data types. + The typestring character corresponding to signed and unsigned integers, + floating point numbers, and complex-floating point numbers are recognized + and converted. + Other values of gentype are returned. + This function can be used to convert, for example, the string 'f4' to +\family typewriter +NPY_FLOAT32 +\family default +. + +\end_layout + +\begin_layout Subsection +Miscellaneous +\end_layout + +\begin_layout Subsubsection +Importing the API +\end_layout + +\begin_layout Standard +In order to make use of the C-API from another extension module, the +\family typewriter +import_array +\family default +() command must be used. + If the extension module is self-contained in a single .c file, then that + is all that needs to be done. + If, however, the extension module involves multiple files where the C-API + is needed then some additional steps must be taken. +\end_layout + +\begin_layout Description +import_array (void) (void) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function must be called in the initialization section of a module + that will make use of the C-API. + It imports the module where the function-pointer table is stored and points + the correct variable to it. + +\end_layout + +\begin_layout Description +PY_ARRAY_UNIQUE_SYMBOL +\end_layout + +\begin_layout Description +NO_IMPORT_ARRAY +\end_layout + +\begin_layout Description +\InsetSpace ~ + Using these #defines you can use the C-API in multiple files for a single + extension module. + In each file you must define +\family typewriter +PY_ARRAY_UNIQUE_SYMBOL +\family default + to some name that will hold the C-API ( +\emph on +e.g. + +\emph default + myextension_ARRAY_API). + This must be done +\series bold +before +\series default + including the numpy/arrayobject.h file. + In the module intialization routine you call +\family typewriter +import_array +\family default +(). + In addition, in the files that do not have the module initialization sub_routin +e define +\family typewriter +NO_IMPORT_ARRAY +\family default + prior to including numpy/arrayobject.h. +\end_layout + +\begin_layout Description +\InsetSpace ~ + Suppose I have two files coolmodule.c and coolhelper.c which need to be compiled + and linked into a single extension module. + Suppose coolmodule.c contains the required initcool module initialization + function (with the import_array() function called). + Then, coolmodule.c would have at the top: +\end_layout + +\begin_layout LyX-Code +#define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API +\end_layout + +\begin_layout LyX-Code +#include numpy/arrayobject.h +\end_layout + +\begin_layout Description +\InsetSpace ~ + On the other hand, coolhelper.c would contain at the top: +\end_layout + +\begin_layout LyX-Code +#define PY_ARRAY_UNIQUE_SYMBOL cool_ARRAY_API +\end_layout + +\begin_layout LyX-Code +#define NO_IMPORT_ARRAY +\end_layout + +\begin_layout LyX-Code +#include numpy/arrayobject.h +\end_layout + +\begin_layout Description +PyArray_GetNDArrayCVersion ( +\family typewriter +unsigned +\family default + +\family typewriter +int +\family default +) ( +\family typewriter +void +\family default +) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This just returns the value +\family typewriter +NPY_VERSION +\family default +. + Because it is in the C-API, however, comparing the output of this function + from the value defined in the current header gives a way to test if the + C-API has changed thus requiring a re-compilation of extension modules + that use the C-API. + +\end_layout + +\begin_layout Subsubsection +Internal Flexibility +\end_layout + +\begin_layout Description +PyArray_SetNumericOps ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + dict) +\end_layout + +\begin_layout Description +\InsetSpace ~ + NumPy stores an internal table of Python callable objects that are used + to implement arithmetic operations for arrays as well as certain array + calculation methods. + This function allows the user to replace any or all of these Python objects + with their own versions. + The keys of the dictionary, +\emph on +dict +\emph default +, are the named functions to replace and the paired value is the Python + callable object to use. + Care should be taken that the function used to replace an internal array + operation does not itself call back to that internal array operation (unless + you have designed the function to handle that), or an unchecked infinite + recursion can result (possibly causing program crash). + The key names that represent operations that can be replaced are: +\end_layout + +\begin_layout Quote + +\series bold +add +\series default +, +\series bold +subtract +\series default +, +\series bold +multiply +\series default +, +\series bold +divide +\series default +, +\series bold +remainder +\series default +, +\series bold +power +\series default +, +\series bold +square, reciprocal, ones_like, sqrt +\series default +, +\series bold +negative +\series default +, +\series bold +absolute +\series default +, +\series bold +invert +\series default +, +\series bold +left_shift +\series default +, +\series bold +right_shift +\series default +, +\series bold +bitwise_and +\series default +, +\series bold +bitwise_xor +\series default +, +\series bold +bitwise_or +\series default +, +\series bold +less +\series default +, +\series bold +less_equal +\series default +, +\series bold +equal +\series default +, +\series bold +not_equal +\series default +, +\series bold +greater +\series default +, +\series bold +greater_equal +\series default +, +\series bold +floor_divide +\series default +, +\series bold +true_divide +\series default +, +\series bold +logical_or +\series default +, +\series bold +logical_and +\series default +, +\series bold +floor +\series default +, +\series bold +ceil +\series default +, +\series bold +maximum +\series default +, +\series bold +minimum +\series default +, +\series bold +rint +\series default +. +\end_layout + +\begin_layout Description +\InsetSpace ~ + These functions are included here because they are used at least once in + the array object's methods. + The function returns -1 (without setting a Python Error) if one of the + objects being assigned is not callable. +\end_layout + +\begin_layout Description +PyArray_GetNumericOps ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +void +\family default +) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return a Python dictionary containing the callable Python objects stored + in the the internal arithmetic operation table. + The keys of this dictionary are given in the explanation for +\family typewriter +PyArray_SetNumericOps +\family default +. +\end_layout + +\begin_layout Description +PyArray_SetStringFunction ( +\family typewriter +void +\family default +) ( +\family typewriter +PyObject* +\family default + op, +\family typewriter +int +\family default + repr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function allows you to alter the tp_str and tp_repr methods of the + array object to any Python function. + Thus you can alter what happens for all arrays when str(arr) or repr(arr) + is called from Python. + The function to be called is passed in as +\emph on +op +\emph default +. + If +\emph on +repr +\emph default + is non-zero, then this function will be called in response to repr(arr), + otherwise the function will be called in response to str(arr). + No check on whether or not +\emph on +op +\emph default + is callable is performed. + The callable passed in to +\emph on +op +\emph default + should expect an array argument and should return a string to be printed. +\end_layout + +\begin_layout Subsubsection +Memory management +\end_layout + +\begin_layout Description +PyDataMem_NEW ( +\family typewriter +char* +\family default +) ( +\family typewriter +size_t +\family default + nbytes) +\end_layout + +\begin_layout Description +PyDataMem_FREE ( +\family typewriter +char* +\family default + ptr) +\end_layout + +\begin_layout Description +PyDataMem_RENEW ( +\family typewriter +char* +\family default +) ( +\family typewriter +void * +\family default + ptr, +\family typewriter +size_t +\family default + newbytes) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Macros to allocate, free, and reallocate memory. + These macros are used internally to create arrays. +\end_layout + +\begin_layout Description +PyDimMem_NEW ( +\family typewriter +npy_intp* +\family default +) (nd) +\end_layout + +\begin_layout Description +PyDimMem_FREE ( +\family typewriter +npy_intp* +\family default + ptr) +\end_layout + +\begin_layout Description +PyDimMem_RENEW ( +\family typewriter +npy_intp* +\family default +) ( +\family typewriter +npy_intp* +\family default + ptr, +\family typewriter +npy_intp +\family default + newnd) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Macros to allocate, free, and reallocate dimension and strides memory. +\end_layout + +\begin_layout Description +PyArray_malloc (nbytes) +\end_layout + +\begin_layout Description +PyArray_free (ptr) +\end_layout + +\begin_layout Description +PyArray_realloc (ptr, nbytes) +\end_layout + +\begin_layout Description +\InsetSpace ~ + These macros use different memory allocators, depending on the constant + +\family typewriter +NPY_USE_PYMEM +\family default +. + The system malloc is used when NPY_USE_PYMEM is 0, if NPY_USE_PYMEM is + 1, then the Python memory allocator is used. + +\end_layout + +\begin_layout Subsubsection +Threading support +\end_layout + +\begin_layout Standard +These macros are only meaningful if +\family typewriter +NPY_ALLOW_THREADS +\family default + evaluates True during compilation of the extension module. + Otherwise, these macros are equivalent to whitespace. + Python uses a single Global Interpreter Lock (GIL) for each Python process + so that only a single thread may excecute at a time (even on multi-cpu + machines). + When calling out to a compiled function that may take time to compute (and + does not have side-effects for other threads like updated global variables), + the GIL should be released so that other Python threads can run while the + time-consuming calculations are performed. + This can be accomplished using two groups of macros. + Typically, if one macro in a group is used in a code block, all of them + must be used in the same code block. + Currently, +\family typewriter +NPY_ALLOW_THREADS +\family default + is defined to the python-defined +\family typewriter +WITH_THREADS +\family default + constant unless the environment variable +\family typewriter +NPY_NOSMP +\family default + is set in which case +\family typewriter +NPY_ALLOW_THREADS +\family default + is defined to be 0. + +\end_layout + +\begin_layout Description +Group\InsetSpace ~ +1 This group is used to call code that may take some time but does + not use any Python C-API calls. + Thus, the GIL should be released during its calculation. +\end_layout + +\begin_deeper +\begin_layout Description +NPY_BEGIN_ALLOW_THREADS Equivalent to +\family typewriter +Py_BEGIN_ALLOW_THREADS +\family default + except it uses +\family typewriter +NPY_ALLOW_THREADS +\family default + to determine if the macro if replaced with white-space or not. + +\end_layout + +\begin_layout Description +NPY_END_ALLOW_THREADS Equivalent to +\family typewriter +Py_END_ALLOW_THREADS +\family default + except it uses +\family typewriter +NPY_ALLOW_THREADS +\family default + to determine if the macro if replaced with white-space or not. + +\end_layout + +\begin_layout Description +NPY_BEGIN_THREADS_DEF Place in the variable declaration area. + This macro sets up the variable needed for storing the Python state. +\end_layout + +\begin_layout Description +NPY_BEGIN_THREADS Place right before code that does not need the Python + interpreter (no Python C-API calls). + This macro saves the Python state and releases the GIL. +\end_layout + +\begin_layout Description +NPY_END_THREADS Place right after code that does not need the Python interpreter. + This macro acquires the GIL and restores the Python state from the saved + variable. +\end_layout + +\begin_layout Description +NPY_BEGIN_THREADS_DESCR ( +\family typewriter +PyArray_Descr* +\family default + dtype) Useful to release the GIL only if +\emph on +dtype +\emph default + does not contain arbitrary Python objects which may need the Python interpreter + during execution of the loop. + Equivalent to +\end_layout + +\begin_layout Description +NPY_END_THREADS_DESCR ( +\family typewriter +PyArray_Descr* +\family default + dtype) Useful to regain the GIL in situations where it was released using + the BEGIN form of this macro. + +\end_layout + +\end_deeper +\begin_layout Description +Group\InsetSpace ~ +2 This group is used to re-acquire the Python GIL after it has been + released. + For example, suppose the GIL has been released (using the previous calls), + and then some path in the code (perhaps in a different subroutine) requires + use of the Python C-API, then these macros are useful to acquire the GIL. + These macros accomplish essentially a reverse of the previous three (acquire + the LOCK saving what state it had) and then re-release it with the saved + state. +\end_layout + +\begin_deeper +\begin_layout Description +NPY_ALLOW_C_API_DEF Place in the variable declaration area to set up the + necessary variable. + +\end_layout + +\begin_layout Description +NPY_ALLOW_C_API Place before code that needs to call the Python C-API (when + it is known that the GIL has already been released). + +\end_layout + +\begin_layout Description +NPY_DISABLE_C_API Place after code that needs to call the Python C-API (to + re-release the GIL). + +\end_layout + +\end_deeper +\begin_layout Tip +Never use semicolons after the threading support macros. +\end_layout + +\begin_layout Subsubsection +Priority +\end_layout + +\begin_layout Description +NPY_PRIOIRTY Default priority for arrays. +\end_layout + +\begin_layout Description +NPY_SUBTYPE_PRIORITY Default subtype priority. +\end_layout + +\begin_layout Description +NPY_SCALAR_PRIORITY Default scalar priority (very small) +\end_layout + +\begin_layout Description +PyArray_GetPriority ( +\family typewriter +double +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +double +\family default + def) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return the +\series bold +__array_priority__ +\series default + attribute (converted to a double) of +\emph on +obj +\emph default + or +\emph on +def +\emph default + if no attribute of that name exists. + Fast returns that avoid the attribute lookup are provided for objects of + type +\family typewriter +PyArray_Type +\family default +. + +\end_layout + +\begin_layout Subsubsection +Default buffers +\end_layout + +\begin_layout Description +NPY_BUFSIZE Default size of the user-settable internal buffers. +\end_layout + +\begin_layout Description +NPY_MIN_BUFSIZE Smallest size of user-settable internal buffers. +\end_layout + +\begin_layout Description +NPY_MAX_BUFSIZE Largest size allowed for the user-settable buffers. +\end_layout + +\begin_layout Subsubsection +Other constants +\end_layout + +\begin_layout Description +NPY_NUM_FLOATTYPE The number of floating-point types +\end_layout + +\begin_layout Description +NPY_MAXDIMS The maximum number of dimensions allowed in arrays. +\end_layout + +\begin_layout Description +NPY_VERSION The current version of the ndarray object (check to see if this + variable is defined to guarantee the numpy/arrayobject.h header is being + used). + +\end_layout + +\begin_layout Description +NPY_FALSE Defined as 0 for use with Bool. +\end_layout + +\begin_layout Description +NPY_TRUE Defined as 1 for use with Bool. +\end_layout + +\begin_layout Description +NPY_FAIL The return value of failed converter functions which are called + using the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + syntax in PyArg_ParseTuple-like functions. +\end_layout + +\begin_layout Description +NPY_SUCCEED The return value of successful converter functions which are + called using the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + syntax in PyArg_ParseTuple-like functions. +\end_layout + +\begin_layout Subsubsection +Miscellaneous Macros +\end_layout + +\begin_layout Description +PyArray_SAMESHAPE (a1, a2) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Evaluates as True if arrays +\emph on +a1 +\emph default + and +\emph on +a2 +\emph default + have the same shape. + +\end_layout + +\begin_layout Description +PyArray_MAX (a,b) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns the maximum of +\emph on +a +\emph default + and +\emph on +b +\emph default +. + If ( +\emph on +a +\emph default +) or ( +\emph on +b +\emph default +) are expressions they are evaluated twice. +\end_layout + +\begin_layout Description +PyArray_MIN (a,b) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns the minimum of +\emph on +a +\emph default + and +\emph on +b +\emph default +. + If ( +\emph on +a +\emph default +) or ( +\emph on +b +\emph default +) are expressions they are evaluated twice. +\end_layout + +\begin_layout Description +PyArray_CLT (a,b) +\end_layout + +\begin_layout Description +PyArray_CGT (a,b) +\end_layout + +\begin_layout Description +PyArray_CLE (a,b) +\end_layout + +\begin_layout Description +PyArray_CGE (a,b) +\end_layout + +\begin_layout Description +PyArray_CEQ (a,b) +\end_layout + +\begin_layout Description +PyArray_CNE (a,b) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Implements the complex comparisons between two complex numbers (structures + with a real and imag member) using NumPy's definition of the ordering which + is lexicographic: comparing the real parts first and then the complex parts + if the real parts are equal. + +\end_layout + +\begin_layout Description +PyArray_REFCOUNT ( +\family typewriter +PyObject* +\family default + op) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Returns the reference count of any Python object. + +\end_layout + +\begin_layout Description +PyArray_XDECREF_ERR (PyObject *obj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + DECREF's an array object which may have the +\family typewriter +NPY_UPDATEIFCOPY +\family default + flag set without causing the contents to be copied back into the original + array. + Resets the +\family typewriter +NPY_WRITEABLE +\family default + flag on the base object. + This is useful for recovering from an error condition when +\family typewriter +NPY_UPDATEIFCOPY +\family default + is used. + +\end_layout + +\begin_layout Subsubsection +Enumerated Types +\end_layout + +\begin_layout Description +NPY_SORTKIND A special variable-type which can take on the values +\series bold +NPY_ +\series default +<KIND> where <KIND> is +\end_layout + +\begin_layout Quote + +\series bold +QUICKSORT +\series default +, +\series bold +HEAPSORT +\series default +, +\series bold +MERGESORT +\end_layout + +\begin_layout Description +\InsetSpace ~ + +\series bold +NPY_NSORTS +\series default + is defined to be the number of sorts. +\end_layout + +\begin_layout Description +NPY_SCALARKIND A special variable type indicating the number of +\begin_inset Quotes eld +\end_inset + +kinds +\begin_inset Quotes erd +\end_inset + + of scalars distinguished in determining scalar-coercion rules. + This variable can take on the values NPY_<KIND> where <KIND> can be +\end_layout + +\begin_layout Quote + +\series bold +NOSCALAR +\series default +, +\series bold +BOOL_SCALAR +\series default +, +\series bold +INTPOS_SCALAR +\series default +, +\series bold +INTNEG_SCALAR +\series default +, +\series bold +FLOAT_SCALAR +\series default +, +\series bold +COMPLEX_SCALAR +\series default +, +\series bold +OBJECT_SCALAR +\end_layout + +\begin_layout Description +\InsetSpace ~ + +\series bold +NPY_NSCALARKINDS +\series default + is defined to be the number of scalar kinds (not including +\family typewriter +NPY_NOSCALAR +\family default +). + +\end_layout + +\begin_layout Description +NPY_ORDER A variable type indicating the order that an array should be interpret +ed in. + The value of a variable of this type can be +\series bold +NPY_ +\series default +<ORDER> where <ORDER> is +\end_layout + +\begin_layout Quote + +\series bold +ANYORDER +\series default +, +\series bold +CORDER +\series default +, +\series bold +FORTRANORDER +\end_layout + +\begin_layout Description +NPY_CLIPMODE A variable type indicating the kind of clipping that should + be applied in certain functions. + The value of a variable of this type can be +\series bold +NPY_ +\series default +<MODE> where <MODE> is +\end_layout + +\begin_layout Quote + +\series bold +CLIP +\series default +, +\series bold +WRAP +\series default +, +\series bold +RAISE +\begin_inset LatexCommand index +name "ndarray!C-API|)" + +\end_inset + + +\begin_inset LatexCommand index +name "C-API!array|)" + +\end_inset + + +\end_layout + +\begin_layout Section +UFunc API +\begin_inset LatexCommand index +name "ufunc!C-API|(" + +\end_inset + + +\begin_inset LatexCommand index +name "C-API!ufunc|(" + +\end_inset + + +\end_layout + +\begin_layout Subsection +Constants +\end_layout + +\begin_layout Description +UFUNC_ERR_<HANDLER> +\end_layout + +\begin_layout Description +\InsetSpace ~ + <HANDLER> can be +\series bold +IGNORE +\series default +, +\series bold +WARN +\series default +, +\series bold +RAISE +\series default +, or +\series bold +CALL +\end_layout + +\begin_layout Description +UFUNC_<THING>_<ERR> +\end_layout + +\begin_layout Description +\InsetSpace ~ + <THING> can be +\series bold +MASK +\series default +, +\series bold +SHIFT +\series default +, or +\series bold +FPE +\series default +, and <ERR> can be +\series bold +DIVIDEBYZERO +\series default +, +\series bold +OVERFLOW +\series default +, +\series bold +UNDERFLOW +\series default +, and +\series bold +INVALID +\series default +. +\end_layout + +\begin_layout Description +PyUFunc_<VALUE> <VALUE> can be +\series bold +One +\series default + (1), +\series bold +Zero +\series default + (0), or +\series bold +None +\series default + (-1) +\end_layout + +\begin_layout Subsection +Macros +\end_layout + +\begin_layout Description +NPY_LOOP_BEGIN_THREADS +\end_layout + +\begin_layout Description +\InsetSpace ~ + Used in universal function code to only release the Python GIL if loop->obj + is not true ( +\emph on +i.e. + +\emph default + this is not an OBJECT array loop). + Requires use of +\family typewriter +NPY_BEGIN_THREADS_DEF +\family default + in variable declaration area. +\end_layout + +\begin_layout Description +NPY_LOOP_END_THREADS +\end_layout + +\begin_layout Description +\InsetSpace ~ + Used in universal function code to re-acquire the Python GIL if it was + released (because loop->obj was not true). + +\end_layout + +\begin_layout Description +UFUNC_CHECK_ERROR (loop) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A macro used internally to check for errors and goto fail if found. + This macro requires a fail label in the current code block. + The +\emph on +loop +\emph default + variable must have at least members (obj, errormask, and errorobj). + If +\emph on +loop +\emph default +->obj is nonzero, then +\family typewriter +PyErr_Occurred +\family default +() is called (meaning the GIL must be held). + If +\emph on +loop +\emph default +->obj is zero, then if +\emph on +loop +\emph default +->errormask is nonzero, +\family typewriter +PyUFunc_checkfperr +\family default + is called with arguments +\emph on +loop +\emph default +->errormask and +\emph on +loop +\emph default +->errobj. + If the result of this check of the IEEE floating point registers is true + then the code redirects to the fail label which must be defined. +\end_layout + +\begin_layout Description +UFUNC_CHECK_STATUS ( +\emph on +ret +\emph default +) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A macro that expands to platform-dependent code. + The +\emph on +ret +\emph default + variable can can be any integer. + The +\family typewriter +UFUNC_FPE_ +\family default +<ERR> bits are set in +\emph on +ret +\emph default + according to the status of the corresponding error flags of the floating + point processor. + +\end_layout + +\begin_layout Subsection +Functions +\end_layout + +\begin_layout Description +PyUFunc_FromFuncAndData ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyUFuncGenericFunction* +\family default + func, +\family typewriter +void** +\family default + data, +\family typewriter +char* +\family default + types, +\family typewriter +int +\family default + ntypes, +\family typewriter +int +\family default + nin, +\family typewriter +int +\family default + nout, +\family typewriter +int +\family default + identity, +\family typewriter +char* +\family default + name, +\family typewriter +char* +\family default + doc, +\family typewriter +int +\family default + check_return) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Create a new broadcasting universal function from required variables. + Each ufunc builds around the notion of an element-by-element operation. + Each ufunc object contains pointers to 1-d loops implementing the basic + functionality for each supported type. + +\end_layout + +\begin_layout Description +nin The number of inputs to this operation. +\end_layout + +\begin_layout Description +nout The number of outputs +\end_layout + +\begin_layout Description +ntypes How many different data-type +\begin_inset Quotes eld +\end_inset + +signatures +\begin_inset Quotes erd +\end_inset + + the ufunc has implemented. + +\end_layout + +\begin_layout Description +func Must to an array of length +\emph on +ntypes +\emph default + containing +\family typewriter +PyUFuncGenericFunction +\family default + items. + These items are pointers to functions that acutally implement the underlying + (element-by-element) function +\begin_inset Formula $N$ +\end_inset + + times. + T +\end_layout + +\begin_layout Description +types Must be of length ( +\emph on +nin +\emph default ++ +\emph on +nout +\emph default +) +\emph on +*ntypes +\emph default +, and it contains the data-types (built-in only) that the corresponding + function in the +\emph on +func +\emph default + array can deal with. + +\end_layout + +\begin_layout Description +data Should be +\family typewriter +NULL +\family default + or a pointer to an array of size +\emph on +ntypes +\emph default +. + This array may contain arbitrary extra-data to be passed to the corresponding + 1-d loop function in the func array. + +\end_layout + +\begin_layout Description +name The name for the ufunc. + +\end_layout + +\begin_layout Description +doc Allows passing in a documentation string to be stored with the ufunc. + The documentation string should not contain the name of the function or + the calling signature as that will be dynamically determined from the object + and available when accessing the +\series bold +__doc__ +\series default + attribute of the ufunc. + +\end_layout + +\begin_layout Description +check_return Unused and present for backwards compatibility of the C-API. + A corresponding +\emph on +check_return +\emph default + integer does exist in the ufunc structure and it does get set with this + value when the ufunc object is created. + +\end_layout + +\begin_layout Description +PyUFunc_RegisterLoopForType ( +\family typewriter +int +\family default +) ( +\family typewriter +PyUFuncObject* +\family default + ufunc, +\family typewriter +int +\family default + usertype, +\family typewriter +PyUFuncGenericFunction +\family default + function, +\family typewriter +int* +\family default + arg_types, +\family typewriter +void* +\family default + data) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function allows the user to register a 1-d loop with an already-created + ufunc to be used whenever the ufunc is called with any of its input arguments + as the user-defined data-type. + This is needed in order to make ufuncs work with built-in data-types. + The data-type must have been previously registered with the numpy system. + The loop is passed in as +\emph on +function +\emph default +. + This loop can take arbitrary data which should be passed in as +\emph on +data +\emph default +. + The data-types the loop requires are passed in as +\emph on +arg_types +\emph default + which must be a pointer to memory at least as large as ufunc->nargs. +\end_layout + +\begin_layout Description +PyUFunc_ReplaceLoopBySignature ( +\family typewriter +int +\family default +) ( +\family typewriter +PyUFuncObject* +\family default + ufunc, +\family typewriter +PyUFuncGenericFunction +\family default + newfunc, +\family typewriter +int* +\family default + signature, +\family typewriter +PyUFuncGenericFunction* +\family default + oldfunc) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Replace a 1-d loop matching the given +\emph on +signature +\emph default + in the already-created +\emph on +ufunc +\emph default + with the new 1-d loop newfunc. + Return the old 1-d loop function in +\emph on +oldfunc +\emph default +. + Return 0 on success and -1 on failure. + This function works only with built-in types (use +\family typewriter +PyUFunc_RegisterLoopForType +\family default + for user-defined types). + A signature is an array of data-type numbers indicating the inputs followed + by the outputs assumed by the 1-d loop. + +\end_layout + +\begin_layout Description +PyUFunc_GenericFunction ( +\family typewriter +int +\family default +) ( +\family typewriter +PyUFuncObject* +\family default + self, +\family typewriter +PyObject* +\family default + args, +\family typewriter +PyArrayObject** +\family default + mps) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A generic ufunc call. + The ufunc is passed in as +\emph on +self +\emph default +, the arguments to the ufunc as +\emph on +args +\emph default +. + The +\emph on +mps +\emph default + argument is an array of +\family typewriter +PyArrayObject +\family default + pointers containing the converted input arguments as well as the ufunc + outputs on return. + The user is responsible for managing this array and receives a new reference + for each array in +\emph on +mps +\emph default +. + The total number of arrays in +\emph on +mps +\emph default + is given by +\emph on +self +\emph default +->nin + +\emph on +self +\emph default +->nout. +\end_layout + +\begin_layout Description +PyUFunc_checkfperr ( +\family typewriter +int +\family default +) ( +\family typewriter +int +\family default + errmask, +\family typewriter +PyObject* +\family default + errobj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + A simple interface to the IEEE error-flag checking support. + The +\emph on +errmask +\emph default + argument is a mask of +\family typewriter +UFUNC_MASK_<ERR> +\family default + bitmasks indicating which errors to check for (and how to check for them). + The +\emph on +errobj +\emph default + must be a Python tuple with two elements: a string containing the name + which will be used in any communication of error and either a callable + Python object (call-back function) or +\family typewriter +Py_None +\family default +. + The callable object will only be used if +\family typewriter +UFUNC_ERR_CALL +\family default + is set as the desired error checking method. + This routine manages the GIL and is safe to call even after releasing the + GIL. + If an error in the IEEE-compatibile hardware is determined a -1 is returned, + otherwise a 0 is returned. + +\end_layout + +\begin_layout Description +PyUFunc_clearfperr ( +\family typewriter +void +\family default +) () +\end_layout + +\begin_layout Description +\InsetSpace ~ + Clear the IEEE error flags. + +\end_layout + +\begin_layout Description +PyUFunc_GetPyValues ( +\family typewriter +void +\family default +) ( +\family typewriter +char* +\family default + name, +\family typewriter +int* +\family default + bufsize, +\family typewriter +int* +\family default + errmask, +\family typewriter +PyObject** +\family default + errobj) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Get the Python values used for ufunc processing from the thread-local storage + area unless the defaults have been set in which case the name lookup is + bypassed. + The name is placed as a string in the first element of +\emph on +*errobj +\emph default +. + The second element is the looked-up function to call on error callback. + The value of the looked-up buffer-size to use is passed into +\emph on +bufsize +\emph default +, and the value of the error mask is placed into +\emph on +errmask +\emph default +. + +\end_layout + +\begin_layout Subsection +Generic functions +\end_layout + +\begin_layout Standard +At the core of every ufunc is a collection of type-specific functions that + defines the basic functionality for each of the supported types. + These functions must evaluate the underlying function +\begin_inset Formula $N\geq1$ +\end_inset + + times. + Extra-data may be passed in that may be used during the calculation. + This feature allows some general functions to be used as these basic looping + functions. + The general function has all the code needed to point variables to the + right place and set up a function call. + The general function assumes that the actual function to call is passed + in as the extra data and calls it with the correct values. + All of these functions are suitable for placing directly in the array of + functions stored in the functions member of the PyUFuncObject structure. + +\end_layout + +\begin_layout Description +PyUFunc_f_f_As_d_d ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_d_d ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_f_f ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_g_g ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_F_F_As_D_D ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_F_F ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_D_D ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_G_G ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type specific, core 1-d functions for ufuncs where each calculation is + obtained by calling a function taking one input argument and returning + one output. + This function is passed in +\family typewriter +func +\family default +. + The letters correspond to dtypechar's of the supported data types ( +\family typewriter +f +\family default + - float, +\family typewriter +d +\family default + - double, +\family typewriter +g +\family default + - long double, +\family typewriter +F +\family default + - cfloat, +\family typewriter +D +\family default + - cdouble, +\family typewriter +G +\family default + - clongdouble). + The argument +\emph on +func +\emph default + must support the same signature. + The _As_X_X variants assume ndarray's of one data type but cast the values + to use an underlying function that takes a different data type. + Thus, +\family typewriter +PyUFunc_f_f_As_d_d +\family default + uses ndarrays of data type +\family typewriter +NPY_FLOAT +\family default + but calls out to a C-function that takes double and returns double. + +\end_layout + +\begin_layout Description +PyUFunc_ff_f_As_dd_d ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_ff_f ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_dd_d ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_gg_g ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_FF_F_As_DD_D ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_DD_D ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_FF_F ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_GG_G ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Type specific, core 1-d functions for ufuncs where each calculation is + obtained by calling a function taking two input arguments and returning + one output. + The underlying function to call is passed in as +\emph on +func +\emph default +. + The letters correspond to dtypechar's of the specific data type supported + by the general-purpose function. + The argument +\family typewriter +func +\family default + must support the corresponding signature. + The +\family typewriter +_As_XX_X +\family default + variants assume ndarrays of one data type but cast the values at each iteration + of the loop to use the underlying function that takes a different data + type. + +\end_layout + +\begin_layout Description +PyUFunc_O_O ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +PyUFunc_OO_O ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + One-input, one-output, and two-input, one-output core 1-d functions for + the +\family typewriter +NPY_OBJECT +\family default + data type. + These functions handle reference count issues and return early on error. + The actual function to call is +\emph on +func +\emph default + and it must accept calls with the signature ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default +) for +\family typewriter +PyUFunc_O_O +\family default + or ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject +\family default + *, +\family typewriter +PyObject +\family default + *) for +\family typewriter +PyUFunc_OO_O +\family default +. +\end_layout + +\begin_layout Description +PyUFunc_O_O_method ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This general purpose 1-d core function assumes that +\emph on +func +\emph default + is a string representing a method of the input object. + For each iteration of the loop, the Python obejct is extracted from the + array and its +\emph on +func +\emph default + method is called returning the result to the output array. + +\end_layout + +\begin_layout Description +PyUFunc_OO_O_method ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This general purpose 1-d core function assumes that +\emph on +func +\emph default + is a string representing a method of the input object that takes one argument. + The first argument in +\emph on +args +\emph default + is the method whose function is called, the second argument in +\emph on +args +\emph default + is the argument passed to the function. + The output of the function is stored in the third entry of +\emph on +args +\emph default +. + +\end_layout + +\begin_layout Description +PyUFunc_On_Om ( +\family typewriter +void +\family default +) ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + func) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This is the 1-d core function used by the dynamic ufuncs created by umath.frompy +func(function, nin, nout). + In this case +\emph on +func +\emph default + is a pointer to a +\family typewriter +PyUFunc_PyFuncData +\family default + structure which has definition { +\family typewriter +int +\family default + nin; +\family typewriter +int +\family default + nout; +\family typewriter +PyObject* +\family default + callable}. + At each iteration of the loop, the +\emph on +nin +\emph default + input objects are exctracted from their object arrays and placed into an + argument tuple, the Python +\emph on +callable +\emph default + is called with the input arguments, and the nout outputs are placed into + their object arrays. + +\end_layout + +\begin_layout Section +Importing the API +\end_layout + +\begin_layout Description +PY_UFUNC_UNIQUE_SYMBOL +\end_layout + +\begin_layout Description +NO_IMPORT_UFUNC +\end_layout + +\begin_layout Description +import_ufunc ( +\family typewriter +void +\family default +) ( +\family typewriter +void +\family default +) +\end_layout + +\begin_layout Description +\InsetSpace ~ + These are the constants and functions for accessing the ufunc C-API from + extension modules in precisely the same way as the array C-API can be accessed. + The +\family typewriter +import_ufunc +\family default +() function must always be called (in the initialization subroutine of the + extension module). + If your extension module is in one file then that is all that is required. + The other two constants are useful if your extension module makes use of + multiple files. + In that case, define +\family typewriter +PY_UFUNC_UNIQUE_SYMBOL +\family default + to something unique to your code and then in source files that do not contain + the module initialization function but still need access to the UFUNC API, + define +\family typewriter +PY_UFUNC_UNIQUE_SYMBOL +\family default + to the same name used previously and also define +\family typewriter +NO_IMPORT_UFUNC +\family default +. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + The C-API is actually an array of function pointers. + This array is created (and pointed to by a global variable) by import_ufunc. + The global variable is either statically defined or allowed to be seen + by other files depending on the state of +\family typewriter +Py_UFUNC_UNIQUE_SYMBOL +\family default + and +\family typewriter +NO_IMPORT_UFUNC +\family default +. + +\begin_inset LatexCommand index +name "ufunc!C-API|)" + +\end_inset + + +\begin_inset LatexCommand index +name "C-API!ufunc|)" + +\end_inset + + +\end_layout + +\begin_layout Chapter +How to extend NumPy +\end_layout + +\begin_layout Quotation +That which is static and repetitive is boring. + That which is dynamic and random is confusing. + In between lies art. +\end_layout + +\begin_layout Right Address +--- +\emph on +John A. + Locke +\end_layout + +\begin_layout Quotation +Science is a differential equation. + Religion is a boundary condition. +\end_layout + +\begin_layout Right Address +--- +\emph on +Alan Turing +\end_layout + +\begin_layout Section +Writing an extension module +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand label +name "sec:Writing-an-extension" + +\end_inset + + +\begin_inset LatexCommand index +name "extension module|(" + +\end_inset + +While the ndarray object is designed to allow rapid computation in Python, + it is also designed to be general-purpose and satisfy a wide-variety of + computational needs. + As a result, if absolute speed is essential, there is no replacement for + a well-crafted, compiled loop specific to your application and hardware. + This is one of the reasons that numpy includes f2py so that an easy-to-use + mechanisms for linking (simple) C/C++ and (arbitrary) Fortran code directly + into Python are available. + You are encouraged to use and improve this mechanism. + The purpose of this section is not to document this tool but to document + the more basic steps to writing an extension module that this tool depends + on. + +\end_layout + +\begin_layout Standard +When an extension module is written, compiled, and installed to somewhere + in the Python path (sys.path), the code can then be imported into Python + as if it were a standard python file. + It will contain objects and methods that have been defined and compiled + in C code. + The basic steps for doing this in Python are well-documented and you can + find more information in the documentation for Python itself available + online at +\begin_inset LatexCommand url +name "www.python.org" +target "http://www.python.org" + +\end_inset + +. + +\end_layout + +\begin_layout Standard +In addition to the Python C-API, there is a full and rich C-API for NumPy + allowing sophisticated manipulations on a C-level. + However, for most applications, only a few API calls will typically be + used. + If all you need to do is extract a pointer to memory along with some shape + information to pass to another calculation routine, then you will use very + different calls, then if you are trying to create a new array-like type + or add a new data type for ndarrays. + This chapter documents the API calls and macros that are most commonly + used. +\end_layout + +\begin_layout Section +Required subroutine +\end_layout + +\begin_layout Standard +There is exactly one function that must be defined in your C-code in order + for Python to use it as an extension module. + The function must be called init<name> where <name> is the name of the + module from Python. + This function must be declared so that it is visible to code outside of + the routine. + Besides adding the methods and constants you desire, this subroutine must + also contain calls to import_array() and/or import_ufunc() depending on + which C-API is needed. + Forgetting to place these commands will show itself as an ugly segmentation + fault (crash) as soon as any C-API subroutine is actually called. + It is actually possible to have multiple init<name> functions in a single + file in which case multiple modules will be defined by that file. + However, there are some tricks to get that to work correctly and it is + not covered here. +\end_layout + +\begin_layout Standard +A minimal init<name> method looks like +\end_layout + +\begin_layout LyX-Code +PyMODINIT_FUNC +\newline +init<name>(void) +\newline +{ +\newline + (void)Py_InitModule( +\begin_inset Quotes erd +\end_inset + +<name> +\begin_inset Quotes erd +\end_inset + +, mymethods); +\newline + import_array(); +\newline +} +\end_layout + +\begin_layout Standard +The mymethods must be an array (usually statically declared) of PyMethodDef + structures which contain method names, actual C-functions, a variable indicatin +g whether the method uses keyword arguments or not, and docstrings. + These are explained in the next section. + If you want to add constants to the module, then you store the returned + value from Py_InitModule which is a module object. + The most general way to add itmes to the module is to get the module dictionary + using PyModule_GetDict(module). + With the module dictionary, you can add whatever you like to the module + manually. + An easier way to add objects to the module is to use one of three additional + Python C-API calls that do not require a separate extraction of the module + dictionary. + These are documented in the Python documentation, but repeated here for + convenience: +\end_layout + +\begin_layout Description +PyModule_AddObject ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + module, +\family typewriter +char* +\family default + name, +\family typewriter +PyObject* +\family default + value) +\end_layout + +\begin_layout Description +PyModule_AddIntConstant ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + module, +\family typewriter +char* +\family default + name, +\family typewriter +long +\family default + value) +\end_layout + +\begin_layout Description +PyModule_AddStringConstant ( +\family typewriter +int +\family default +) ( +\family typewriter +PyObject* +\family default + module, +\family typewriter +char* +\family default + name, +\family typewriter +char* +\family default + value) +\end_layout + +\begin_layout Description +\InsetSpace ~ + All three of these functions require the +\family typewriter +module +\family default + object (the return value of Py_InitModule). + The +\family typewriter +name +\family default + is a string that labels the value in the module. + Depending on which function is called, the +\family typewriter +value +\family default + argument is either a general object (PyModule_AddObject steals a reference + to it), an integer constant, or a string constant. +\end_layout + +\begin_layout Section +Defining functions +\end_layout + +\begin_layout Standard +The second argument passed in to the Py_InitModule function is a structure + that makes it easy to to define functions in the module. + In the example given above, the mymethods structure would have been defined + earlier in the file (usually right before the init<name> subroutine) to + +\end_layout + +\begin_layout LyX-Code +static PyMethodDef mymethods[] = { +\newline +{ +\begin_inset Quotes erd +\end_inset + +nokeywordfunc +\begin_inset Quotes erd +\end_inset + +,nokeyword_cfunc, +\newline +METH_VARARGS, +\newline + +\begin_inset Quotes erd +\end_inset + +Doc string +\begin_inset Quotes erd +\end_inset + +}, +\newline +{ +\begin_inset Quotes erd +\end_inset + +keywordfunc +\begin_inset Quotes erd +\end_inset + +, keyword_cfunc, +\end_layout + +\begin_layout LyX-Code +METH_VARARGS|METH_KEYWORDS, +\newline + +\begin_inset Quotes erd +\end_inset + +Doc string +\begin_inset Quotes erd +\end_inset + +}, +\newline +{NULL, NULL, 0, NULL} /* Sentinel */ +\newline +} +\end_layout + +\begin_layout Standard +Each entry in the mymethods array is a PyMethodDef structure containing + 1) the Python name, 2) the C-function that implements the function, 3) + flags indicating whether or not keywords are accepted for this function, + and 4) The docstring for the function. + Any number of functions may be defined for a single module by adding more + entries to this table. + The last entry must be all NULL as shown to act as a sentinel. + Python looks for this entry to know that all of the functions for the module + have been defined. + +\end_layout + +\begin_layout Standard +The last thing that must be done to finish the extension module is to actually + write the code that performs the desired functions. + There are two kinds of functions: those that don't accept keyword arguments, + and those that do. +\end_layout + +\begin_layout Subsection +Functions without keyword arguments +\end_layout + +\begin_layout Standard +Functions that don't accept keyword arguments should be written as +\end_layout + +\begin_layout LyX-Code +static PyObject* +\newline +nokeyword_cfunc (PyObject *dummy, PyObject *args) +\newline +{ +\newline + /* + convert Python arguments */ +\newline + /* do function */ +\end_layout + +\begin_layout LyX-Code + /* return something */ +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Standard +The dummy argument is not used in this context and can be safely ignored. + The +\emph on +args +\emph default + argument contains all of the arguments passed in to the function as a tuple. + You can do anything you want at this point, but usually the easiest way + to manage the input arguments is to call +\family typewriter +PyArg_ParseTuple +\family default + (args, format_string, addresses_to_C_variables...) or +\family typewriter +PyArg_UnpackTuple +\family default + (tuple, +\begin_inset Quotes eld +\end_inset + +name +\begin_inset Quotes erd +\end_inset + +, min, max, ...). + A good description of how to use the first function is contained in the + Python C-API reference manual under section 5.5 (Parsing arguments and building + values). + You should pay particular attention to the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + format which uses converter functions to go between the Python object and + the C object. + All of the other format functions can be (mostly) thought of as special + cases of this general rule. + There are several converter functions defined in the NumPy C-API that may + be of use. + In particular, the +\family typewriter +PyArray_DescrConverter +\family default + function is very useful to support arbitrary data-type specification. + This function transforms any valid data-type Python object into a +\family typewriter +PyArray_Descr* +\family default + object. + Remember to pass in the address of the C-variables that should be filled + in. +\end_layout + +\begin_layout Standard +There are lots of examples of how to use +\family typewriter +PyArg_ParseTuple +\family default + throughout the NumPy source code. + The standard usage is like this: +\end_layout + +\begin_layout LyX-Code +PyObject *input; +\end_layout + +\begin_layout LyX-Code +PyArray_Descr *dtype; +\end_layout + +\begin_layout LyX-Code +if (!PyArg_ParseTuple(args, "OO&", &input, +\newline + PyArray_DescrCon +verter, +\newline + &dtype)) return NULL; +\end_layout + +\begin_layout Standard +It is important to keep in mind that you get a +\emph on +borrowed +\emph default + reference to the object when using the +\begin_inset Quotes eld +\end_inset + +O +\begin_inset Quotes erd +\end_inset + + format string. + However, the converter functions usually require some form of memory handling. + In this example, if the conversion is successful, +\emph on +dtype +\emph default + will hold a new reference to a +\family typewriter +PyArray_Descr* +\family default + object, while +\emph on +input +\emph default + will hold a borrowed reference. + Therefore, if this conversion were mixed with another conversion (say to + an integer) and the data-type conversion was successful but the integer + conversion failed, then you would need to release the reference count to + the data-type object before returning. + A typical way to do this is to set +\emph on +dtype +\emph default + to +\family typewriter +NULL +\family default + before calling PyArg_ParseTuple and then use +\family typewriter +Py_XDECREF +\family default + on +\emph on +dtype +\emph default + before returning. + +\end_layout + +\begin_layout Standard +After the input arguments are processed, the code that actually does the + work is written (likely calling other functions as needed). + The final step of the C-function is to return something. + If an error is encountered then +\family typewriter +NULL +\family default + should be returned (making sure an error has actually been set). + If nothing should be returned then increment +\family typewriter +Py_None +\family default + and return it. + If a single object should be returned then it is returned (ensuring that + you own a reference to it first). + If multiple objects should be returned then you need to return a tuple. + The +\family typewriter +Py_BuildValue +\family default + (format_string, c_variables...) function makes it easy to build tuples of + Python objects from C variables. + Pay special attention to the difference between 'N' and 'O' in the format + string or you can easily create memory leaks. + The 'O' format string increments the reference count of the +\family typewriter +PyObject* +\family default + C-variable it corresponds to, while the 'N' format string steals a reference + to the corresponding +\family typewriter +PyObject* +\family default + C-variable. + You should use 'N' if you ave already created a reference for the object + and just want to give that reference to the tuple. + You should use 'O' if you only have a borrowed reference to an object and + need to create one to provide for the tuple. + +\end_layout + +\begin_layout Subsection +Functions with keyword arguments +\end_layout + +\begin_layout Standard +These functions are very similar to functions without keyword arguments. + The only difference is that the function signature is +\end_layout + +\begin_layout LyX-Code +static PyObject* +\newline +keyword_cfunc (PyObject *dummy, PyObject *args, PyObject + *kwds) +\newline +{ +\newline +... +\newline +} +\end_layout + +\begin_layout Standard +The kwds argument holds a Python dictionary whose keys are the names of + the keyword arguments and whose values are the corresponding keyword-argument + values. + This dictionary can be processed however you see fit. + The easiest way to handle it, however, is to replace the +\family typewriter +PyArg_ParseTuple +\family default + (args, format_string, addresses...) function with a call to +\family typewriter +PyArg_ParseTupleAndKeywords +\family default + (args, kwds, format_string, char *kwlist[], addresses...). + The kwlist parameter to this function is a +\family typewriter +NULL +\family default +-terminated array of strings providing the expected keyword arguments. + There should be one string for each entry in the format_string. + Using this function will raise a TypeError if invalid keyword arguments + are passed in. + +\end_layout + +\begin_layout Standard +For more help on this function please see section 1.8 (Keyword Paramters + for Extension Functions) of the Extending and Embedding tutorial in the + Python documentation. +\end_layout + +\begin_layout Subsection +Reference counting +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "reference counting|(" + +\end_inset + +The biggest difficulty when writing extension modules is reference counting. + It is an important reason for the popularity of f2py, weave, pyrex, ctypes, + etc.... + If you mis-handle reference counts you can get problems from memory-leaks + to segmentation faults. + The only strategy I know of to handle reference counts correctly is blood, + sweat, and tears. + First, you force it into your head that every Python variable has a reference + count. + Then, you understand exactly what each function does to the reference count + of your objects, so that you can properly use DECREF and INCREF when you + need them. + Reference counting can really test the amount of patience and diligence + you have towards your programming craft. + Despite the grim depiction, most cases of reference counting are quite + straightforward with the most common difficulty being not using DECREF + on objects before exiting early from a routine due to some error. + In second place, is the common error of not owning the reference on an + object that is passed to a function or macro that is going to steal the + reference ( +\emph on +e.g. + +\emph default + +\family typewriter +PyTuple_SET_ITEM +\family default +, and most functions that take +\family typewriter +PyArray_Descr +\family default + objects). + +\end_layout + +\begin_layout Standard +Typically you get a new reference to a variable when it is created or is + the return value of some function (there are some prominent exceptions, + however --- such as getting an item out of a tuple or a dictionary). + When you own the reference, you are responsible to make sure that +\family typewriter +Py_DECREF +\family default +(var) is called when the variable is no longer necessary (and no other function + has +\begin_inset Quotes eld +\end_inset + +stolen +\begin_inset Quotes erd +\end_inset + + its reference). + Also, if you are passing a Python object to a function that will +\begin_inset Quotes eld +\end_inset + +steal +\begin_inset Quotes erd +\end_inset + + the reference, then you need to make sure you own it (or use +\family typewriter +Py_INCREF +\family default + to get your own reference). + You will also encounter the notion of borrowing a reference. + A function that borrows a reference does not alter the reference count + of the object and does not expect to +\begin_inset Quotes eld +\end_inset + +hold on +\begin_inset Quotes erd +\end_inset + + to the reference. + It's just going to use the object temporarily. + When you use +\family typewriter +PyArg_ParseTuple +\family default + or +\family typewriter +PyArg_UnpackTuple +\family default + you receive a borrowed reference to the objects in the tuple and should + not alter their reference count inside your function. + With practice, you can learn to get reference counting right, but it can + be frustrating at first. + +\end_layout + +\begin_layout Standard +One common source of reference-count errors is the +\family typewriter +Py_BuildValue +\family default + function. + Pay careful attention to the difference between the 'N' format character + and the 'O' format character. + If you create a new object in your subroutine (such as an output array), + and you are passing it back in a tuple of return values, then you should + most-likely use the 'N' format character in +\family typewriter +Py_BuildValue +\family default +. + The 'O' character will increase the reference count by one. + This will leave the caller with two reference counts for a brand-new array. + When the variable is deleted and the reference count decremented by one, + there will still be that extra reference count, and the array will never + be deallocated. + You will have a reference-counting induced memory leak. + Using the 'N' character will avoid this situation as it will return to + the caller an object (inside the tuple) with a single reference count. + +\begin_inset LatexCommand index +name "reference counting|)" + +\end_inset + + +\end_layout + +\begin_layout Section +Dealing with array objects +\end_layout + +\begin_layout Standard +Most extension modules for NumPy will need to access the memory for an ndarray + object (or one of it's sub-classes). + The easiest way to do this doesn't require you to know much about the internals + of NumPy. + The method is to +\end_layout + +\begin_layout Enumerate +Ensure you are dealing with a well-behaved array (aligned, in machine byte-order + and single-segment) of the correct type and number of dimensions. + +\end_layout + +\begin_deeper +\begin_layout Enumerate +By converting it from some Python object using +\family typewriter +PyArray_FromAny +\family default + or a macro built on it. + +\end_layout + +\begin_layout Enumerate +By constructing a new ndarray of your desired shape and type using +\family typewriter +PyArray_NewFromDescr +\family default + or a simpler macro or function based on it. + +\end_layout + +\end_deeper +\begin_layout Enumerate +Get the shape of the array and a pointer to its actual data. + +\end_layout + +\begin_layout Enumerate +Pass the data and shape information on to a subroutine or other section + of code that actually performs the computation. + +\end_layout + +\begin_layout Enumerate +If you are writing the algorithm, then I recommend that you use the stride + information contained in the array to access the elements of the array + (the +\family typewriter +PyArray_GETPTR +\family default + macros make this painless). + Then, you can relax your requirements so as not to force a single-segment + array and the data-copying that might result. + +\end_layout + +\begin_layout Standard +Each of these sub-topics is covered in the following sub-sections. +\end_layout + +\begin_layout Subsection +Converting an arbitrary sequence object +\end_layout + +\begin_layout Standard +The main routine for obtaining an array from any Python object that can + be converted to an array is +\family typewriter +PyArray_FromAny +\family default +. + This function is very flexible with many input arguments. + Several macros make it easier to use the basic function. + +\family typewriter +PyArray_FROM_OTF +\family default + is arguably the most useful of these macros for the most common uses. + It allows you to convert an arbitrary Python object to an array of a specific + builtin data-type ( +\emph on +e.g. + +\emph default + float), while specifying a particular set of requirements ( +\emph on +e.g. + +\emph default + contiguous, aligned, and writeable). + The syntax is +\end_layout + +\begin_layout Description +PyArray_FROM_OTF ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyObject* +\family default + obj, +\family typewriter +int +\family default + typenum, +\family typewriter +int +\family default + requirements) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Return an ndarray from any Python object, +\emph on +obj +\emph default +, that can be converted to an array. + The number of dimensions in the returned array is determined by the object. + The desired data-type of the returned array is provided in +\emph on +typenum +\emph default + which should be one of the enumerated types. + The +\emph on +requirements +\emph default + for the returned array can be any combination of standard array flags. + Each of these arguments is explained in more detail below. + You receive a new reference to the array on success. + On failure, +\family typewriter +NULL +\family default + is returned and an exception is set. + +\end_layout + +\begin_deeper +\begin_layout Description +obj The object can be any Python object convertable to an ndarray. + If the object is already (a subclass of) the ndarray that satisfies the + requirements then a new reference is returned. + Otherwise, a new array is constructed. + The contents of +\emph on +obj +\emph default + are copied to the new array unless the array interface is used so that + data does not have to be copied. + Objects that can be converted to an array include: 1) any nested sequence + object, 2) any object exposing the array interface, 3) any object with + an +\series bold +__array__ +\series default + method (which should return an ndarray), and 4) any scalar object (becomes + a zero-dimensional array). + Sub-classes of the ndarray that otherwise fit the requirements will be + passed through. + If you want to ensure a base-class ndarray, then use +\family typewriter +NPY_ENSUREARRAY +\family default + in the requirements flag. + A copy is made only if necessary. + If you want to guarantee a copy, then pass in +\family typewriter +NPY_ENSURECOPY +\family default + to the requirements flag. + +\end_layout + +\begin_layout Description +typenum One of the enumerated types or +\family typewriter +NPY_NOTYPE +\family default + if the data-type should be determined from the object itself. + The C-based names can be used: +\end_layout + +\begin_deeper +\begin_layout Quote + +\family typewriter +NPY_BOOL +\family default +, +\family typewriter +NPY_BYTE +\family default +, +\family typewriter +NPY_UBYTE +\family default +, +\family typewriter +NPY_SHORT +\family default +, +\family typewriter +NPY_USHORT +\family default +, +\family typewriter +NPY_INT +\family default +, +\family typewriter +NPY_UINT +\family default +, +\family typewriter +NPY_LONG +\family default +, +\family typewriter +NPY_ULONG +\family default +, +\family typewriter +NPY_LONGLONG +\family default +, +\family typewriter +NPY_ULONGLONG +\family default +, +\family typewriter +NPY_DOUBLE +\family default +, +\family typewriter +NPY_LONGDOUBLE +\family default +, +\family typewriter +NPY_CFLOAT +\family default +, +\family typewriter +NPY_CDOUBLE +\family default +, +\family typewriter +NPY_CLONGDOUBLE +\family default +, +\family typewriter +NPY_OBJECT +\family default +. + +\end_layout + +\end_deeper +\begin_layout Description +\InsetSpace ~ + Alternatively, the bit-width names can be used as supported on the platform. + For example: +\end_layout + +\begin_deeper +\begin_layout Quote + +\family typewriter +NPY_INT8 +\family default +, +\family typewriter +NPY_INT16 +\family default +, +\family typewriter +NPY_INT32 +\family default +, +\family typewriter +NPY_INT64 +\family default +, +\family typewriter +NPY_UINT8 +\family default +, +\family typewriter +NPY_UINT16 +\family default +, +\family typewriter +NPY_UINT32 +\family default +, +\family typewriter +NPY_UINT64 +\family default +, +\family typewriter +NPY_FLOAT32 +\family default +, +\family typewriter +NPY_FLOAT64 +\family default +, +\family typewriter +NPY_COMPLEX64 +\family default +, +\family typewriter +NPY_COMPLEX128 +\family default +. + +\end_layout + +\end_deeper +\begin_layout Description +\InsetSpace ~ + The object will be converted to the desired type only if it can be done + without losing precision. + Otherwise +\family typewriter +NULL +\family default + will be returned and an error raised. + Use +\family typewriter +NPY_FORCECAST +\family default + in the requirements flag to override this behavior. + +\end_layout + +\begin_layout Description +requirements The memory model for an ndarray admits arbitrary strides in + each dimension to advance to the next element of the array. + Often, however, you need to interface with code that expects a C-contiguous + or a Fortran-contiguous memory layout. + In addition, an ndarray can be misaligned (the address of an element is + not at an integral multiple of the size of the element) which can cause + your program to crash (or at least work more slowly) if you try and dereference + a pointer into the array data. + Both of these problems can be solved by converting the Python object into + an array that is more +\begin_inset Quotes eld +\end_inset + +well-behaved +\begin_inset Quotes erd +\end_inset + + for your specific usage. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + The requirements flag allows specification of what kind of array is acceptable. + If the object passed in does not satisfy this requirements then a copy + is made so that thre returned object will satisfy the requirements. + these ndarray can use a very generic pointer to memory. + This flag allows specification of the desired properties of the returned + array object. + All of the flags are explained in the detailed API chapter. + The flags most commonly needed are NPY_IN_ARRAY, NPY_OUT_ARRAY, and NPY_INOUT_A +RRAY: +\end_layout + +\begin_deeper +\begin_layout Description +NPY_IN_ARRAY Equivalent to NPY_CONTIGUOUS | NPY_ALIGNED. + This combination of flags is useful for arrays that must be in C-contiguous + order and aligned. + These kinds of arrays are usually input arrays for some algorithm. +\end_layout + +\begin_layout Description +NPY_OUT_ARRAY Equivalent to NPY_CONTIGUOUS | NPY_ALIGNED | NPY_WRITEABLE. + This combination of flags is useful to specify an array that is in C-contiguous + order, is aligned, and can be written to as well. + Such an array is usually returned as output (although normally such output + arrays are created from scratch). + +\end_layout + +\begin_layout Description +NPY_INOUT_ARRAY Equivalent to NPY_CONTIGUOUS | NPY_ALIGNED | NPY_WRITEABLE + | NPY_UPDATEIFCOPY. + This combination of flags is useful to specify an array that will be used + for both input and output. + If a copy is needed, then when the temporary is deleted (by your use of + Py_DECREF at the end of the interface routine), the temporary array will + be copied back into the original array passed in. + Use of the UPDATEIFCOPY flag requires that the input object is already + an array (because other objects cannot be automatically updated in this + fashion). + If an error occurs use +\series bold +PyArray_DECREF_ERR +\series default +(obj) on an array with the NPY_UPDATEIFCOPY flag set. + This will delete the array without causing the contents to be copied back + into the original array. + +\end_layout + +\end_deeper +\begin_layout Description +\InsetSpace ~ + Other useful flags that can be OR'd as additional requirements are: +\end_layout + +\begin_deeper +\begin_layout Description +NPY_FORCECAST Cast to the desired type, even if it can't be done without + losing information. +\end_layout + +\begin_layout Description +NPY_ENSURECOPY Make sure the resulting array is a copy of the original. +\end_layout + +\begin_layout Description +NPY_ENSUREARRAY Make sure the resulting object is an actual ndarray and + not a sub-class. +\end_layout + +\end_deeper +\end_deeper +\begin_layout Note +Whether or not an array is byte-swapped is determined by the data-type of + the array. + Native byte-order arrays are always requested by PyArray_FROM_OTF and so + there is no need for a NPY_NOTSWAPPED flag in the requirements argument. + There is also no way to get a byte-swapped array from this routine. +\end_layout + +\begin_layout Subsection +Creating a brand-new ndarray +\end_layout + +\begin_layout Standard +Quite often new arrays must be created from within extension-module code. + Perhaps an output array is needed and you don't want the caller to have + to supply it. + Perhaps only a temporary array is needed to hold an intermediate calculation. + Whatever the need there are simple ways to get an ndarray object of whatever + data-type is needed. + The most general function for doing this is PyArray_NewFromDescr. + All array creation functions go through this heavily re-used code. + Because of its flexibility, it can be somewhat confusing to use. + As a result, simpler forms exist that are easier to use. + +\end_layout + +\begin_layout Description +PyArray_SimpleNew ( +\family typewriter +PyObject* +\family default +)( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + typenum) +\end_layout + +\begin_layout Description +\InsetSpace ~ + This function allocates new memory and places it in an ndarray with +\family typewriter +nd +\family default + dimensions whose shape is determined by the array of at least +\family typewriter +nd +\family default + items pointed to by +\family typewriter +dims +\family default +. + The memory for the array is uninitialized (unless typenum is +\series bold +PyArray_OBJECT +\series default + in which case each element in the array is set to NULL). + The +\family typewriter +typenum +\family default + argument allows specification of any of the builtin data-types such as + +\series bold +PyArray_FLOAT +\series default + or +\series bold +PyArray_LONG +\series default +. + The memory for the array can be set to zero if desired using +\series bold +PyArray_FILLWBYTE +\series default +(return_object, 0). + +\end_layout + +\begin_layout Description +PyArray_SimpleNewFromData ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +int +\family default + nd, +\family typewriter +npy_intp* +\family default + dims, +\family typewriter +int +\family default + typenum, +\family typewriter +void* +\family default + data) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Sometimes, you want to wrap memory allocated elsewhere into an ndarray + object for downstream use. + This routine makes it straightforward to do that. + The first three arguments are the same as in +\series bold +PyArray_SimpleNew +\series default +, the final argument is a pointer to a block of contiguous memory that the + ndarray should use as it's data-buffer which will be interpreted in C-style + contiguous fashion. + A new reference to an ndarray is returned, but the ndarray will not own + its data. + When this ndarray is deallocated, the pointer will not be freed. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + You should ensure that the provided memory is not freed while the returned + array is in existence. + The easiest way to handle this is if data comes from another reference-counted + Python object. + The reference count on this object should be increased after the pointer + is passed in, and the base member of the returned ndarray should point + to the Python object that owns the data. + Then, when the ndarray is deallocated, the base-member will be DECREF'd + appropriately. + If you want the memory to be freed as soon as the ndarray is deallocated + then simply set the OWNDATA flag on the returned ndarray. + +\end_layout + +\begin_layout Subsection +Getting at ndarray memory and accessing elements of the ndarray +\end_layout + +\begin_layout Standard +If obj is an ndarray (PyArrayObject *), then the data-area of the ndarray + is pointed to by the void* pointer +\series bold +PyArray_DATA +\series default +(obj) or the char* pointer +\series bold +PyArray_BYTES +\series default +(obj). + Remember that (in general) this data-area may not be aligned according + to the data-type, it may represent byte-swapped data, and/or it may not + be writeable. + If the data area is aligned and in native byte-order, then how to get at + a specific element of the array is determined only by the array of npy_intp + variables, +\series bold +PyArray_STRIDES +\series default +(obj). + In particular, this c-array of integers shows how many +\series bold +bytes +\series default + must be added to the current element pointer to get to the next element + in each dimension. + For arrays less than 4-dimensions there are +\series bold +PyArray_GETPTR<k> +\series default +(obj, ...) macros where <k> is the integer 1, 2, 3, or 4 that make using the + array strides easier. + The arguments .... + represent <k> non-negative integer indices into the array. + For example, suppose +\family typewriter +E +\family default + is a 3-dimensional ndarray. + A (void*) pointer to the element +\family typewriter +E[i,j,k] +\family default + is obtained as PyArray_GETPTR3(E, i, j, k). + +\end_layout + +\begin_layout Standard +As explained previously, C-style contiguous arrays and Fortran-style contiguous + arrays have particular striding patterns. + Two array flags (NPY_C_CONTIGUOUS and NPY_F_CONTIGUOUS) indicate whether + or not the striding pattern of a particular array matches the C-style contiguou +s or Fortran-style contiguous or neither. + Whether or not the striding pattern matches a standard C or Fortran one + can be tested Using +\family typewriter +PyArray_ISCONTIGUOUS +\family default +(obj) and +\family typewriter +PyArray_ISFORTRAN +\family default +(obj) respectively. + Most third-party libraries expect contiguous arrays. + But, often it is not difficult to support general-purpose striding. + I encourage you to use the striding information in your own code whenever + possible, and reserve single-segment requirements for wrapping third-party + code. + Using the striding information provided with the ndarray rather than requiring + a contiguous striding reduces copying that otherwise must be made. + +\end_layout + +\begin_layout Section +Example +\end_layout + +\begin_layout Standard +The following example shows how you might write a wrapper that accepts two + input arguments (that will be converted to an array) and an output argument + (that must be an array). + The function returns None and updates the output array. + +\begin_inset LatexCommand index +name "extension module|)" + +\end_inset + + +\end_layout + +\begin_layout LyX-Code +static PyObject * +\end_layout + +\begin_layout LyX-Code +example_wrapper(PyObject *dummy, PyObject *args) +\end_layout + +\begin_layout LyX-Code +{ +\end_layout + +\begin_layout LyX-Code + PyObject *arg1=NULL, *arg2=NULL, *out=NULL; +\end_layout + +\begin_layout LyX-Code + PyObject *arr1=NULL, *arr2=NULL, *oarr=NULL; +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + if (!PyArg_ParseTuple(args, +\begin_inset Quotes eld +\end_inset + +OOO& +\begin_inset Quotes erd +\end_inset + +, &arg1, *arg2, +\end_layout + +\begin_layout LyX-Code + &PyArrayType, *out)) return NULL; +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); +\end_layout + +\begin_layout LyX-Code + if (arr1 == NULL) return NULL; +\end_layout + +\begin_layout LyX-Code + arr2 = PyArray_FROM_OTF(arg2, NPY_DOUBLE, NPY_IN_ARRAY); +\end_layout + +\begin_layout LyX-Code + if (arr2 == NULL) goto fail; +\end_layout + +\begin_layout LyX-Code + oarr = PyArray_FROM_OTF(out, NPY_DOUBLE, NPY_INOUT_ARRAY); +\end_layout + +\begin_layout LyX-Code + if (oarr == NULL) goto fail; +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + /* code that makes use of arguments */ +\end_layout + +\begin_layout LyX-Code + /* You will probably need at least +\end_layout + +\begin_layout LyX-Code + nd = PyArray_NDIM(<..>) -- number of dimensions +\end_layout + +\begin_layout LyX-Code + dims = PyArray_DIMS(<..>) -- npy_intp array of length nd +\end_layout + +\begin_layout LyX-Code + showing length in each dim. +\end_layout + +\begin_layout LyX-Code + dptr = (double *)PyArray_DATA(<..>) -- pointer to data. +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + If an error occurs goto fail. +\end_layout + +\begin_layout LyX-Code + */ +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + Py_DECREF(arr1); +\end_layout + +\begin_layout LyX-Code + Py_DECREF(arr2); +\end_layout + +\begin_layout LyX-Code + Py_DECREF(oarr); +\end_layout + +\begin_layout LyX-Code + Py_INCREF(Py_None); +\end_layout + +\begin_layout LyX-Code + return Py_None; +\end_layout + +\begin_layout LyX-Code + +\end_layout + +\begin_layout LyX-Code + fail: +\end_layout + +\begin_layout LyX-Code + Py_XDECREF(arr1); +\end_layout + +\begin_layout LyX-Code + Py_XDECREF(arr2); +\end_layout + +\begin_layout LyX-Code + PyArray_XDECREF_ERR(oarr); +\end_layout + +\begin_layout LyX-Code + return NULL; +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Chapter +Beyond the Basics +\end_layout + +\begin_layout Quotation +The voyage of discovery is not in seeking new landscapes but in having new + eyes. +\end_layout + +\begin_layout Right Address +--- +\emph on +Marcel Proust +\end_layout + +\begin_layout Quotation +Discovery is seeing what everyone else has seen and thinking what no one + else has thought. +\end_layout + +\begin_layout Right Address +--- +\emph on +Albert Szent-Gyorgi +\end_layout + +\begin_layout Section +Iterating over elements in the array +\end_layout + +\begin_layout Subsection +Basic Iteration +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand label +name "sec:array_iterator" + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "array iterator|(" + +\end_inset + +One common algorithmic requirement is to be able to walk over all elements + in a multidimensional array. + The array iterator object makes this easy to do in a generic way that works + for arrays of any dimension. + Naturally, if you know the number of dimensions you will be using, then + you can always write nested for loops to accomplish the iteration. + If, however, you want to write code that works with any number of dimensions, + then you can make use of the array iterator. + An array iterator object is returned when accessing the .flat attribute + of an array. + +\end_layout + +\begin_layout Standard +Basic usage is to call +\series bold +PyArray_IterNew +\series default + ( +\family typewriter +array +\family default +) where array is an ndarray object (or one of its sub-classes). + The returned object is an array-iterator object (the same object returned + by the .flat attribute of the ndarray). + This object is usually cast to PyArrayIterObject* so that its members can + be accessed. + The only members that are needed are +\family typewriter +iter->size +\family default + which contains the total size of the array, +\family typewriter +iter->index +\family default +, which contains the current 1-d index into the array, and +\family typewriter +iter->dataptr +\family default + which is a pointer to the data for the current element of the array. + Sometimes it is also useful to access +\family typewriter +iter->ao +\family default + which is a pointer to the underlying ndarray object. + +\end_layout + +\begin_layout Standard +After processing data at the current element of the array, the next element + of the array can be obtained using the macro +\series bold +PyArray_ITER_NEXT +\series default +( +\family typewriter +iter +\family default +). + The iteration always proceeds in a C-style contiguous fashion (last index + varying the fastest). + The +\series bold +PyArray_ITER_GOTO +\series default +( +\family typewriter +iter +\family default +, +\family typewriter +destination +\family default +) can be used to jump to a particular point in the array, where +\family typewriter +destination +\family default + is an array of npy_intp data-type with space to handle at least the number + of dimensions in the underlying array. + Occasionally it is useful to use +\series bold +PyArray_ITER_GOTO1D +\series default +( +\family typewriter +iter +\family default +, +\family typewriter +index +\family default +) which will jump to the 1-d index given by the value of +\family typewriter +index +\family default +. + The most common usage, however, is given in the following example. + +\end_layout + +\begin_layout LyX-Code +PyObject *obj; /* assumed to be some ndarray object */ +\end_layout + +\begin_layout LyX-Code +PyArrayIterObject *iter; +\end_layout + +\begin_layout LyX-Code +... +\end_layout + +\begin_layout LyX-Code +iter = (PyArrayIterObject *)PyArray_IterNew(obj); +\end_layout + +\begin_layout LyX-Code +if (iter == NULL) goto fail; /* Assume fail has clean-up code */ +\end_layout + +\begin_layout LyX-Code +while (iter->index < iter->size) { +\end_layout + +\begin_layout LyX-Code + /* do something with the data at it->dataptr */ +\end_layout + +\begin_layout LyX-Code + PyArray_ITER_NEXT(it); +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout LyX-Code +... +\end_layout + +\begin_layout Standard +You can also use +\series bold +PyArrayIter_Check +\series default +( +\family typewriter +obj +\family default +) to ensure you have an iterator object and +\series bold +PyArray_ITER_RESET +\series default +( +\family typewriter +iter +\family default +) to reset an iterator object back to the beginning of the array. + +\end_layout + +\begin_layout Standard +It should be emphasized at this point that you may not need the array iterator + if your array is already contiguous (using an array iterator will work + but will be slower than the fastest code you could write). + The major purpose of array iterators is to encapsulate iteration over N-dimensi +onal arrays with arbitrary strides. + They are used in many, many places in the NumPy source code itself. + If you already know your array is contiguous (Fortran or C), then simply + adding the element-size to a running pointer variable will step you through + the array very efficiently. + In other words, code like this will probably be faster for you in the contiguou +s case (assuming doubles). + +\end_layout + +\begin_layout LyX-Code +npy_intp size; +\end_layout + +\begin_layout LyX-Code +double *dptr; /* could make this any variable type */ +\end_layout + +\begin_layout LyX-Code +size = PyArray_SIZE(obj); +\end_layout + +\begin_layout LyX-Code +dptr = PyArray_DATA(obj); +\end_layout + +\begin_layout LyX-Code +while(size--) { +\end_layout + +\begin_layout LyX-Code + /* do something with the data at dptr */ +\end_layout + +\begin_layout LyX-Code + dptr++; +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Subsection +Iterating over all but one axis +\end_layout + +\begin_layout Standard +A common algorithm is to loop over all elements of an array and perform + some function with each element by issuing a function call. + As function calls can be time consuming, one way to speed up this kind + of algorithm is to write the function so it takes a vector of data and + then write the iteration so the function call is performed for an entire + dimension of data at a time. + This increases the amount of work done per function call, thereby reducing + the function-call over-head to a small(er) fraction of the total time. + Even if the interior of the loop is performed without a function call it + can be advantageous to perform the inner loop over the dimension with the + highest number of elements to take advantage of speed enhancements available + on micro-processors that use pipelining to enhance fundmental operations. + +\end_layout + +\begin_layout Standard +The +\series bold +PyArray_IterAllButAxis +\series default +( +\family typewriter +array +\family default +, +\family typewriter +&dim +\family default +) constructs an iterator object that is modified so that it will not iterate + over the dimension indicated by dim. + The only restriction on this iterator object, is that the +\series bold +PyArray_Iter_GOTO1D +\series default +( +\family typewriter +it +\family default +, +\family typewriter +ind +\family default +) macro cannot be used (thus flat indexing won't work either if you pass + this object back to Python --- so you shouldn't do this). + Note that the returned object from this routine is still usually cast to + PyArrayIterObject *. + All that's been done is to modify the strides and dimensions of the returned + iterator to simulate iterating over array[...,0,...] where 0 is placed on the + +\begin_inset Formula $\textrm{dim}^{\textrm{th}}$ +\end_inset + + dimension. + If dim is negative, then the dimension with the largest axis is found and + used. + +\end_layout + +\begin_layout Subsection +Iterating over multiple arrays +\end_layout + +\begin_layout Standard +Very often, it is desireable to iterate over several arrays at the same + time. + The universal functions are an example of this kind of behavior. + If all you want to do is iterate over arrays with the same shape, then + simply creating several iterator objects is the standard procedure. + For example, the following code iterates over two arrays assumed to be + the same shape and size (actually obj1 just has to have at least as many + total elements as does obj2): +\end_layout + +\begin_layout LyX-Code +/* It is already assumed that obj1 and obj2 +\end_layout + +\begin_layout LyX-Code + are ndarrays of the same shape and size. +\end_layout + +\begin_layout LyX-Code +*/ +\end_layout + +\begin_layout LyX-Code +iter1 = (PyArrayIterObject *)PyArray_IterNew(obj1); +\end_layout + +\begin_layout LyX-Code +if (iter1 == NULL) goto fail; +\end_layout + +\begin_layout LyX-Code +iter2 = (PyArrayIterObject *)PyArray_IterNew(obj2); +\end_layout + +\begin_layout LyX-Code +if (iter2 == NULL) goto fail; /* assume iter1 is DECREF'd at fail */ +\end_layout + +\begin_layout LyX-Code +while (iter2->index < iter2->size) { +\end_layout + +\begin_layout LyX-Code + /* process with iter1->dataptr and iter2->dataptr */ +\end_layout + +\begin_layout LyX-Code + PyArray_ITER_NEXT(iter1); +\end_layout + +\begin_layout LyX-Code + PyArray_ITER_NEXT(iter2); +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Subsection +Broadcasting over multiple arrays +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "broadcasting" + +\end_inset + +When multiple arrays are involved in an operation, you may want to use the + same broadcasting rules that the math operations ( +\emph on +i.e. + +\emph default + the ufuncs) use. + This can be done easily using the PyArrayMultiIterObject. + This is the object returned from the Python command numpy.broadcast and + it is almost as easy to use from C. + The function +\series bold +PyArray_MultiIterNew +\series default + ( +\family typewriter +n +\family default +, +\family typewriter +... +\family default +) is used (with +\family typewriter +n +\family default + input objects in place of +\family typewriter +... +\family default +). + The input objects can be arrays or anything that can be converted into + an array. + A pointer to a PyArrayMultiIterObject is returned. + Broadcasting has already been accomplished which adjusts the iterators + so that all that needs to be done to advance to the next element in each + array is for PyArray_ITER_NEXT to be called for each of the inputs. + This incrementing is automatically performed by +\series bold +PyArray_MultiIter_NEXT +\series default +( +\family typewriter +obj +\family default +) macro (which can handle a multiterator +\family typewriter +obj +\family default + as either a PyArrayMultiObject* or a PyObject*). + The data from input number +\family typewriter +i +\family default + is available using +\series bold +PyArray_MultiIter_DATA +\series default +( +\family typewriter +obj +\family default +, +\family typewriter +i +\family default +) and the total (broadcasted) size as +\series bold +PyArray_MultiIter_SIZE +\series default +( +\family typewriter +obj +\family default +). + An example of using this feature follows. +\end_layout + +\begin_layout LyX-Code +mobj = PyArray_MultiIterNew(2, obj1, obj2); +\end_layout + +\begin_layout LyX-Code +size = PyArray_MultiIter_SIZE(obj); +\end_layout + +\begin_layout LyX-Code +while(size--) { +\end_layout + +\begin_layout LyX-Code + ptr1 = PyArray_MultiIter_DATA(mobj, 0); +\end_layout + +\begin_layout LyX-Code + ptr2 = PyArray_MultiIter_DATA(mobj, 1); +\end_layout + +\begin_layout LyX-Code + /* code using contents of ptr1 and ptr2 */ +\end_layout + +\begin_layout LyX-Code + PyArray_MultiIter_NEXT(mobj); +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Standard +The function +\series bold +PyArray_RemoveLargest +\series default +( +\family typewriter +multi +\family default +) can be used to take a multi-iterator object and adjust all the iterators + so that iteration does not take place over the largest dimension (it makes + that dimension of size 1). + The code being looped over that makes use of the pointers will very-likely + also need the strides data for each of the iterators. + This information is stored in multi->iters[i]->strides. +\end_layout + +\begin_layout Standard +There are several examples of using the multi-iterator in the NumPy source + code as it makes N-dimensional broadcasting-code very simple to write. + Browse the source for more examples. + +\begin_inset LatexCommand index +name "array iterator|)" + +\end_inset + + +\end_layout + +\begin_layout Section +Creating a new universal function +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand label +name "sec:Creating-a-new" + +\end_inset + + +\begin_inset LatexCommand index +name "ufunc!adding new|(" + +\end_inset + +The umath module is a computer-generated C-module that creates many ufuncs. + It provides a great many examples of how to create a universal function. + Creating your own ufunc that will make use of the ufunc machinery is not + difficult either. + Suppose you have a function that you want to operate element-by-element + over its inputs. + By creating a new ufunc you will obtain a function that handles +\end_layout + +\begin_layout Itemize +broadcasting +\end_layout + +\begin_layout Itemize +N-dimensional looping +\end_layout + +\begin_layout Itemize +automatic type-conversions with minimal memory usage +\end_layout + +\begin_layout Itemize +optional output arrays +\end_layout + +\begin_layout Standard +It is not difficult to create your own ufunc. + All that is required is a 1-d loop for each data-type you want to support. + Each 1-d loop must have a specific signature, and only ufuncs for fixed-size + data-types can be used. + The function call used to create a new ufunc to work on built-in data-types + is given below. + A different mechanism is used to register ufuncs for user-defined data-types. +\end_layout + +\begin_layout Description +PyUFunc_FromFuncAndData ( +\family typewriter +PyObject* +\family default +) ( +\family typewriter +PyUFuncGenericFunction* +\family default + func, +\family typewriter +void** +\family default + data, +\family typewriter +char* +\family default + types, +\family typewriter +int +\family default + ntypes, +\family typewriter +int +\family default + nin, +\family typewriter +int +\family default + nout, +\family typewriter +int +\family default + identity, +\family typewriter +char* +\family default + name, +\family typewriter +char* +\family default + doc, +\family typewriter +int +\family default + check_return) +\end_layout + +\begin_deeper +\begin_layout Description +func A pointer to an array of 1-d functions to use. + This array must be at least ntypes long. + Each entry in the array must be a +\family typewriter +PyUFuncGenericFunction +\family default + function. + This function has the following signature. + An example of a valid 1d loop function is also given. + +\end_layout + +\begin_layout Description +\InsetSpace ~ + +\family typewriter +void +\family default + loop1d ( +\family typewriter +char** +\family default + args, +\family typewriter +npy_intp* +\family default + dimensions, +\family typewriter +npy_intp* +\family default + steps, +\family typewriter +void* +\family default + data) +\end_layout + +\begin_deeper +\begin_layout Description +args An array of pointers to the actual data for the input and output arrays. + The input arguments are given first followed by the output arguments. +\end_layout + +\begin_layout Description +dimensions A pointer to the size of the dimension over which this function + is looping. + +\end_layout + +\begin_layout Description +steps A pointer to the number of bytes to jump to get to the next element + in this dimension for each of the input and output arguments. + +\end_layout + +\begin_layout Description +data Arbitrary data (extra arguments, function names, +\emph on +etc. +\emph default +) that can be stored with the ufunc and will be passed in when it is called. + +\end_layout + +\end_deeper +\begin_layout LyX-Code +static void +\newline +double_add(char *args, npy_intp *dimensions, npy_intp *steps, + void *extra) +\newline +{ +\newline + npy_intp i; +\newline + npy_intp is1=steps[0], is2=steps[1]; +\newline + + npy_intp os=steps[2], n=dimensions[0]; +\newline + char *i1=args[0], *i2=args[1], + *op=args[2]; +\newline + for (i=0; i<n; i++) { +\newline + *((double *)op) = *((double + *)i1) + +\backslash + +\newline + *((double *)i2); +\newline + i1 += is1; i2 += is2; + op += os; +\newline + } +\newline +} +\end_layout + +\begin_layout Description +data An array of data. + There should be ntypes entries (or NULL) --- one for every loop function + defined for this ufunc. + This data will be passed in to the 1-d loop. + One common use of this data variable is to pass in an actual function to + call to compute the result when a generic 1-d loop (e.g. + PyUFunc_d_d) is being used. + +\end_layout + +\begin_layout Description +types An array of type-number signatures (type +\family typewriter +char +\family default +). + This array should be of size (nin+nout)*ntypes and contain the data-types + for the corresponding 1-d loop. + The inputs should be first followed by the outputs. + For example, suppose I have a ufunc that supports 1 integer and 1 double + 1-d loop (length-2 func and data arrays) that takes 2 inputs and returns + 1 output that is always a complex double, then the types array would be +\end_layout + +\begin_layout LyX-Code +char my_sigs[] = +\backslash + +\newline +{NPY_INT, NPY_INT, NPY_CDOUBLE, +\newline +NPY_DOUBLE, NPY_DOUBLE, NPY_CDOUBLE}; +\end_layout + +\begin_layout Description +\InsetSpace ~ + The bit-width names can also be used (e.g. + +\family typewriter +NPY_INT32 +\family default +, +\family typewriter +NPY_COMPLEX128 +\family default +) if desired. + +\end_layout + +\begin_layout Description +ntypes The number of data-types supported. + This is equal to the number of 1-d loops provided. + +\end_layout + +\begin_layout Description +nin The number of input arguments. +\end_layout + +\begin_layout Description +nout The number of output arguments. +\end_layout + +\begin_layout Description +identity Either +\series bold +PyUFunc_One +\series default +, +\series bold +PyUFunc_Zero +\series default +, +\series bold +PyUFunc_None +\series default +. + This specifies what should be returned when an empty array is passed to + the reduce method of the ufunc. + +\end_layout + +\begin_layout Description +name A +\family typewriter +NULL +\family default +-terminated string providing the name of this ufunc (should be the Python + name it will be called). + +\end_layout + +\begin_layout Description +doc A documentation string for this ufunc (will be used in generating the + response to <ufunc_name>.__doc__). + Do not include the function signature or the name as this is generated + automatically. + +\end_layout + +\begin_layout Description +check_return Not presently used, but this integer value does get set in + the structure-member of similar name. + +\end_layout + +\end_deeper +\begin_layout Standard +The returned ufunc object is a callable Python object. + It should be placed in a (module) dictionary under the same name as was + used in the name argument to the ufunc-creation routine. + The following example is adapted from the umath module: +\begin_inset LatexCommand index +name "ufunc!adding new|)" + +\end_inset + + +\end_layout + +\begin_layout LyX-Code +static PyUFuncGenericFunction atan2_functions[]= +\backslash + +\newline + {PyUFunc_ff_f, PyUFunc_dd_d, +\newline + PyUFunc_gg_g, PyUFunc_OO_O_method}; +\newline +static + void* atan2_data[]= +\backslash + +\newline + {(void *)atan2f,(void *) atan2, +\newline + (void *)atan2l,(void *)"arctan2"}; +\newline +stati +c char atan2_signatures[]= +\backslash + +\newline + {NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, +\newline + NPY_DOUBLE, NPY_DOUBLE, +\newline + NPY_DOUBLE +, NPY_LONGDOUBLE, +\newline + NPY_LONGDOUBLE, NPY_LONGDOUBLE +\newline + NPY_OBJECT, NPY_OBJECT, + +\newline + NPY_OBJECT}; +\newline +... +\newline +/* in the module initialization code */ +\newline +PyObject *f, *dict, + *module; +\newline +... +\newline +dict = PyModule_GetDict(module); +\newline +... +\newline +f = PyUFunc_FromFuncAndData(atan2_funct +ions, +\newline + atan2_data, atan2_signatures, 4, 2, 1, +\newline + PyUFunc_None, "arctan2", + +\newline + "a safe and correct arctan(x1/x2)", 0); +\newline +PyDict_SetItemString(dict, "arctan2" +, f); +\newline +Py_DECREF(f); +\newline +... +\end_layout + +\begin_layout Section +User-defined data-types +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "dtype!adding new|(" + +\end_inset + +NumPy comes with 21 builtin data-types. + While this covers a large majority of possible use cases, it is conceivable + that a user may have a need for an additional data-type. + There is some support for adding an additional data-type into the NumPy + system. + This additional data-type will behave much like a regular data-type except + ufuncs must have 1-d loops registered to handle it separately. + Also checking for whether or not other data-types can be cast +\begin_inset Quotes eld +\end_inset + +safely +\begin_inset Quotes erd +\end_inset + + to and from this new type or not will always return +\begin_inset Quotes eld +\end_inset + +can cast +\begin_inset Quotes erd +\end_inset + + unless you also register which types your new data-type can be cast to + and from. + Adding data-types is one of the less well-tested areas for NumPy 1.0, so + there may be bugs remaining in the approach. + Only add a new data-type if you can't do what you want to do using the + OBJECT or VOID data-types that are already available. + As an example of what I consider a useful application of the ability to + add data-types is the possibility of adding a data-type of arbitrary precision + floats to NumPy. + +\end_layout + +\begin_layout Subsection +Adding the new data-type +\end_layout + +\begin_layout Standard +To begin to make use of the new data-type, you need to first define a new + Python type to hold the scalars of your new data-type. + It should be acceptable to inherit from one of the array scalars if your + new type has a binary compatible layout. + This will allow your new data type to have the methods and attributes of + array scalars. + New data-types must have a fixed memory size (if you want to define a data-type + that needs a flexible representation, like a variable-precision number, + then use a pointer to the object as the data-type). + The memory layout of the object structure for the new Python type must + be PyObject_HEAD followed by the fixed-size memory needed for the data-type. + For example, a suitable structure for the new Python type is: +\end_layout + +\begin_layout LyX-Code +typedef struct { +\end_layout + +\begin_layout LyX-Code + PyObject_HEAD; +\end_layout + +\begin_layout LyX-Code + some_data_type obval; +\end_layout + +\begin_layout LyX-Code + /* the name can be whatever you want */ +\end_layout + +\begin_layout LyX-Code +} PySomeDataTypeObject; +\end_layout + +\begin_layout Standard +After you have defined a new Python type object, you must then define a + new PyArray_Descr structure whose typeobject member will contain a pointer + to the data-type you've just defined. + In addition, the required functions in the +\begin_inset Quotes eld +\end_inset + +.f +\begin_inset Quotes erd +\end_inset + + member must be defined: nonzero, copyswap, copyswapn, setitem, getitem, + and cast. + The more functions in the +\begin_inset Quotes eld +\end_inset + +.f +\begin_inset Quotes erd +\end_inset + + member you define, however, the more useful the new data-type will be. + It is very important to intialize unused functions to NULL. + This can be achieved using +\series bold +PyArray_InitArrFuncs +\series default +(f). +\end_layout + +\begin_layout Standard +Once a new PyArray_Descr structure is created and filled with the needed + information and useful functions you call +\series bold +PyArray_RegisterDataType +\series default +(new_descr). + The return value from this call is an integer providing you with a unique + type_number that specifies your data-type. + This type number should be stored and made available by your module so + that other modules can use it to recognize your data-type (the other mechanism + for finding a user-defined data-type number is to search based on the name + of the type-object associated with the data-type using +\series bold +PyArray_TypeNumFromName +\series default +). + +\end_layout + +\begin_layout Subsection +Registering a casting function +\end_layout + +\begin_layout Standard +You may want to allow builtin (and other user-defined) data-types to be + cast automatically to your data-type. + In order to make this possible, you must register a casting function with + the data-type you want to be able to cast from. + This requires writing low-level casting functions for each conversion you + want to support and then registering these functions with the data-type + descriptor. + A low-level casting function has the signature. + +\end_layout + +\begin_layout Description +castfunc ( +\family typewriter +void +\family default +) ( +\family typewriter +void* +\family default + from, +\family typewriter +void* +\family default + to, +\family typewriter +npy_intp +\family default + n, +\family typewriter +void* +\family default + fromarr, +\family typewriter +void* +\family default + toarr) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Cast +\family typewriter +n +\family default + elements +\family typewriter +from +\family default + one type +\family typewriter +to +\family default + another. + The data to cast from is in a contiguous, correctly-swapped and aligned + chunk of memory pointed to by from. + The buffer to cast to is also contiguous, correctly-swapped and aligned. + The fromarr and toarr arguments should only be used for flexible-element-sized + arrays (string, unicode, void). + +\end_layout + +\begin_layout Standard +An example castfunc is +\end_layout + +\begin_layout LyX-Code +static void +\end_layout + +\begin_layout LyX-Code +double_to_float(double *from, float* to, npy_intp n, +\newline + void* ig1, void* + ig2); +\newline +while (n--) { +\newline + (*to++) = (double) *(from++); +\newline +} +\end_layout + +\begin_layout Standard +This could then be registered to convert doubles to floats using the code +\end_layout + +\begin_layout LyX-Code +doub = PyArray_DescrFromType(NPY_DOUBLE); +\newline +PyArray_RegisterCastFunc(doub, + NPY_FLOAT, +\newline + (PyArray_VectorUnaryFunc *)double_to_float); +\newline +Py_DECREF(doub); +\end_layout + +\begin_layout Subsection +Registering coercion rules +\end_layout + +\begin_layout Standard +By default, all user-defined data-types are not presumed to be safely castable + to any builtin data-types. + In addition builtin data-types are not presumed to be safely castable to + user-defined data-types. + This situation limits the ability of user-defined data-types to participate + in the coercion system used by ufuncs and other times when automatic coercion + takes place in NumPy. + This can be changed by registering data-types as safely castable from a + particlar data-type object. + The function +\series bold +PyArray_RegisterCanCast +\series default + (from_descr, totype_number, scalarkind) should be used to specify that + the data-type object from_descr can be cast to the data-type with type + number totype_number. + If you are not trying to alter scalar coercion rules, then use +\series bold +PyArray_NOSCALAR +\series default + for the scalarkind argument. +\end_layout + +\begin_layout Standard +If you want to allow your new data-type to also be able to share in the + scalar coercion rules, then you need to specify the scalarkind function + in the data-type object's +\begin_inset Quotes eld +\end_inset + +.f +\begin_inset Quotes erd +\end_inset + + member to return the kind of scalar the new data-type should be seen as + (the value of the scalar is available to that function). + Then, you can register data-types that can be cast to separately for each + scalar kind that may be returned from your user-defined data-type. + If you don't register scalar coercion handling, then all of your user-defined + data-types will be seen as +\series bold +PyArray_NOSCALAR +\series default +. + +\end_layout + +\begin_layout Subsection +Registering a ufunc loop +\end_layout + +\begin_layout Standard +You may also want to register low-level ufunc loops for your data-type so + that an ndarray of your data-type can have math applied to it seamlessly. + Registering a new loop with exactly the same arg_types signature, silently + replaces any previously registered loops for that data-type. + +\end_layout + +\begin_layout Standard +Before you can register a 1-d loop for a ufunc, the ufunc must be previously + created. + Then you call +\series bold +PyUFunc_RegisterLoopForType +\series default +(...) with the information needed for the loop. + The return value of this function is +\family typewriter +0 +\family default + if the process was successful and +\family typewriter +-1 +\family default + with an error condition set if it was not successful. + +\end_layout + +\begin_layout Description +PyUFunc_RegisterLoopForType ( +\family typewriter +int +\family default +) ( +\family typewriter +PyUFuncObject* +\family default + ufunc, +\family typewriter +int +\family default + usertype, +\family typewriter +PyUFuncGenericFunction +\family default + function, +\family typewriter +int* +\family default + arg_types, +\family typewriter +void* +\family default + data) +\end_layout + +\begin_layout Description +ufunc The ufunc to attach this loop to. +\end_layout + +\begin_layout Description +usertype The user-defined type this loop should be indexed under. + This number must be a user-defined type or an error occurs. + +\end_layout + +\begin_layout Description +function The ufunc inner 1-d loop. + This function must have the signature as explained in Section +\begin_inset LatexCommand ref +reference "sec:Creating-a-new" + +\end_inset + +. +\end_layout + +\begin_layout Description +arg_types (optional) If given, this should contain an array of integers + of at least size ufunc.nargs containing the data-types expected by the loop + function. + The data will be copied into a NumPy-managed structure so the memory for + this argument should be deleted after calling this function. + If this is NULL, then it will be assumed that all data-types are of type + usertype. +\end_layout + +\begin_layout Description +data (optional) Specify any optional data needed by the function which will + be passed when the function is called. + +\begin_inset LatexCommand index +name "dtype!adding new|)" + +\end_inset + + +\end_layout + +\begin_layout Section +Subtyping the ndarray in C +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ndarray!subtyping|(" + +\end_inset + +One of the lesser-used features that has been lurking in Python since 2.2 + is the ability to sub-class types in C. + This facility is one of the important reasons for basing NumPy off of the + Numeric code-base which was already in C. + A sub-type in C allows much more flexibility with regards to memory management. + Sub-typing in C is not difficult even if you have only a rudimentary understand +ing of how to create new types for Python. + While it is easiest to sub-type from a single parent type, sub-typing from + multiple parent types is also possible. + Multiple inheritence in C is generally less useful than it is in Python + because a restriction on Python sub-types is that they have a binary compatible + memory layout. + Perhaps for this reason, it is somewhat easier to sub-type from a single + parent type. + +\end_layout + +\begin_layout Standard +All C-structures corresponding to Python objects must begin with PyObject_HEAD + (or PyObject_VAR_HEAD). + In the same way, any sub-type must have a C-structure that begins with + exactly the same memory layout as the parent type (or all of the parent + types in the case of multiple-inheritance). + The reason for this is that Python may attempt to access a member of the + sub-type structure as if it had the parent structure ( +\emph on +i.e. + +\emph default + it will cast a given pointer to a pointer to the parent structure and then + dereference one of it's members). + If the memory layouts are not compatible, then this attempt will cause + unpredictable behavior (eventually leading to a memory violation and program + crash). + +\end_layout + +\begin_layout Standard +One of the elements in PyObject_HEAD is a pointer to a type-object structure. + A new Python type is created by creating a new type-object structure and + populating it with functions and pointers to describe the desired behavior + of the type. + Typically, a new C-structure is also created to contain the instance-specific + information needed for each object of the type as well. + For example, &PyArray_Type is a pointer to the type-object table for the + ndarray while a PyArrayObject* variable is a pointer to a particular instance + of an ndarray (one of the members of the ndarray structure is, in turn, + a pointer to the type-object table &PyArray_Type). + Finally +\series bold +PyType_Ready +\series default +(<pointer_to_type_object>) must be called for every new Python type. + +\end_layout + +\begin_layout Subsection +Creating sub-types +\end_layout + +\begin_layout Standard +To create a sub-type, a similar proceedure must be followed except only + behaviors that are different require new entries in the type-object structure. + All other entires can be NULL and will be filled in by +\series bold +PyType_Ready +\series default + with appropriate functions from the parent type(s). + In particular, to create a sub-type in C follow these steps: +\end_layout + +\begin_layout Enumerate +If needed create a new C-structure to handle each instance of your type. + A typical C-structure would be +\end_layout + +\begin_deeper +\begin_layout LyX-Code +typedef _new_struct { +\newline + PyArrayObject base; +\newline + /* new things here */ +\newline +} NewArrayO +bject; +\end_layout + +\begin_layout Standard +Notice that the full PyArrayObject is used as the first entry in order to + ensure that the binary layout of instances of the new type is identical + to the PyArrayObject. + +\end_layout + +\end_deeper +\begin_layout Enumerate +Fill in a new Python type-object structure with pointers to new functions + that will over-ride the default behavior while leaving any function that + should remain the same unfilled (or NULL). + The tp_name element should be different. +\end_layout + +\begin_layout Enumerate +Fill in the tp_base member of the new type-object structure with a pointer + to the (main) parent type object. + For multiple-inheritance, also fill in the tp_bases member with a tuple + containing all of the parent objects in the order they should be used to + define inheritance. + Remember, all parent-types must have the same C-structure for multiple + inheritance to work properly. + +\end_layout + +\begin_layout Enumerate +Call +\series bold +PyType_Ready +\series default +(<pointer_to_new_type>). + If this function returns a negative number, a failure occurred and the + type is not initialized. + Otherwise, the type is ready to be used. + It is generally important to place a reference to the new type into the + module dictionary so it can be accessed from Python. + +\end_layout + +\begin_layout Standard +More information on creating sub-types in C can be learned by reading PEP + 253 (available at http://www.python.org/dev/peps/pep-0253). +\end_layout + +\begin_layout Subsection +Specific features of ndarray sub-typing +\end_layout + +\begin_layout Standard +Some special methods and attributes are used by arrays in order to facilitate + the interoperation of sub-types with the base ndarray type. + +\end_layout + +\begin_layout Subsubsection +The __array_finalize__ method +\end_layout + +\begin_layout Standard +Several array-creation functions of the ndarray allow specification of a + particular sub-type to be created. + This allows sub-types to be handled seamlessly in many routines. + When a sub-type is created in such a fashion, however, neither the __new__ + method nor the __init__ method gets called. + Instead, the sub-type is allocated and the appropriate instance-structure + members are filled in. + Finally, the +\series bold +__array_finalize__ +\series default + attribute is looked-up in the object dictionary. + If it is present and not None, then it can be either a CObject containing + a pointer to a +\series bold +PyArray_FinalizeFunc +\series default + or it can be a method taking a single argument (which could be None). + +\end_layout + +\begin_layout Standard +If the +\series bold +__array_finalize__ +\series default + attribute is a CObject, then the pointer must be a pointer to a function + with the signature: +\end_layout + +\begin_layout Description +\InsetSpace ~ + (int) (PyArrayObject *, PyObject *) +\end_layout + +\begin_layout Standard +The first argument is the newly created sub-type. + The second argument (if not NULL) is the +\begin_inset Quotes eld +\end_inset + +parent +\begin_inset Quotes erd +\end_inset + + array (if the array was created using slicing or some other operation where + a clearly-distinguishable parent is present). + This routine can do anything it wants to. + It should return a -1 on error and 0 otherwise. + +\end_layout + +\begin_layout Standard +If the +\series bold +__array_finalize__ +\series default + attribute is not None nor a CObject, then it must be a Python method that + takes the parent array as an argument (which could be None if there is + no parent), and returns nothing. + Errors in this method will be caught and handled. + +\end_layout + +\begin_layout Subsubsection +The __array_priority__ attribute +\end_layout + +\begin_layout Standard +This attribute allows simple but flexible determination of which sub-type + should be considered +\begin_inset Quotes eld +\end_inset + +primary +\begin_inset Quotes erd +\end_inset + + when an operation involving two or more sub-types arises. + In operations where different sub-types are being used, the sub-type with + the largest +\series bold +__array_priority__ +\series default + attribute will determine the sub-type of the output(s). + If two sub-types have the same +\series bold +__array_prioirty__ +\series default + then the sub-type of the first argument determines the output. + The default +\series bold +__array_priority__ +\series default + attribute returns a value of 0.0 for the base ndarray type and 1.0 for a + sub-type. + This attribute can also be defined by objects that are not sub-types of + the ndarray and can be used to determine which +\series bold +__array_wrap__ +\series default + method should be called for the return output. + +\end_layout + +\begin_layout Subsubsection +The __array_wrap__ method +\end_layout + +\begin_layout Standard +Any class or type can define this method which should take an ndarray argument + and return an instance of the type. + It can be seen as the opposite of the +\series bold +__array__ +\series default + method. + This method is used by the ufuncs (and other NumPy functions) to allow + other objects to pass through. + For Python >2.4, it can also be used to write a decorator that converts + a function that works only with ndarrays to one that works with any type + with +\series bold +__array__ +\series default + and +\series bold +__array_wrap__ +\series default + methods. + +\begin_inset LatexCommand index +name "ndarray!subtyping|)" + +\end_inset + + +\end_layout + +\begin_layout Chapter +Using Python as glue +\end_layout + +\begin_layout Quotation +There is no conversation more boring than the one where everybody agrees. +\end_layout + +\begin_layout Right Address +--- +\emph on +Michel de Montaigne +\end_layout + +\begin_layout Quotation +Duct tape is like the force. + It has a light side, and a dark side, and it holds the universe together. +\end_layout + +\begin_layout Right Address +--- +\emph on +Carl Zwanzig +\end_layout + +\begin_layout Standard +Many people like to say that Python is a fantastic glue language. + Hopefully, this Chapter will convince you that this is true. + The first adopters of Python for science were typically people who used + it to glue together large applicaton codes running on super-computers. + Not only was it much nicer to code in Python than in a shell script or + Perl, in addition, the ability to easily extend Python made it relatively + easy to create new classes and types specifically adapted to the problems + being solved. + From the interactions of these early contributors, Numeric emerged as an + array-like object that could be used to pass data between these applications. +\end_layout + +\begin_layout Standard +As Numeric has matured and developed into NumPy, people have been able to + write more code directly in NumPy. + Often this code is fast-enough for production use, but there are still + times that there is a need to access compiled code. + Either to get that last bit of efficiency out of the algorithm or to make + it easier to access widely-available codes written in C/C++ or Fortran. + +\end_layout + +\begin_layout Standard +This chapter will review many of the tools that are available for the purpose + of accessing code written in other compiled languages. + There are many resources available for learning to call other compiled + libraries from Python and the purpose of this Chapter is not to make you + an expert. + The main goal is to make you aware of some of the possibilities so that + you will know what to +\begin_inset Quotes eld +\end_inset + +Google +\begin_inset Quotes erd +\end_inset + + in order to learn more. + +\end_layout + +\begin_layout Standard +The http://www.scipy.org website also contains a great deal of useful information + about many of these tools. + For example, there is a nice description of using several of the tools + explained in this chapter at http://www.scipy.org/PerformancePython. + This link provides several ways to solve the same problem showing how to + use and connect with compiled code to get the best performance. + In the process you can get a taste for several of the approaches that will + be discussed in this chapter. + +\end_layout + +\begin_layout Section +Calling other compiled libraries from Python +\end_layout + +\begin_layout Standard +While Python is a great language and a pleasure to code in, its dynamic + nature results in overhead that can cause some code ( +\emph on +i.e. + +\emph default + raw computations inside of for loops) to be up 10-100 times slower than + equivalent code written in a static compiled language. + In addition, it can cause memory usage to be larger than necessary as temporary + arrays are created and destroyed during computation. + For many types of computing needs the extra slow-down and memory consumption + can often not be spared (at least for time- or memory-critical portions + of your code). + Therefore one of the most common needs is to call out from Python code + to a fast, machine-code routine (e.g. + compiled using C/C++ or Fortran). + The fact that this is relatively easy to do is a big reason why Python + is such an excellent high-level language for scientific and engineering + programming. + +\end_layout + +\begin_layout Standard +Their are two basic approaches to calling compiled code: writing an extension + module that is then imported to Python using the import command, or calling + a shared-library subroutine directly from Python using the ctypes module + (included in the standard distribution with Python 2.5). + The first method is the most common (but with the inclusion of ctypes into + Python 2.5 this status may change). +\end_layout + +\begin_layout Warning +Calling C-code from Python can result in Python crashes if you are not careful. + None of the approaches in this chapter are immune. + You have to know something about the way data is handled by both NumPy + and by the third-party library being used. + +\end_layout + +\begin_layout Section +Hand-generated wrappers +\end_layout + +\begin_layout Standard +Extension modules were discussed in Chapter +\begin_inset LatexCommand ref +reference "sec:Writing-an-extension" + +\end_inset + +. + The most basic way to interface with compiled code is to write an extension + module and construct a module method that calls the compiled code. + For improved readability, your method should take advantage of the PyArg_ParseT +uple call to convert between Python objects and C data-types. + For standard C data-types there is probably already a built-in converter. + For others you may need to write your own converter and use the +\begin_inset Quotes eld +\end_inset + +O& +\begin_inset Quotes erd +\end_inset + + format string which allows you to specify a function that will be used + to perform the conversion from the Python object to whatever C-structures + are needed. + +\end_layout + +\begin_layout Standard +Once the conversions to the appropriate C-structures and C data-types have + been performed, the next step in the wrapper is to call the underlying + function. + This is straightforward if the underlying function is in C or C++. + However, in order to call Fortran code you must be familiar with how Fortran + subroutines are called from C/C++ using your compiler and platform. + This can vary somewhat platforms and compilers (which is another reason + f2py makes life much simpler for interfacing Fortran code) but generally + involves underscore mangling of the name and the fact that all variables + are passed by reference (i.e. + all arguments are pointers). + +\end_layout + +\begin_layout Standard +The advantage of the hand-generated wrapper is that you have complete control + over how the C-library gets used and called which can lead to a lean and + tight interface with minimal over-head. + The disadvantage is that you have to write, debug, and maintain C-code, + although most of it can be adapted using the time-honored technique of + +\begin_inset Quotes eld +\end_inset + +cutting-pasting-and-modifying +\begin_inset Quotes erd +\end_inset + + from other extension modules. + Because, the procedure of calling out to additional C-code is fairly regimented +, code-generation procedures have been developed to make this process easier. + One of these code-generation techniques is distributed with NumPy and allows + easy integration with Fortran and (simple) C code. + This package, f2py, will be covered briefly in the next session. + +\end_layout + +\begin_layout Section +f2py +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "f2py|(" + +\end_inset + +F2py allows you to automatically construct an extension module that interfaces + to routines in Fortran 77/90/95 code. + It has the ability to parse Fortran 77/90/95 code and automatically generate + Python signatures for the subroutines it encounters, or you can guide how + the subroutine interfaces with Python by constructing an interface-defintion-fi +le (or modifying the f2py-produced one). + +\end_layout + +\begin_layout Subsection +Creating source for a basic extension module +\end_layout + +\begin_layout Standard +Probably the easiest way to introduce f2py is to offer a simple example. + Here is one of the subroutines contained in a file named add.f +\end_layout + +\begin_layout LyX-Code +C +\newline + SUBROUTINE ZADD(A,B,C,N) +\newline +C +\newline + DOUBLE COMPLEX A(*) +\newline + DOUBLE COMPLEX + B(*) +\newline + DOUBLE COMPLEX C(*) +\newline + INTEGER N +\newline + DO 20 J = 1, N +\newline + + C(J) = A(J)+B(J) +\newline + 20 CONTINUE +\newline + END +\end_layout + +\begin_layout Standard +This routine simply adds the elements in two contiguous arrays and places + the result in a third. + The memory for all three arrays must be provided by the calling routine. + A very basic interface to this routine can be automatically generated by + f2py: +\end_layout + +\begin_layout LyX-Code +f2py -m add add.f +\end_layout + +\begin_layout Standard +You should be able to run this command assuming your search-path is set-up + properly. + This command will produce an extension module named addmodule.c in the current + directory. + This extension module can now be compiled and used from Python just like + any other extension module. + +\end_layout + +\begin_layout Subsection +Creating a compiled extension module +\end_layout + +\begin_layout Standard +You can also get f2py to compile add.f and also compile its produced extension + module leaving only a shared-library extension file that can be imported + from Python: +\end_layout + +\begin_layout LyX-Code +f2py -c -m add add.f +\end_layout + +\begin_layout Standard +This command leaves a file named add.<ext> in the current directory (where + <ext> is the appropriate extension for a python extension module on your + platform --- so, pyd, +\emph on +etc. +\emph default +). + This module may then be imported from Python. + It will contain a method for each subroutin in add (zadd, cadd, dadd, sadd). + The docstring of each method contains information about how the module + method may be called: +\end_layout + +\begin_layout LyX-Code +>>> import add +\newline +>>> print add.zadd.__doc__ +\newline +zadd - Function signature: +\newline + zadd(a,b,c,n) +\newline + +Required arguments: +\newline + a : input rank-1 array('D') with bounds (*) +\newline + b : input + rank-1 array('D') with bounds (*) +\newline + c : input rank-1 array('D') with bounds + (*) +\newline + n : input int +\end_layout + +\begin_layout Subsection +Improving the basic interface +\end_layout + +\begin_layout Standard +The default interface is a very literal translation of the fortran code + into Python. + The Fortran array arguments must now be NumPy arrays and the integer argument + should be an integer. + The interface will attempt to convert all arguments to their required types + (and shapes) and issue an error if unsuccessful. + However, because it knows nothing about the semantics of the arguments + (such that C is an output and n should really match the array sizes), it + is possible to abuse this function in ways that can cause Python to crash. + For example +\end_layout + +\begin_layout LyX-Code +>>> add.zadd([1,2,3],[1,2],[3,4],1000) +\end_layout + +\begin_layout Standard +will cause a program crash on most systems. + Under the covers, the lists are being converted to proper arrays but then + the underlying add loop is told to cycle way beyond the borders of the + allocated memory. + +\end_layout + +\begin_layout Standard +In order to improve the interface, directives should be provided. + This is accomplished by constructing an interface definition file. + It is usually best to start from the interface file that f2py can produce + (where it gets its default behavior from). + To get f2py to generate the interface file use the -h option: +\end_layout + +\begin_layout LyX-Code +f2py -h add.pyf -m add add.f +\end_layout + +\begin_layout Standard +This command leaves the file add.pyf in the current directory. + The section of this file corresponding to zadd is: +\end_layout + +\begin_layout LyX-Code +subroutine zadd(a,b,c,n) ! in :add:add.f +\newline + double complex dimension(*) :: + a +\newline + double complex dimension(*) :: b +\newline + double complex dimension(*) :: + c +\newline + integer :: n +\newline +end subroutine zadd +\end_layout + +\begin_layout Standard +By placing intent directives and checking code, the interface can be cleaned + up quite a bit until the Python module method is both easier to use and + more robust. + +\end_layout + +\begin_layout LyX-Code +subroutine zadd(a,b,c,n) ! in :add:add.f +\newline + double complex dimension(n) :: + a +\newline + double complex dimension(n) :: b +\newline + double complex intent(out),dimension(n +) :: c +\newline + integer intent(hide),depend(a) :: n=len(a) +\newline +end subroutine zadd +\end_layout + +\begin_layout Standard +The intent directive, intent(out) is used to tell f2py that +\family typewriter +c +\family default + is an output variable and should be created by the interface before being + passed to the underlying code. + The intent(hide) directive tells f2py to not allow the user to specify + the variable, +\family typewriter +n +\family default +, but instead to get it from the size of +\family typewriter +a +\family default +. + The depend( +\family typewriter +a +\family default +) directive is necessary to tell f2py that the value of n depends on the + input a (so that it won't try to create the variable n until the variable + a is created). + +\end_layout + +\begin_layout Standard +The new interface has docstring: +\end_layout + +\begin_layout LyX-Code +>>> print add.zadd.__doc__ +\newline +zadd - Function signature: +\newline + c = zadd(a,b) +\newline +Required + arguments: +\newline + a : input rank-1 array('D') with bounds (n) +\newline + b : input rank-1 + array('D') with bounds (n) +\newline +Return objects: +\newline + c : rank-1 array('D') with + bounds (n) +\end_layout + +\begin_layout Standard +Now, the function can be called in a much more robust way: +\end_layout + +\begin_layout LyX-Code +>>> add.zadd([1,2,3],[4,5,6]) +\newline +array([ 5.+0.j, 7.+0.j, 9.+0.j]) +\end_layout + +\begin_layout Standard +Notice the automatic conversion to the correct format that occurred. + +\end_layout + +\begin_layout Subsection +Inserting directives in Fortran source +\end_layout + +\begin_layout Standard +The nice interface can also be generated automatically by placing the variable + directives as special comments in the original fortran code. + Thus, if I modify the source code to contain: +\end_layout + +\begin_layout LyX-Code +C +\newline + SUBROUTINE ZADD(A,B,C,N) +\newline +C +\newline +CF2PY INTENT(OUT) :: C +\newline +CF2PY INTENT(HIDE) + :: N +\newline +CF2PY DOUBLE COMPLEX :: A(N) +\newline +CF2PY DOUBLE COMPLEX :: B(N) +\newline +CF2PY DOUBLE + COMPLEX :: C(N) +\newline + DOUBLE COMPLEX A(*) +\newline + DOUBLE COMPLEX B(*) +\newline + + DOUBLE COMPLEX C(*) +\newline + INTEGER N +\newline + DO 20 J = 1, N +\newline + C(J) = A(J) + + B(J) +\newline + 20 CONTINUE +\newline + END +\end_layout + +\begin_layout Standard +Then, I can compile the extension module using +\end_layout + +\begin_layout LyX-Code +f2py -c -m add add.f +\end_layout + +\begin_layout Standard +The resulting signature for the function add.zadd is exactly the same one + that was created previously. + If the original source code had contained A(N) instead of A(*) and so forth + with B and C, then I could obtain (nearly) the same interface simply by + placing the INTENT(OUT) :: C comment line in the source code. + The only difference is that N would be an optional input that would default + to the length of A. + +\end_layout + +\begin_layout Subsection +A filtering example +\end_layout + +\begin_layout Standard +For comparison with the other methods to be discussed. + Here is another example of a function that filters a two-dimensional array + of double precision floating-point numbers using a fixed averaging filter. + The advantage of using Fortran to index into multi-dimensional arrays should + be clear from this example. + +\end_layout + +\begin_layout LyX-Code + SUBROUTINE DFILTER2D(A,B,M,N) +\newline +C +\newline + DOUBLE PRECISION A(M,N) +\newline + DOUBLE + PRECISION B(M,N) +\newline + INTEGER N, M +\newline +CF2PY INTENT(OUT) :: B +\newline +CF2PY INTENT(HIDE) + :: N +\newline +CF2PY INTENT(HIDE) :: M +\newline + DO 20 I = 2,M-1 +\newline + DO 40 J=2,N-1 +\newline + + B(I,J) = A(I,J) + +\newline + $ (A(I-1,J)+A(I+1,J) + +\newline + + $ A(I,J-1)+A(I,J+1) )*0.5D0 + +\newline + $ (A(I-1,J-1) + A(I-1,J+1 +) + +\newline + $ A(I+1,J-1) + A(I+1,J+1))*0.25D0 +\newline + 40 CONTINUE +\newline + 20 + CONTINUE +\newline + END +\end_layout + +\begin_layout Standard +This code can be compiled and linked into an extension module named filter + using +\end_layout + +\begin_layout LyX-Code +f2py -c -m filter filter.f +\end_layout + +\begin_layout Standard +This will produce an extension module named filter.so in the current directory + with a method named dfilter2d that returns a filtered version of the input. + +\end_layout + +\begin_layout Subsection +Calling f2py from Python +\end_layout + +\begin_layout Standard +The f2py program is written in Python and can be run from inside your module. + This provides a facility that is somewhat similar to the use of weave.ext_tools + described below. + An example of the final interface executed using Python code is +\end_layout + +\begin_layout LyX-Code +import numpy.f2py as f2py +\end_layout + +\begin_layout LyX-Code +fid = open('add.f') +\end_layout + +\begin_layout LyX-Code +source = fid.read() +\end_layout + +\begin_layout LyX-Code +fid.close() +\end_layout + +\begin_layout LyX-Code +f2py.compile(source, modulename='add') +\end_layout + +\begin_layout LyX-Code +import add +\end_layout + +\begin_layout Standard +The source string can be any valid Fortran code. + If you want to save the extension-module source code then a suitable file-name + can be provided by the source_fn keyword to the compile function. + +\end_layout + +\begin_layout Subsection +Automatic extension module generation +\end_layout + +\begin_layout Standard +If you want to distribute your f2py extension module, then you only need + to include the .pyf file and the Fortran code. + The distutils extensions in NumPy allow you to define an extension module + entirely in terms of this interface file. + A valid setup.py file allowing distribution of the add.f module (as part + of the package f2py_examples so that it would be loaded as f2py_examples.add) + is +\end_layout + +\begin_layout LyX-Code +def configuration(parent_package='', top_path=None) +\newline + from numpy.distutils.misc_u +til import Configuration +\newline + config = Configuration('f2py_examples',parent_packag +e, top_path) +\newline + config.add_extension('add', sources=['add.pyf','add.f']) +\newline + + return config +\newline + +\newline +if __name__ == '__main__': +\newline + from numpy.distutils.core import + setup +\newline + setup(**configuration(top_path='').todict()) +\end_layout + +\begin_layout Standard +Installation of the new package is easy using +\end_layout + +\begin_layout LyX-Code +python setup.py install +\end_layout + +\begin_layout Standard +assuming you have the proper permissions to write to the main site-packages + directory for the version of Python you are using. + For the resulting package to work, you need to create a file named __init__.py + (in the same directory as add.pyf). + Notice the extension module is defined entirely in terms of the +\begin_inset Quotes eld +\end_inset + +add.pyf +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +add.f +\begin_inset Quotes erd +\end_inset + + files. + The conversion of the .pyf file to a .c file is handled by numpy.disutils. + +\end_layout + +\begin_layout Subsection +Conclusion +\end_layout + +\begin_layout Standard +The interface definition file (.pyf) is how you can fine-tune the interface + between Python and Fortran. + There is decent documentation for f2py found in the numpy/f2py/docs directory + where-ever NumPy is installed on your system (usually under site-packages). + There is also more information on using f2py (including how to use it to + wrap C codes) at http://www.scipy.org/Cookbook under the +\begin_inset Quotes eld +\end_inset + +Using NumPy with Other Languages +\begin_inset Quotes erd +\end_inset + + heading. + +\end_layout + +\begin_layout Standard +The f2py method of linking compiled code is currently the most sophisticated + and integrated approach. + It allows clean separation of Python with compiled code while still allowing + for separate distribution of the extension module. + The only draw-back is that it requires the existence of a Fortran compiler + in order for a user to install the code. + However, with the existence of the free-compilers g77, gfortran, and g95, + as well as high-quality commerical compilers, this restriction is not particula +rly onerous. + In my opinion, Fortran is still the easiest way to write fast and clear + code for scientific computing. + It handles complex numbers, and multi-dimensional indexing in the most + straightforward way. + Be aware, however, that some Fortran compilers will not be able to optimize + code as well as good hand-written C-code. + +\begin_inset LatexCommand index +name "f2py|)" + +\end_inset + + +\end_layout + +\begin_layout Section +weave +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "weave|(" + +\end_inset + +Weave is a scipy package that can be used to automate the process of extending + Python with C/C++ code. + It can be used to speed up evaluation of an array expression that would + otherwise create temporary variables, to directly +\begin_inset Quotes eld +\end_inset + +inline +\begin_inset Quotes erd +\end_inset + + C/C++ code into Python, or to create a fully-named extension module. + You must either install scipy or get the weave package separately and install + it using the standard python setup.py install. + You must also have a C/C++-compiler installed and useable by Python distutils + in order to use weave. +\end_layout + +\begin_layout Standard +Somewhat dated, but still useful documentation for weave can be found at + the link http://www.scipy/Weave. + There are also many examples found in the examples directory which is installed + under the weave directory in the place where weave is installed on your + system. +\end_layout + +\begin_layout Subsection +Speed up code involving arrays (also see scipy.numexpr) +\end_layout + +\begin_layout Standard +This is the easiest way to use weave and requires minimal changes to your + Python code. + It involves placing quotes around the expression of interest and calling + weave.blitz. + Weave will parse the code and generate C++ code using Blitz C++ arrays. + It will then compile the code and catalog the shared library so that the + next time this exact string is asked for (and the array types are the same), + the already-compiled shared library will be loaded and used. + Because Blitz makes extensive use of C++ templating, it can take a long + time to compile the first time. + After that, however, the code should evaluate more quickly than the equivalent + NumPy expression. + This is especially true if your array sizes are large and the expression + would require NumPy to create several temporaries. + Only expressions involving basic arithmetic operations and basic array + slicing can be converted to Blitz C++ code. + +\end_layout + +\begin_layout Standard +For example, consider the expression +\end_layout + +\begin_layout LyX-Code +d = 4*a + 5*a*b + 6*b*c +\end_layout + +\begin_layout Standard +where a, b, and c are all arrays of the same type and shape. + When the data-type is double-precision and the size is 1000x1000, this + expression takes about 0.5 seconds to compute on an 1.1Ghz AMD Athlon machine. + When this expression is executed instead using blitz: +\end_layout + +\begin_layout LyX-Code +d = empty(a.shape, 'd'); weave.blitz(expr) +\end_layout + +\begin_layout Standard +execution time is only about 0.20 seconds (about 0.14 seconds spent in weave + and the rest in allocating space for d). + Thus, we've sped up the code by a factor of 2 using only a simnple command + (weave.blitz). + Your mileage may vary, but factors of 2-8 speed-ups are possible with this + very simple technique. + +\end_layout + +\begin_layout Standard +If you are interested in using weave in this way, then you should also look + at scipy.numexpr which is another similar way to speed up expressions by + eliminating the need for temporary variables. + Using numexpr does not require a C/C++ compiler. + +\end_layout + +\begin_layout Subsection +Inline C-code +\end_layout + +\begin_layout Standard +Probably the most widely-used method of employing weave is to +\begin_inset Quotes eld +\end_inset + +in-line +\begin_inset Quotes erd +\end_inset + + C/C++ code into Python in order to speed up a time-critical section of + Python code. + In this method of using weave, you define a string containing useful C-code + and then pass it to the function +\series bold +weave.inline +\series default +( +\family typewriter +code_string +\family default +, +\family typewriter +variables +\family default +), where code_string is a string of valid C/C++ code and variables is a + list of variables that should be passed in from Python. + The C/C++ code should refer to the variables with the same names as they + are defined with in Python. + If weave.line should return anything the the special value return_val should + be set to whatever object should be returned. + The following example shows how to use weave on basic Python objects +\end_layout + +\begin_layout LyX-Code +code = r""" +\newline +int i; +\newline +py::tuple results(2); +\newline +for (i=0; i<a.length(); i++) { +\newline + + a[i] = i; +\newline +} +\newline +results[0] = 3.0; +\newline +results[1] = 4.0; +\newline +return_val = results; +\newline +""" + +\newline +a = [None]*10 +\newline +res = weave.inline(code,['a']) +\end_layout + +\begin_layout Standard +The C++ code shown in the code string uses the name 'a' to refer to the + Python list that is passed in. + Because the Python List is a mutable type, the elements of the list itself + are modified by the C++ code. + A set of C++ classes are used to access Python objects using simple syntax. + +\end_layout + +\begin_layout Standard +The main advantage of using C-code, however, is to speed up processing on + an array of data. + Accessing a NumPy array in C++ code using weave, depends on what kind of + type converter is chosen in going from NumPy arrays to C++ code. + The default converter creates 5 variables for the C-code for every NumPy + array passed in to weave.inline. + The following table shows these variables which can all be used in the + C++ code. + The table assumes that +\family typewriter +myvar +\family default + is the name of the array in Python with data-type <dtype> (i.e. + float64, float32, int8, etc.) +\end_layout + +\begin_layout Standard +\align center +\begin_inset Tabular +<lyxtabular version="3" rows="6" columns="3"> +<features> +<column alignment="center" valignment="top" leftline="true" width="0"> +<column alignment="center" valignment="top" leftline="true" width="0"> +<column alignment="center" valignment="top" leftline="true" rightline="true" width="0"> +<row topline="true" bottomline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Variable +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Type +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Contents +\end_layout + +\end_inset +</cell> +</row> +<row topline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +myvar +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +<dtype>* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Pointer to the first element of the array +\end_layout + +\end_inset +</cell> +</row> +<row topline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Nmyvar +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +npy_intp* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +A pointer to the dimensions array +\end_layout + +\end_inset +</cell> +</row> +<row topline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Smyvar +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +npy_intp* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +A pointer to the strides array +\end_layout + +\end_inset +</cell> +</row> +<row topline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +Dmyvar +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +int +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +The number of dimensions +\end_layout + +\end_inset +</cell> +</row> +<row topline="true" bottomline="true"> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +myvar_array +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +PyArrayObject* +\end_layout + +\end_inset +</cell> +<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> +\begin_inset Text + +\begin_layout Standard +The entire structure for the array +\end_layout + +\end_inset +</cell> +</row> +</lyxtabular> + +\end_inset + + +\end_layout + +\begin_layout Standard +The in-lined code can contain references to any of these variables as well + as to the standard macros MYVAR1(i), MYVAR2(i,j), MYVAR3(i,j,k), and MYVAR4(i,j +,k,l). + These name-based macros (they are the Python name capitalized followed + by the number of dimensions needed) will de-reference the memory for the + array at the given location with no error checking (be-sure to use the + correct macro and ensure the array is aligned and in correct byte-swap + order in order to get useful results). + The following code shows how you might use these variables and macros to + code a loop in C that computes a simple 2-d weighted averaging filter. +\end_layout + +\begin_layout LyX-Code +int i,j; +\newline +for(i=1;i<Na[0]-1;i++) { +\newline + for(j=1;j<Na[1]-1;j++) { +\newline + B2(i,j) + = A2(i,j) + (A2(i-1,j) + +\newline + A2(i+1,j)+A2(i,j-1) +\newline + + + A2(i,j+1))*0.5 +\newline + + (A2(i-1,j-1) +\newline + + + A2(i-1,j+1) +\newline + + A2(i+1,j-1) +\newline + + A2(i+1,j+1))*0.25 +\newline + + } +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout Standard +The above code doesn't have any error checking and so could fail with a + Python crash if, +\family typewriter +a +\family default + had the wrong number of dimensions, or +\family typewriter +b +\family default + did not have the same shape as +\family typewriter +a +\family default +. + However, it could be placed inside a standard Python function with the + necessary error checking to produce a robust but fast subroutine. +\end_layout + +\begin_layout Standard +One final note about weave.inline: if you have additional code you want to + include in the final extension module such as supporting function calls, + include statments, etc. + you can pass this code in as a string using the keyword support_code: +\family typewriter +weave.inline(code, variables, support_code=support) +\family default +. + If you need the extension module to link against an additional library + then you can also pass in distutils-style keyword arguments such as library_dir +s, libraries, and/or runtime_library_dirs which point to the appropriate + libraries and directories. + +\end_layout + +\begin_layout Subsection +Simplify creation of an extension module +\end_layout + +\begin_layout Standard +The inline function creates one extension module for each function to-be + inlined. + It also generates a lot of intermediate code that is duplicated for each + extension module. + If you have several related codes to execute in C, it would be better to + make them all separate functions in a single extension module with multiple + functions. + You can also use the tools weave provides to produce this larger extension + module. + In fact, the weave.inline function just uses these more general tools to + do its work. + +\end_layout + +\begin_layout Standard +The approach is to: +\end_layout + +\begin_layout Enumerate +construct a extension module object using ext_tools.ext_module( +\family typewriter +module_name +\family default +); +\end_layout + +\begin_layout Enumerate +create function objects using ext_tools.ext_function( +\family typewriter +func_name +\family default +, +\family typewriter +code +\family default +, +\family typewriter +variables +\family default +); +\end_layout + +\begin_layout Enumerate +(optional) add support code to the function using the .customize.add_support_code( +\family typewriter +support_code +\family default +) method of the function object; +\end_layout + +\begin_layout Enumerate +add the functions to the extension module object using the .add_function( +\family typewriter +func +\family default +) method; +\end_layout + +\begin_layout Enumerate +when all the functions are added, compile the extension with its .compile() + method. +\end_layout + +\begin_layout Standard +Several examples are available in the examples directory where weave is + installed on your system. + Look particularly at ramp2.py, increment_example.py and fibonacii.py +\end_layout + +\begin_layout Subsection +Conclusion +\end_layout + +\begin_layout Standard +Weave is a useful tool for quickly routines in C/C++ and linking them into + Python. + It's caching-mechanism allows for on-the-fly compilation which makes it + particularly attractive for in-house code. + Because of the requirement that the user have a C++-compiler, it can be + difficult (but not impossible) to distribute a package that uses weave + to other users who don't have a compiler installed. + Of course, weave could be used to construct an extension module which is + then distributed in the normal way +\emph on +( +\emph default +using a setup.py file). + While you can use weave to build larger extension modules with many methods, + creating methods with a variable-number of arguments is not possible. + Thus, for a more sophisticated module, you will still probably want a Python-la +yer that calls the weave-produced extension. + +\begin_inset LatexCommand index +name "weave|)" + +\end_inset + + +\end_layout + +\begin_layout Section +Pyrex +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "pyrex|(" + +\end_inset + +Pyrex is a way to write C-extension modules using Python-like syntax. + It is an interesting way to generate extension modules that is growing + in popularity, particularly among people who have rusty or non-existent + C-skills. + It does require the user to write the +\begin_inset Quotes eld +\end_inset + +interface +\begin_inset Quotes erd +\end_inset + + code and so is more time-consuming than SWIG or f2py if you are trying + to interface to a large library of code. + However, if you are writing an extension module that will include quite + a bit of your own algorithmic code, as well, then Pyrex is a good match. + A big weakness perhaps is the inability to easily and quickly access the + elements of a multidimensional array. + +\end_layout + +\begin_layout Standard +Notice that Pyrex is an extension-module generator only. + Unlike weave or f2py, it includes no automatic facility for compiling and + linking the extension module (which must be done in the usual fashion). + It does provide a modified distutils class called build_ext which lets + you build an extension module from a .pyx source. + Thus, you could write in a setup.py file +\end_layout + +\begin_layout LyX-Code +from Pyrex.Distutils import build_ext +\newline +from distutils.extension import Extension +\newline +from + distutils.core import setup +\newline + +\newline +import numpy +\newline +py_ext = Extension('mine', ['mine.pyx'], +\newline + + include_dirs=[numpy.get_include()]) +\newline + +\newline +setup(name='mine', description='Nothi +ng', +\newline + ext_modules=[pyx_ext], +\newline + cmdclass = {'build_ext':build_ext}) +\end_layout + +\begin_layout Standard +Adding the NumPy include directory is, of course, only necessary if you + are using NumPy arrays in the extension module (which is what I assume + you are using Pyrex for). + The distutils extensions in NumPy also include support for automatically + producing the extension-module and linking it from a +\family typewriter +.pyx +\family default + file. + It works so that if the user does not have Pyrex installed, then it looks + for a file with the same file-name but a +\family typewriter +.c +\family default + extension which it then uses instead of trying to produce the +\family typewriter +.c +\family default + file again. + +\end_layout + +\begin_layout Standard +Pyrex does not natively understand NumPy arrays. + However, it is not difficult to include information that lets Pyrex deal + with them usefully. + In fact, the numpy.random.mtrand module was written using Pyrex so an example + of Pyrex usage is already included in the NumPy source distribution. + That experience led to the creation of a standard c_numpy.pxd file that + you can use to simplify interacting with NumPy array objects in a Pyrex-written + extension. + The file may not be complete (it wasn't at the time of this writing). + If you have additions you'd like to contribute, please send them. + The file is located in the .../site-packages/numpy/doc/pyrex directory where + you have Python installed. + There is also an example in that directory of using Pyrex to construct + a simple extension module. + It shows that Pyrex looks a lot like Python but also contains some new + syntax that is necessary in order to get C-like speed. + +\end_layout + +\begin_layout Standard +If you just use Pyrex to compile a standard Python module, then you will + get a C-extension module that runs either as fast or, possibly, more slowly + than the equivalent Python module. + Speed increases are possible only when you use cdef to statically define + C variables and use a special construct to create for loops: +\end_layout + +\begin_layout LyX-Code +cdef int i +\newline +for i from start <= i < stop +\end_layout + +\begin_layout Standard +Let's look at two examples we've seen before to see how they might be implemente +d using Pyrex. + These examples were compiled into extension modules using Pyrex-0.9.3.1. +\end_layout + +\begin_layout Subsection +Pyrex-add +\end_layout + +\begin_layout Standard +Here is part of a Pyrex-file I named add.pyx which implements the add functions + we previously implemented using f2py: +\end_layout + +\begin_layout LyX-Code +cimport c_numpy +\newline +from c_numpy cimport import_array, ndarray, npy_intp, npy_cdouble +, +\backslash + +\newline + npy_cfloat, NPY_DOUBLE, NPY_CDOUBLE, NPY_FLOAT, +\backslash + +\newline + NPY_CFLOAT +\newline + +\newline +#We need to initialize NumPy +\newline +import_array() +\newline + +\newline +def zadd(object + ao, object bo): +\newline + cdef ndarray c, a, b +\newline + cdef npy_intp i +\newline + a = c_numpy.PyArra +y_ContiguousFromAny(ao, +\newline + NPY_CDOUBLE, 1, 1) +\newline + b = c_numpy.PyArr +ay_ContiguousFromAny(bo, +\newline + NPY_CDOUBLE, 1, 1) +\newline + c = c_numpy.PyAr +ray_SimpleNew(a.nd, a.dimensions, +\newline + a.descr.type_num) +\newline + for i + from 0 <= i < a.dimensions[0]: +\newline + (<npy_cdouble *>c.data)[i].real = +\backslash + +\newline + (<npy_cdouble *>a.data)[i].real + +\backslash + +\newline + (<npy_cdouble *>b.data)[i].real +\newline + (<npy_cdouble *>c.data)[i].imag + = +\backslash + +\newline + (<npy_cdouble *>a.data)[i].imag + +\backslash + +\newline + (<npy_cdouble *>b.data)[i].imag +\newline + return c +\end_layout + +\begin_layout Standard +This module shows use of the +\family typewriter +cimport +\family default + statement to load the definitions from the c_numpy.pxd file. + As shown, both versions of the import statement are supported. + It also shows use of the NumPy C-API to construct NumPy arrays from arbitrary + input objects. + The array c is created using PyArray_SimpleNew. + Then the c-array is filled by addition. + Casting to a particiular data-type is accomplished using <cast *>. + Pointers are de-referenced with bracket notation and members of structures + are accessed using '.' notation even if the object is techinically a pointer + to a structure. + The use of the special for loop construct ensures that the underlying code + will have a similar C-loop so the addition calculation will proceed quickly. + Notice that we have not checked for NULL after calling to the C-API --- + a cardinal sin when writing C-code. + For routines that return Python objects, Pyrex inserts the checks for NULL + into the C-code for you and returns with failure if need be. + There is also a way to get Pyrex to automatically check for exceptions + when you call functions that don't return Python objects. + See the documentation of Pyrex for details. + +\end_layout + +\begin_layout Subsection +Pyrex-filter +\end_layout + +\begin_layout Standard +The two-dimensional example we created using weave is a bit uglierto implement + in Pyrex because two-dimensional indexing using Pyrex is not as simple. + But, it is straightforward (and possibly faster because of pre-computed + indices). + Here is the Pyrex-file I named image.pyx. +\end_layout + +\begin_layout LyX-Code +cimport c_numpy +\newline +from c_numpy cimport import_array, ndarray, npy_intp, +\backslash + +\newline + NPY_DOUBLE, NPY_CDOUBLE, +\backslash + +\newline + NPY_FLOAT, NPY_CFLOAT, NPY_ALIGNED +\backslash + +\newline + +\newline +#We need to initialize NumPy +\newline +import_array() +\newline +def filter(object ao): +\newline + cdef + ndarray a, b +\newline + cdef npy_intp i, j, M, N, oS +\newline + cdef npy_intp r,rm1,rp1,c,cm1,c +p1 +\newline + cdef double value +\newline + # Require an ALIGNED array +\newline + # (but not necessarily + contiguous) +\newline + # We will use strides to access the elements. +\newline + a = c_numpy.PyAr +ray_FROMANY(ao, NPY_DOUBLE, +\backslash + +\newline + 2, 2, NPY_ALIGNED) +\newline + b = c_numpy.PyArray_SimpleNew(a.nd,a.dimensio +ns, +\backslash + +\newline + a.descr.type_num) +\newline + M = a.dimensions[0] +\newline + + N = a.dimensions[1] +\newline + S0 = a.strides[0] +\newline + S1 = a.strides[1] +\newline + for i + from 1 <= i < M-1: +\newline + r = i*S0 +\newline + rm1 = r-S0 +\newline + rp1 = r+S0 +\newline + + oS = i*N +\newline + for j from 1 <= j < N-1: +\newline + c = j*S1 +\newline + + cm1 = c-S1 +\newline + cp1 = c+S1 +\newline + (<double *>b.data)[oS+j] + = +\backslash + +\newline + (<double *>(a.data+r+c))[0] + +\backslash + +\newline + ((<double *>(a.data+rm1+c))[0] + +\backslash + +\newline + (<double *>(a.data+rp1+c))[0] + +\backslash + +\newline + (<double *>(a.data+r+cm1))[0] + +\backslash + +\newline + (<double *>(a.data+r+cp1))[0])*0.5 + +\backslash + +\newline + ((<double *>(a.data+rm1+cm1))[0] + +\backslash + +\newline + (<double *>(a.data+rp1+cm1))[0] + +\backslash + +\newline + (<double *>(a.data+rp1+cp1))[0] + +\backslash + +\newline + (<double *>(a.data+rm1+cp1))[0])*0.25 +\newline + return b +\end_layout + +\begin_layout Standard +This 2-d averaging filter runs quickly because the loop is in C and the + pointer computations are done only as needed. + However, it is not particularly easy to understand what is happening. + A 2-d image, +\family typewriter +in +\family default +, can be filtered using this code very quickly using +\end_layout + +\begin_layout LyX-Code +import image +\end_layout + +\begin_layout LyX-Code +out = image.filter(in) +\end_layout + +\begin_layout Subsection +Conclusion +\end_layout + +\begin_layout Standard +There are several disadvantages of using Pyrex: +\end_layout + +\begin_layout Enumerate +The syntax for Pyrex can get a bit bulky, and it can be confusing at first + to understand what kind of objects you are getting and how to interface + them with C-like constructs. + +\end_layout + +\begin_layout Enumerate +Inappropriate Pyrex syntax or incorrect calls to C-code or type-mismatches + can result in failures such as +\end_layout + +\begin_deeper +\begin_layout Enumerate +Pyrex failing to generate the extension module source code, +\end_layout + +\begin_layout Enumerate +Compiler failure while generating the extension module binary due to incorrect + C syntax, +\end_layout + +\begin_layout Enumerate +Python failure when trying to use the module. + +\end_layout + +\end_deeper +\begin_layout Enumerate +It is easy to lose a clean separation between Python and C which makes re-using + your C-code for other non-Python-related projects more difficult. +\end_layout + +\begin_layout Enumerate +Multi-dimensional arrays are +\begin_inset Quotes eld +\end_inset + +bulky +\begin_inset Quotes erd +\end_inset + + to index (appropriate macros may be able to fix this). + +\end_layout + +\begin_layout Enumerate +The C-code generated by Prex is hard to read and modify (and typically compiles + with annoying but harmless warnings). + +\end_layout + +\begin_layout Standard +Writing a good Pyrex extension module still takes a bit of effort because + not only does it require (a little) familiarity with C, but also with Pyrex's + brand of Python-mixed-with C. + One big advantage of Pyrex-generated extension modules is that they are + easy to distribute using distutils. + In summary, Pyrex is a very capable tool for either gluing C-code or generating + an extension module quickly and should not be over-looked. + It is especially useful for people that can't or won't write C-code or + Fortran code. + But, if you are already able to write simple subroutines in C or Fortran, + then I would use one of the other approaches such as f2py (for Fortran), + ctypes (for C shared-libraries), or weave (for inline C-code). +\begin_inset LatexCommand index +name "pyrex|)" + +\end_inset + + +\end_layout + +\begin_layout Section +ctypes +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ctypes|(" + +\end_inset + +Ctypes is a python extension module (downloaded separately for Python <2.5 + and included with Python 2.5) that allows you to call an arbitrary function + in a shared library directly from Python. + This approach allows you to interface with C-code directly from Python. + This opens up an enormous number of libraries for use from Python. + The drawback, however, is that coding mistakes can lead to ugly program + crashes very easily (just as can happen in C) because there is little type + or bounds checking done on the parameters. + This is especially true when array data is passed in as a pointer to a + raw memory location. + The responsibility is then on you that the subroutine will not access memory + outside the actual array area. + But, if you don't mind living a little dangerously ctypes can be an effective + tool for quickly taking advantage of a large shared library (or writing + extended functionality in your own shared library). +\end_layout + +\begin_layout Standard +Because the ctypes approach exposes a raw interface to the compiled code + it is not always tolerant of user mistakes. + Robust use of the ctypes module typically involves an additional layer + of Python code in order to check the data types and array bounds of objects + passed to the underlying subroutine. + This additional layer of checking (not to mention the conversion from ctypes + objects to C-data-types that ctypes itself performs), will make the interface + slower than a hand-written extension-module interface. + However, this overhead should be neglible if the C-routine being called + is doing any significant amount of work. + If you are a great Python programmer with weak C-skills, ctypes is an easy + way to write a useful interface to a (shared) library of compiled code. + +\end_layout + +\begin_layout Standard +To use c-types you must +\end_layout + +\begin_layout Enumerate +Have a shared library. +\end_layout + +\begin_layout Enumerate +Load the shared library. +\end_layout + +\begin_layout Enumerate +Convert the python objects to ctypes-understood arguments. +\end_layout + +\begin_layout Enumerate +Call the function from the library with the ctypes arguments. +\end_layout + +\begin_layout Subsection +Having a shared library +\end_layout + +\begin_layout Standard +There are several requirements for a shared library that can be used with + c-types that are platform specific. + This guide assumes you have some familiarity with making a shared library + on your system (or simply have a shared library available to you). + Items to remember are: +\end_layout + +\begin_layout Itemize +A shared library must be compiled in a special way ( +\emph on +e.g. + +\emph default + using the -shared flag with gcc). +\end_layout + +\begin_layout Itemize +On some platforms ( +\emph on +e.g. + +\emph default + Windows) , a shared library requires a .def file that specifies the functions + to be exported. + For example a mylib.def file might contain. + +\end_layout + +\begin_deeper +\begin_layout LyX-Code +LIBRARY mylib.dll +\newline +EXPORTS +\newline +cool_function1 +\newline +cool_function2 +\end_layout + +\begin_layout Standard +Alternatively, you may be able to use the storage-class specifier __declspec(dll +export) in the C-definition of the function to avoid the need for this .def + file. + +\end_layout + +\end_deeper +\begin_layout Standard +There is no standard way in Python distutils to create a standard shared + library (an extension module is a +\begin_inset Quotes eld +\end_inset + +special +\begin_inset Quotes erd +\end_inset + + shared library Python understands) in a cross-platform manner. + Thus, a big disadvantage of ctypes at the time of writing this book is + that it is difficult to distribute in a cross-platform manner a Python + extension that uses c-types and includes your own code which should be + compiled as a shared library on the users system. + +\end_layout + +\begin_layout Subsection +Loading the shared library +\end_layout + +\begin_layout Standard +A simple, but robust way to load the shared library is to get the absolute + path name and load it using the cdll object of ctypes. + +\end_layout + +\begin_layout LyX-Code +lib = ctypes.cdll[<full_path_name>] +\end_layout + +\begin_layout Standard +However, on Windows accessing an attribute of the cdll method will load + the first DLL by that name found in the current directory or on the PATH. + Loading the absolute path name requires a little finesse for cross-platform + work since the extension of shared libraries varies. + There is a +\family typewriter +ctypes.util.find_library +\family default + utility available that can simplify the process of finding the library + to load but it is not foolproof. + Complicating matters, different platforms have different default extensions + used by shared libraries (e.g. + .dll -- Windows, .so -- Linux, .dylib -- Mac OS X). + This must also be taken into account if you are using c-types to wrap code + that needs to work on several platforms. + +\end_layout + +\begin_layout Standard +NumPy provides a convenience function called +\series bold +ctypeslib.load_library +\series default +(name, path). + This function takes the name of the shared library (including any prefix + like 'lib' but excluding the extension) and a path where the shared library + can be located. + It returns a ctypes library object or raises an OSError if the library + cannot be found or raises an ImportError if the ctypes module is not available. + (Windows users: the ctypes library object loaded using +\series bold +load_library +\series default + is always loaded assuming cdecl calling convention. + See the ctypes documentation under ctypes.windll and/or ctypes.oledll for + ways to load libraries under other calling conventions). + +\end_layout + +\begin_layout Standard +The functions in the shared library are available as attributes of the ctypes + library object (returned from +\series bold +ctypeslib.load_library +\series default +) or as items using lib['func_name'] syntax. + The latter method for retrieving a function name is particularly useful + if the function name contains characters that are not allowable in Python + variable names. + +\end_layout + +\begin_layout Subsection +Converting arguments +\end_layout + +\begin_layout Standard +Python ints/longs, strings, and unicode objects are automatically converted + as needed to equivalent c-types arguments The None object is also converted + automatically to a NULL pointer. + All other Python objects must be converted to ctypes-specific types. + There are two ways around this restriction that allow c-types to integrate + with other objects. + +\end_layout + +\begin_layout Enumerate +Don't set the argtypes attribute of the function object and define an _as_parame +ter_ method for the object you want to pass in. + The _as_parameter_ method must return a Python int which will be passed + directly to the function. + +\end_layout + +\begin_layout Enumerate +Set the argtypes attribute to a list whose entries contain objects with + a classmethod named from_param that knows how to convert your object to + an object that ctypes can understand (an int/long, string, unicode, or + object with the _as_parameter_ attribute). + +\end_layout + +\begin_layout Standard +NumPy uses both methods with a preference for the second method because + it can be safer. + The ctypes attribute of the ndarray returns an object that has an _as_parameter +_ attribute which returns an integer representing the address of the ndarray + to which it is associated. + As a result, one can pass this ctypes attribute object directly to a function + expecting a pointer to the data in your ndarray. + The caller must be sure that the ndarray object is of the correct type, + shape, and has the correct flags set or risk nasty crashes if the data-pointer + to inappropriate arrays are passsed in. + +\end_layout + +\begin_layout Standard +To implement the second method, NumPy provides the class-factory function + +\series bold +ndpointer +\series default + in the +\series bold +ctypeslib +\series default + module. + This class-factory function produces an appropriate class that can be placed + in an argtypes attribute entry of a ctypes function. + The class will contain a from_param method which ctypes will use to convert + any ndarray passed in to the function to a ctypes-recognized object. + In the process, the conversion will perform checking on any properties + of the ndarray that were specified by the user in the call to ndpointer. + Aspects of the ndarray that can be checked include the data-type, the number-of +-dimensions, the shape, and/or the state of the flags on any array passed. + The return value of the from_param method is the ctypes attribute of the + array which (because it contains the _as_parameter_ attribute pointing + to the array data area) can be used by ctypes directly. + +\end_layout + +\begin_layout Standard +The ctypes attribute of an ndarray is also endowed with additional attributes + that may be convenient when passing additional information about the array + into a ctypes function. + The attributes +\series bold +data +\series default +, +\series bold +shape +\series default +, and +\series bold +strides +\series default + can provide c-types compatible types corresponding to the data-area, the + shape, and the strides of the array. + The data attribute reutrns a +\family typewriter +c_void_p +\family default + representing a pointer to the data area. + The shape and strides attributes each return an array of ctypes integers + (or None representing a NULL pointer, if a 0-d array). + The base ctype of the array is a ctype integer of the same size as a pointer + on the platform. + There are also methods data_as(<ctype>), shape_as(<base ctype>), and strides_as +(<base ctype>). + These return the data as a ctype object of your choice and the shape/strides + arrays using an underlying base type of your choice. + For convenience, the +\series bold +ctypeslib +\series default + module also contains +\series bold +c_intp +\series default + as a ctypes integer data-type whose size is the same as the size of +\family typewriter +c_void_p +\family default + on the platform (it's value is None if ctypes is not installed). + +\end_layout + +\begin_layout Subsection +Calling the function +\end_layout + +\begin_layout Standard +The function is accessed as an attribute of or an item from the loaded shared-li +brary. + Thus, if +\begin_inset Quotes eld +\end_inset + +./mylib.so +\begin_inset Quotes erd +\end_inset + + has a function named +\begin_inset Quotes eld +\end_inset + +cool_function1 +\begin_inset Quotes erd +\end_inset + +, I could access this function either as +\end_layout + +\begin_layout LyX-Code +lib = numpy.ctypeslib.load_library('mylib','.') +\newline +func1 = lib.cool_function1 # + or equivalently +\newline +func1 = lib['cool_function1'] +\end_layout + +\begin_layout Standard +In ctypes, the return-value of a function is set to be 'int' by default. + This behavior can be changed by setting the restype attribute of the function. + Use None for the restype if the function has no return value ('void'): +\end_layout + +\begin_layout LyX-Code +func1.restype = None +\end_layout + +\begin_layout Standard +As previously discussed, you can also set the argtypes attribute of the + function in order to have ctypes check the types of the input arguments + when the function is called. + Use the ndpointer factory function to generate a ready-made class for data-type +, shape, and flags checking on your new function. + The ndpointer function has the signature +\end_layout + +\begin_layout Description +ndpointer (dtype=None, ndim=None, shape=None, flags=None) +\end_layout + +\begin_layout Description +\InsetSpace ~ + Keyword arguments with the value +\family typewriter +None +\family default + are not checked. + Specifying a keyword enforces checking of that aspect of the ndarray on + conversion to a ctypes-compatible object. + The dtype keyword can be any object understood as a data-type object. + The ndim keyword should be an integer, and the shape keyword should be + an integer or a sequence of integers. + The flags keyword specifies the minimal flags that are required on any + array passed in. + This can be specified as a string of comma separated requirements, an integer + indicating the requirement bits OR'd together, or a flags object returned + from the flags attribute of an array with the necessary requirements. + +\end_layout + +\begin_layout Standard +Using an ndpointer class in the argtypes method can make it significantly + safer to call a C-function using ctypes and the data-area of an ndarray. + You may still want to wrap the function in an additional Python wrapper + to make it user-friendly (hiding some obvious arguments and making some + arguments output arguments). + In this process, the +\series bold +requires +\series default + function in NumPy may be useful to return the right kind of array from + a given input. + +\end_layout + +\begin_layout Subsection +Complete example +\end_layout + +\begin_layout Standard +In this example, I will show how the addition function and the filter function + implemented previously using the other approaches can be implemented using + ctypes. + First, the C-code which implements the algorithms contains the functions + zadd, dadd, sadd, cadd, and dfilter2d. + The zadd function is +\end_layout + +\begin_layout LyX-Code +/* Add arrays of contiguous data */ +\newline +typedef struct {double real; double imag;} + cdouble; +\newline +typedef struct {float real; float imag;} cfloat; +\newline +void zadd(cdouble + *a, cdouble *b, cdouble *c, long n) +\newline +{ +\newline + while (n--) { +\newline + c->real = + a->real + b->real; +\newline + c->imag = a->imag + b->imag; +\newline + a++; b++; + c++; +\newline + } +\newline +} +\end_layout + +\begin_layout Standard +with similar code for cadd, dadd, and sadd that handles complex float, double, + and float data-types, respectively: +\end_layout + +\begin_layout LyX-Code +void cadd(cfloat *a, cfloat *b, cfloat *c, long n) +\newline +{ +\newline + while (n--) { +\newline + + c->real = a->real + b->real; +\newline + c->imag = a->imag + + b->imag; +\newline + a++; b++; c++; +\newline + } +\newline +} +\newline +void dadd(double + *a, double *b, double *c, long n) +\newline +{ +\newline + while (n--) { +\newline + + *c++ = *a++ + *b++; +\newline + } +\newline +} +\newline +void sadd(float *a, float *b, float + *c, long n) +\newline +{ +\newline + while (n--) { +\newline + *c++ = *a++ + *b++; +\newline + + } +\newline +} +\end_layout + +\begin_layout Standard +The code.c file also contains the function dfilter2d: +\end_layout + +\begin_layout LyX-Code +/* Assumes b is contiguous and +\newline + a has strides that are multiples of sizeof(dou +ble) +\newline +*/ +\newline +void +\newline +dfilter2d(double *a, double *b, int *astrides, int *dims) +\newline +{ +\newline + + int i, j, M, N, S0, S1; +\newline + int r, c, rm1, rp1, cp1, cm1; +\newline + +\newline + M = dims[0]; + N = dims[1]; +\newline + S0 = astrides[0]/sizeof(double); +\newline + S1=astrides[1]/sizeof(doub +le); +\newline + for (i=1; i<M-1; i++) { +\newline + r = i*S0; rp1 = r+S0; rm1 = r-S0; +\newline + + for (j=1; j<N-1; j++) { +\newline + c = j*S1; cp1 = j+S1; cm1 = j-S1; +\newline + + b[i*N+j] = a[r+c] + +\backslash + +\newline + (a[rp1+c] + a[rm1+c] + +\backslash + +\newline + a[r+cp1] + a[r+cm1])*0.5 + +\backslash + +\newline + (a[rp1+cp1] + a[rp1+cm1] + +\backslash + +\newline + a[rm1+cp1] + a[rm1+cp1])*0.25; +\newline + } +\newline + } +\newline +} +\end_layout + +\begin_layout Standard +A possible advantage this code has over the Fortran-equivalent code is that + it takes arbitrarily strided (i.e. + non-contiguous arrays) and may also run faster depending on the optimization + capability of your compiler. + But, it is a obviously more complicated than the simple code in filter.f. + This code must be compiled into a shared library. + On my Linux system this is accomplished using +\end_layout + +\begin_layout LyX-Code +gcc -o code.so -shared code.c +\end_layout + +\begin_layout Standard +Which creates a shared_library named code.so in the current directory. + On Windows don't forget to either add __declspec(dllexport) in front of + void on the line preceeding each function definition, or write a code.def + file that lists the names of the functions to be exported. + +\end_layout + +\begin_layout Standard +A suitable Python interface to this shared library should be constructed. + To do this create a file named interface.py with the following lines at + the top: +\end_layout + +\begin_layout LyX-Code +__all__ = ['add', 'filter2d'] +\newline + +\newline +import numpy as N +\newline +import os +\newline + +\newline +_path = os.path.dirname('__ +file__') +\newline +lib = N.ctypeslib.load_library('code', _path) +\newline +_typedict = {'zadd' : + complex, 'sadd' : N.single, +\newline + 'cadd' : N.csingle, 'dadd' : float} +\newline +for + name in _typedict.keys(): +\newline + val = getattr(lib, name) +\newline + val.restype = None +\newline + + _type = _typedict[name] +\newline + val.argtypes = [N.ctypeslib.ndpointer(_type, + +\newline + flags='aligned, contiguous'), +\newline + + N.ctypeslib.ndpointer(_type, +\newline + flags='aligned, contiguous'), +\newline + + N.ctypeslib.ndpointer(_type, +\newline + flags='alig +ned, contiguous,' +\backslash + +\newline + 'writeable'), +\newline + N.ctypeslib.c_intp] +\end_layout + +\begin_layout Standard +This code loads the shared library named code.<ext> located in the same path + as this file. + It then adds a return type of void to the functions contained in the library. + It also adds argument checking to the functions in the library so that + ndarrays can be passed as the first three arguments along with an integer + (large enough to hold a pointer on the platform) as the fourth argument. + +\end_layout + +\begin_layout Standard +Setting up the filtering function is similar and allows the filtering function + to be called with ndarray arguments as the first two arguments and with + pointers to integers (large enough to handle the strides and shape of an + ndarray) as the last two arguments. + +\end_layout + +\begin_layout LyX-Code +lib.dfilter2d.restype=None +\newline +lib.dfilter2d.argtypes = [N.ctypeslib.ndpointer(float, + ndim=2, +\newline + flags='aligned'), +\newline + + N.ctypeslib.ndpointer(float, ndim=2, +\newline + + flags='aligned, contiguous,' +\backslash + +\newline + 'writeable'), +\newline + + ctypes.POINTER(N.ctypeslib.c_intp), +\newline + ctypes.POINTER +(N.ctypeslib.c_intp)] +\end_layout + +\begin_layout Standard +Next, define a simple selection function that chooses which addition function + to call in the shared library based on the data-type: +\end_layout + +\begin_layout LyX-Code +def select(dtype): +\newline + if dtype.char in ['?bBhHf']: +\newline + return lib.sadd, + single +\newline + elif dtype.char in ['F']: +\newline + return lib.cadd, csingle +\newline + elif + dtype.char in ['DG']: +\newline + return lib.zadd, complex +\newline + else: +\newline + return + lib.dadd, float +\newline + return func, ntype +\end_layout + +\begin_layout Standard +Finally, the two functions to be exported by the interface can be written + simply as +\end_layout + +\begin_layout LyX-Code +def add(a, b): +\newline + requires = ['CONTIGUOUS', 'ALIGNED'] +\newline + a = N.asanyarray(a) +\newline + + func, dtype = select(a.dtype) +\newline + a = N.require(a, dtype, requires) +\newline + + b = N.require(b, dtype, requires) +\newline + c = N.empty_like(a) +\newline + func(a,b,c,a.size) +\newline + + return c +\end_layout + +\begin_layout Standard +and +\end_layout + +\begin_layout LyX-Code +def filter2d(a): +\newline + a = N.require(a, float, ['ALIGNED']) +\newline + b = N.zeros_like(a) +\newline + + lib.dfilter2d(a, b, a.ctypes.strides, a.ctypes.shape) +\newline + return b +\end_layout + +\begin_layout Subsection +Conclusion +\end_layout + +\begin_layout Standard +Using ctypes is a powerful way to connect Python with arbitrary C-code. + It's advantages for extending Python include +\end_layout + +\begin_layout Itemize +clean separation of C-code from Python code +\end_layout + +\begin_deeper +\begin_layout Itemize +no need to learn a new syntax except Python and C +\end_layout + +\begin_layout Itemize +allows re-use of C-code +\end_layout + +\begin_layout Itemize +functionality in shared libraries written for other purposes can be obtained + with a simple Python wrapper and search for the library. + +\end_layout + +\end_deeper +\begin_layout Itemize +easy integration with NumPy through the ctypes attribute +\end_layout + +\begin_layout Itemize +full argument checking with the ndpointer class factory +\end_layout + +\begin_layout Standard +It's disadvantages include +\end_layout + +\begin_layout Itemize +It is difficult to distribute an extension module made using ctypes because + of a lack of support for building shared libraries in distutils (but I + suspect this will change in time). + +\end_layout + +\begin_layout Itemize +You must have shared-libraries of your code (no static libraries). + +\end_layout + +\begin_layout Itemize +Very little support for C++ code and it's different library-calling conventions. + You will probably need a C-wrapper around C++ code to use with ctypes (or + just use Boost.Python instead). +\end_layout + +\begin_layout Standard +Because of the difficulty in distributing an extension module made using + ctypes, f2py is still the easiest way to extend Python for package creation. + However, ctypes is a close second and will probably be growing in popularity + now that it is part of the Python distribution. + This should bring more features to ctypes that should eliminate the difficulty + in extending Python and distributing the extension using ctypes. + +\begin_inset LatexCommand index +name "ctypes|)" + +\end_inset + + +\end_layout + +\begin_layout Section +Additional tools you may find useful +\end_layout + +\begin_layout Standard +These tools have been found useful by others using Python and so are included + here. + They are discussed separately because I see them as either older ways to + do things more modernly handled by f2py, weave, Pyrex, or ctypes (SWIG, + PyFort, PyInline) or because I don't know much about them (SIP, Boost, + Instant). + I have not added links to these methods because my experience is that you + can find the most relevant link faster using Google or some other search + engine, and any links provided here would be quickly dated. + Do not assume that just because it is included in this list, I don't think + the package deserves your attention. + I'm including information about these packages because many people have + found them useful and I'd like to give you as many options as possible + for tackling the problem of easily integrating your code. + +\end_layout + +\begin_layout Subsection +SWIG +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "swig" + +\end_inset + +Simplified Wrapper and Interface Generator (SWIG) is an old and fairly stable + method for wrapping C/C++-libraries to a large variety of other languages. + It does not specifically understand NumPy arrays but can be made useable + with NumPy through the use of typemaps. + There are some sample typemaps in the numpy/doc/swig directory under numpy.i + along with an example module that makes use of them. + SWIG excels at wrapping large C/C++ libraries because it can (almost) parse + their headers and auto-produce an interface. + Technically, you need to generate a +\family typewriter +.i +\family default + file that defines the interface. + Often, however, this +\family typewriter +.i +\family default + file can be parts of the header itself. + The interface usually needs a bit of tweaking to be very useful. + This ability to parse C/C++ headers and auto-generate the interface still + makes SWIG a useful approach to adding functionalilty from C/C++ into Python, + despite the other methods that have emerged that are more targeted to Python. + SWIG can actually target extensions for several languages, but the typemaps + usually have to be language-specific. + Nonetheless, with modifications to the Python-specific typemaps, SWIG can + be used to interface a library with other languages such as Perl, Tcl, + and Ruby. + +\end_layout + +\begin_layout Standard +My experience with SWIG has been generally positive in that it is relatively + easy to use and quite powerful. + I used to use it quite often before becoming more proficient at writing + C-extensions. + However, I struggled writing custom interfaces with SWIG because it must + be done using the concept of typemaps which are not Python specific and + are written in a C-like syntax. + Therefore, I tend to prefer other gluing strategies and would only attempt + to use SWIG to wrap a very-large C/C++ library. + Nonetheless, there are others who use SWIG quite happily. + +\end_layout + +\begin_layout Subsection +SIP +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "SIP" + +\end_inset + +SIP is another tool for wrapping C/C++ libraries that is Python specific + and appears to have very good support for C++. + Riverbank Computing developed SIP in order to create Python bindings to + the QT library. + An interface file must be written to generate the binding, but the interface + file looks a lot like a C/C++ header file. + While SIP is not a full C++ parser, it understands quite a bit of C++ syntax + as well as its own special directives that allow modification of how the + Python binding is accomplished. + It also allows the user to define mappings between Python types and C/C++ + structrues and classes. + +\end_layout + +\begin_layout Subsection +Boost Python +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "Boost.Python" + +\end_inset + +Boost is a repository of C++ libraries and Boost.Python is one of those libraries + which provides a concise interface for binding C++ classes and functions + to Python. + The amazing part of the Boost.Python approach is that it works entirely + in pure C++ without introducing a new syntax. + Many users of C++ report that Boost.Python makes it possible to combine + the best of both worlds in a seamless fashion. + I have not used Boost.Python because I am not a big user of C++ and using + Boost to wrap simple C-subroutines is usually over-kill. + It's primary purpose is to make C++ classes available in Python. + So, if you have a set of C++ classes that need to be integrated cleanly + into Python, consider learning about and using Boost.Python. +\end_layout + +\begin_layout Subsection +Instant +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "Instant" + +\end_inset + +This is a relatively new package (called pyinstant at sourceforge) that + builds on top of SWIG to make it easy to inline C and C++ code in Python + very much like weave. + However, Instant builds extension modules on the fly with specific module + names and specific method names. + In this repsect it is more more like f2py in its behavior. + The extension modules are built on-the fly (as long as the SWIG is installed). + They can then be imported. + Here is an example of using Instant with NumPy arrays (adapted from the + test2 included in the Instant distribution): +\end_layout + +\begin_layout LyX-Code +code=""" +\end_layout + +\begin_layout LyX-Code +PyObject* add(PyObject* a_, PyObject* b_){ +\end_layout + +\begin_layout LyX-Code + /* +\end_layout + +\begin_layout LyX-Code + various checks +\end_layout + +\begin_layout LyX-Code + */ +\end_layout + +\begin_layout LyX-Code + PyArrayObject* a=(PyArrayObject*) a_; +\end_layout + +\begin_layout LyX-Code + PyArrayObject* b=(PyArrayObject*) b_; +\end_layout + +\begin_layout LyX-Code + int n = a->dimensions[0]; +\end_layout + +\begin_layout LyX-Code + int dims[1]; +\end_layout + +\begin_layout LyX-Code + dims[0] = n; +\end_layout + +\begin_layout LyX-Code + PyArrayObject* ret; +\end_layout + +\begin_layout LyX-Code + ret = (PyArrayObject*) PyArray_FromDims(1, dims, NPY_DOUBLE); +\end_layout + +\begin_layout LyX-Code + int i; +\end_layout + +\begin_layout LyX-Code + char *aj=a->data; +\end_layout + +\begin_layout LyX-Code + char *bj=b->data; +\end_layout + +\begin_layout LyX-Code + double *retj = (double *)ret->data; +\end_layout + +\begin_layout LyX-Code + for (i=0; i < n; i++) { +\end_layout + +\begin_layout LyX-Code + *retj++ = *((double *)aj) + *((double *)bj); +\end_layout + +\begin_layout LyX-Code + aj += a->strides[0]; +\end_layout + +\begin_layout LyX-Code + bj += b->strides[0]; +\end_layout + +\begin_layout LyX-Code + } +\end_layout + +\begin_layout LyX-Code +return (PyObject *)ret; +\end_layout + +\begin_layout LyX-Code +} +\end_layout + +\begin_layout LyX-Code +""" +\end_layout + +\begin_layout LyX-Code +import Instant, numpy +\end_layout + +\begin_layout LyX-Code +ext = Instant.Instant() +\end_layout + +\begin_layout LyX-Code +ext.create_extension(code=s, headers=["numpy/arrayobject.h"], + include_dirs=[numpy.get_include()], + init_code='import_array();', module="test2b_ext +") +\end_layout + +\begin_layout LyX-Code +import test2b_ext +\end_layout + +\begin_layout LyX-Code +a = numpy.arange(1000) +\end_layout + +\begin_layout LyX-Code +b = numpy.arange(1000) +\end_layout + +\begin_layout LyX-Code +d = test2b_ext.add(a,b) +\end_layout + +\begin_layout Standard +Except perhaps for the dependence on SWIG, Instant is a straightforward + utility for writing extension modules. + +\end_layout + +\begin_layout Subsection +PyInline +\end_layout + +\begin_layout Standard +This is a much older module that allows automatic building of extension + modules so that C-code can be included with Python code. + It's latest release (version 0.03) was in 2001, and it appears that it is + not being updated. + +\end_layout + +\begin_layout Subsection +PyFort +\end_layout + +\begin_layout Standard +PyFort is a nice tool for wrapping Fortran and Fortran-like C-code into + Python with support for Numeric arrays. + It was written by Paul Dubois, a distinguished computer scientist and the + very first maintainer of Numeric (now retired). + It is worth mentioning in the hopes that somebody will update PyFort to + work with NumPy arrays as well which now support either Fortran or C-style + contiguous arrays. + +\end_layout + +\begin_layout Chapter +Code Explanations +\end_layout + +\begin_layout Quotation +Fanaticism consists of redoubling your efforts when you have forgotten your + aim. +\end_layout + +\begin_layout Right Address +--- +\emph on +George Santayana +\end_layout + +\begin_layout Quotation +An authority is a person who can tell you more about something than you + really care to know. +\end_layout + +\begin_layout Right Address +--- +\emph on +Unknown +\end_layout + +\begin_layout Standard +This Chapter attempts to explain the logic behind some of the new pieces + of code. + The purpose behind these explanations is to enable somebody to be able + to understand the ideas behind the implementation somewhat more easily + than just staring at the code. + Perhaps in this way, the algorithms can be improved on, borrowed from, + and/or optimized. + +\end_layout + +\begin_layout Section +Memory model +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ndarray!memory model" + +\end_inset + +One fundamental aspect of the ndarray is that an array is seen as a +\begin_inset Quotes eld +\end_inset + +chunk +\begin_inset Quotes erd +\end_inset + + of memory starting at some location. + The interpretation of this memory depends on the stride information. + For each dimension in an +\begin_inset Formula $N$ +\end_inset + +-dimensional array, an integer (stride) dictates how many bytes must be + skipped to get to the next element in that dimension. + Unless you have a single-segment array, this stride information must be + consulted when traversing through an array. + It is not difficult to write code that accepts strides, you just have to + use (char *) pointers because strides are in units of bytes. + Keep in mind also that strides do not have to be unit-multiples of the + element size. + Also, remember that if the number of dimensions of the array is 0 (sometimes + called a rank-0 array), then the strides and dimensions variables are NULL. + +\end_layout + +\begin_layout Standard +Besides the structural information contained in the strides and dimensions + members of the PyArrayObject, the flags contain important information about + how the data may be accessed. + In particular, the NPY_ALIGNED flag is set when the memory is on a suitable + boundary according to the data-type array. + Even if you have a contiguous chunk of memory, you cannot just assume it + is safe to dereference a data-type-specific pointer to an element. + Only if the NPY_ALIGNED flag is set is this a safe operation (on some platforms + it will work but on others, like Solaris, it will cause a bus error). + The NPY_WRITEABLE should also be ensured if you plan on writing to the + memory area of the array. + It is also possible to obtain a pointer to an unwriteable memory area. + Sometimes, writing to the memory area when the NPY_WRITEABLE flag is not + set will just be rude. + Other times it can cause program crashes ( +\emph on +e.g. + +\emph default + a data-area that is a read-only memory-mapped file). +\end_layout + +\begin_layout Section +Data-type encapsulation +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "dtype" + +\end_inset + +The data-type is an important abstraction of the ndarray. + Operations will look to the data-type to provide the key functionality + that is needed to operate on the array. + This functionality is provided in the list of function pointers pointed + to by the 'f' member of the PyArray_Descr structure. + In this way, the number of data-types can be extended simply by providing + a PyArray_Descr structure with suitable function pointers in the 'f' member. + For built-in types there are some optimizations that by-pass this mechanism, + but the point of the data-type abstraction is to allow new data-types to + be added. +\end_layout + +\begin_layout Standard +One of the built-in data-types, the void data-type allows for arbitrary + records containing 1 or more fields as elements of the array. + A field is simply another data-type object along with an offset into the + current record. + In order to support arbitrarily nested fields, several recursive implementation +s of data-type access are implemented for the void type. + A common idiom is to cycle through the elements of the dictionary and perform + a specific operation based on the data-type object stored at the given + offset. + These offsets can be arbitrary numbers. + Therefore, the possibility of encountering mis-aligned data must be recognized + and taken into account if necessary. + +\end_layout + +\begin_layout Section +N-D Iterators +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "array iterator" + +\end_inset + +A very common operation in much of NumPy code is the need to iterate over + all the elements of a general, strided, N-dimensional array. + This operation of a general-purpose N-dimensional loop is abstracted in + the notion of an iterator object. + To write an N-dimensional loop, you only have to create an iterator object + from an ndarray, work with the dataptr member of the iterator object structure + and call the macro PyArray_ITER_NEXT(it) on the iterator object to move + to the next element. + The +\begin_inset Quotes eld +\end_inset + +next +\begin_inset Quotes erd +\end_inset + + element is always in C-contiguous order. + The macro works by first special casing the C-contiguous, 1-d, and 2-d + cases which work very simply. + +\end_layout + +\begin_layout Standard +For the general case, the iteration works by keeping track of a list of + coordinate counters in the iterator object. + At each iteration, the last coordinate counter is increased (starting from + 0). + If this counter is smaller then one less than the size of the array in + that dimension (a pre-computed and stored value), then the counter is increased + and the dataptr member is increased by the strides in that dimension and + the macro ends. + If the end of a dimension is reached, the counter for the last dimension + is reset to zero and the dataptr is moved back to the beginning of that + dimension by subtracting the strides value times one less than the number + of elements in that dimension (this is also pre-computed and stored in + the backstrides member of the iterator object). + In this case, the macro does not end, but a local dimension counter is + decremented so that the next-to-last dimension replaces the role that the + last dimension played and the previously-described tests are executed again + on the next-to-last dimension. + In this way, the dataptr is adjusted appropriately for arbitrary striding. + +\end_layout + +\begin_layout Standard +The coordinates member of the PyArrayIterObject structure maintains the + current N-d counter unless the underlying array is C-contiguous in which + case the coordinate counting is by-passed. + The index member of the PyArrayIterObject keeps track of the current flat + index of the iterator. + It is updated by the PyArray_ITER_NEXT macro. + +\end_layout + +\begin_layout Section +Broadcasting +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "broadcasting" + +\end_inset + +In Numeric, broadcasting was implemented in several lines of code buried + deep in ufuncobject.c. + In NumPy, the notion of broadcasting has been abstracted so that it can + be performed in multiple places. + Broadcasting is handled by the function PyArray_Broadcast. + This function requires a PyArrayMultiIterObject (or something that is a + binary equivalent) to be passed in. + The PyArrayMultiIterObject keeps track of the broadcasted number of dimensions + and size in each dimension along with the total size of the broadcasted + result. + It also keeps track of the number of arrays being broadcast and a pointer + to an iterator for each of the arrays being broadcasted. + +\end_layout + +\begin_layout Standard +The PyArray_Broadcast function takes the iterators that have already been + defined and uses them to determine the broadcast shape in each dimension + (to create the iterators at the same time that broadcasting occurs then + use the PyMuliIter_New function). + Then, the iterators are adjusted so that each iterator thinks it is iterating + over an array with the broadcasted size. + This is done by adjusting the iterators number of dimensions, and the shape + in each dimension. + This works because the iterator strides are also adjusted. + Broadcasting only adjusts (or adds) length-1 dimensions. + For these dimensions, the strides variable is simply set to 0 so that the + data-pointer for the iterator over that array doesn't move as the broadcasting + operation operates over the extended dimension. + +\end_layout + +\begin_layout Standard +Broadcasting was always implemented in Numeric using 0-valued strides for + the extended dimensions. + It is done in exactly the same way in NumPy. + The big difference is that now the array of strides is kept track of in + a PyArrayIterObject, the iterators involved in a broadcasted result are + kept track of in a PyArrayMultiIterObject, and the PyArray_BroadCast call + implements the broad-casting rules. + +\end_layout + +\begin_layout Section +Array Scalars +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "array scalars" + +\end_inset + +The array scalars offer a hierarchy of Python types that allow a one-to-one + correspondence between the data-type stored in an array and the Python-type + that is returned when an element is extracted from the array. + An exception to this rule was made with object arrays. + Object arrays are heterogeneous collections of arbitrary Python objects. + When you select an item from an object array, you get back the original + Python object (and not an object array scalar which does exist but is rarely + used for practical purposes). +\end_layout + +\begin_layout Standard +The array scalars also offer the same methods and attributes as arrays with + the intent that the same code can be used to support arbitrary dimensions + (including 0-dimensions). + The array scalars are read-only (immutable) with the exception of the void + scalar which can also be written to so that record-array field setting + works more naturally (a[0]['f1'] = +\family typewriter +value +\family default +). +\end_layout + +\begin_layout Section +Advanced ( +\begin_inset Quotes eld +\end_inset + +Fancy +\begin_inset Quotes erd +\end_inset + +) Indexing +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "indexing" + +\end_inset + +The implementation of advanced indexing represents some of the most difficult + code to write and explain. + In fact, there are two implementations of advanced indexing. + The first works only with 1-d arrays and is implemented to handle expressions + involving a.flat[obj]. + The second is general-purpose that works for arrays of +\begin_inset Quotes eld +\end_inset + +arbitrary dimension +\begin_inset Quotes erd +\end_inset + + (up to a fixed maximum). + The one-dimensional indexing approaches were implemented in a rather straightfo +rward fashion, and so it is the general-purpose indexing code that will + be the focus of this section. + +\end_layout + +\begin_layout Standard +There is a multi-layer approach to indexing because the indexing code can + at times return an array scalar and at other times return an array. + The functions with +\begin_inset Quotes eld +\end_inset + +_nice +\begin_inset Quotes erd +\end_inset + + appended to their name do this special handling while the function without + the _nice appendage always return an array (perhaps a 0-dimensional array). + Some special-case optimizations (the index being an integer scalar, and + the index being a tuple with as many dimensions as the array) are handled + in array_subscript_nice function which is what Python calls when presented + with the code +\begin_inset Quotes eld +\end_inset + +a[obj]. +\begin_inset Quotes erd +\end_inset + + These optimizations allow fast single-integer indexing, and also ensure + that a 0-dimensional array is not created only to be discarded as the array + scalar is returned instead. + This provides significant speed-up for code that is selecting many scalars + out of an array (such as in a loop). + However, it is still not faster than simply using a list to store standard + Python scalars, because that is optimized by the Python interpreter itself. + +\end_layout + +\begin_layout Standard +After these optimizations, the array_subscript function itself is called. + This function first checks for field selection which occurs when a string + is passed as the indexing object. + Then, 0-d arrays are given special-case consideration. + Finally, the code determines whether or not advanced, or fancy, indexing + needs to be performed. + If fancy indexing is not needed, then standard view-based indexing is performed + using code borrowed from Numeric which parses the indexing object and returns + the offset into the data-buffer and the dimensions necessary to create + a new view of the array. + The strides are also changed by multiplying each stride by the step-size + requested along the corresponding dimension. + +\end_layout + +\begin_layout Subsection +Fancy-indexing check +\end_layout + +\begin_layout Standard +The fancy_indexing_check routine determines whether or not to use standard + view-based indexing or new copy-based indexing. + If the indexing object is a tuple, then view-based indexing is assumed + by default. + Only if the tuple contains an array object or a sequence object is fancy-indexi +ng assumed. + If the indexing object is an array, then fancy indexing is automatically + assumed. + If the indexing object is any other kind of sequence, then fancy-indexing + is assumed by default. + This is over-ridden to simple indexing if the sequence contains any slice, + newaxis, or Ellipsis objects, and no arrays or additional sequences are + also contained in the sequence. + The purpose of this is to allow the construction of +\begin_inset Quotes eld +\end_inset + +slicing +\begin_inset Quotes erd +\end_inset + + sequences which is a common technique for building up code that works in + arbitrary numbers of dimensions. + +\end_layout + +\begin_layout Subsection +Fancy-indexing implementation +\end_layout + +\begin_layout Standard +The concept of indexing was also abstracted using the idea of an iterator. + If fancy indexing is performed, then a PyArrayMapIterObject is created. + This internal object is not exposed to Python. + It is created in order to handle the fancy-indexing at a high-level. + Both get and set fancy-indexing operations are implemented using this object. + Fancy indexing is abstracted into three separate operations: (1) creating + the PyArrayMapIterObject from the indexing object, (2) binding the PyArrayMapIt +erObject to the array being indexed, and (3) getting (or setting) the items + determined by the indexing object. + There is an optimization implemented so that the PyArrayIterObject (which + has it's own less complicated fancy-indexing) is used for indexing when + possible. + +\end_layout + +\begin_layout Subsubsection +Creating the mapping object +\end_layout + +\begin_layout Standard +The first step is to convert the indexing objects into a standard form where + iterators are created for all of the index array inputs and all Boolean + arrays are converted to equivalent integer index arrays (as if nonzero(arr) + had been called). + Finally, all integer arrays are replaced with the integer 0 in the indexing + object and all of the index-array iterators are +\begin_inset Quotes eld +\end_inset + +broadcast +\begin_inset Quotes erd +\end_inset + + to the same shape. + +\end_layout + +\begin_layout Subsubsection +Binding the mapping object +\end_layout + +\begin_layout Standard +When the mapping object is created it does not know which array it will + be used with so once the index iterators are constructed during mapping-object + creation, the next step is to associate these iterators with a particular + ndarray. + This process interprets any ellipsis and slice objects so that the index + arrays are associated with the appropriate axis (the axis indicated by + the iteraxis entry corresponding to the iterator for the integer index + array). + This information is then used to check the indices to be sure they are + within range of the shape of the array being indexed. + The presence of ellipsis and/or slice objects implies a sub-space iteration + that is accomplished by extracting a sub-space view of the array (using + the index object resulting from replacing all the integer index arrays + with 0) and storing the information about where this sub-space starts in + the mapping object. + This is used later during mapping-object iteration to select the correct + elements from the underlying array. + +\end_layout + +\begin_layout Subsubsection +Getting (or Setting) +\end_layout + +\begin_layout Standard +After the mapping object is successfully bound to a particular array, the + mapping object contains the shape of the resulting item as well as iterator + objects that will walk through the currently-bound array and either get + or set its elements as needed. + The walk is implemented using the PyArray_MapIterNext function. + This function sets the coordinates of an iterator object into the current + array to be the next coordinate location indicated by all of the indexing-objec +t iterators while adjusting, if necessary, for the presence of a sub-space. + The result of this function is that the dataptr member of the mapping object + structure is pointed to the next position in the array that needs to be + copied out or set to some value. + +\end_layout + +\begin_layout Standard +When advanced indexing is used to extract an array, an iterator for the + new array is constructed and advanced in phase with the mapping object + iterator. + When advanced indexing is used to place values in an array, a special +\begin_inset Quotes eld +\end_inset + +broadcasted +\begin_inset Quotes erd +\end_inset + + iterator is constructed from the object being placed into the array so + that it will only work if the values used for setting have a shape that + is +\begin_inset Quotes eld +\end_inset + +broadcastable +\begin_inset Quotes erd +\end_inset + + to the shape implied by the indexing object. + +\end_layout + +\begin_layout Section +Universal Functions +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ufunc|(" + +\end_inset + +Universal functions are callable objects that take +\begin_inset Formula $N$ +\end_inset + + inputs and produce +\begin_inset Formula $M$ +\end_inset + + outputs by wrapping basic 1-d loops that work element-by-element into full + easy-to use functions that seamlessly implement broadcasting, type-checking + and buffered coercion, and output-argument handling. + New universal functions are normally created in C, although there is a + mechanism for creating ufuncs from Python functions ( +\series bold +frompyfunc +\series default +). + The user must supply a 1-d loop that implements the basic function taking + the input scalar values and placing the resulting scalars into the appropriate + output slots as explaine n implementation. + +\end_layout + +\begin_layout Subsection +Setup +\end_layout + +\begin_layout Standard +Every ufunc calculation involves some overhead related to setting up the + calculation. + The practical significance of this overhead is that even though the actual + calculation of the ufunc is very fast, you will be able to write array + and type-specific code that will work faster for small arrays than the + ufunc. + In particular, using ufuncs to perform many calculations on 0-d arrays + will be slower than other Python-based solutions (the silently-imported + scalarmath module exists precisely to give array scalars the look-and-feel + of ufunc-based calculations with significantly reduced overhead). + +\end_layout + +\begin_layout Standard +When a ufunc is called, many things must be done. + The information collected from these setup operations is stored in a loop-objec +t. + This loop object is a C-structure (that could become a Python object but + is not initialized as such because it is only used internally). + This loop object has the layout needed to be used with PyArray_Broadcast + so that the broadcasting can be handled in the same way as it is handled + in other sections of code. + +\end_layout + +\begin_layout Standard +The first thing done is to look-up in the thread-specific global dictionary + the current values for the buffer-size, the error mask, and the associated + error object. + The state of the error mask controls what happens when an error-condiction + is found. + It should be noted that checking of the hardware error flags is only performed + after each 1-d loop is executed. + This means that if the input and output arrays are contiguous and of the + correct type so that a single 1-d loop is performed, then the flags may + not be checked until all elements of the array have been calcluated. + Looking up these values in a thread-specific dictionary takes time which + is easily ignored for all but very small arrays. + +\end_layout + +\begin_layout Standard +After checking, the thread-specific global variables, the inputs are evaluated + to determine how the ufunc should proceed and the input and output arrays + are constructed if necessary. + Any inputs which are not arrays are converted to arrays (using context + if necessary). + Which of the inputs are scalars (and therefore converted to 0-d arrays) + is noted. + +\end_layout + +\begin_layout Standard +Next, an appropriate 1-d loop is selected from the 1-d loops available to + the ufunc based on the input array types. + This 1-d loop is selected by trying to match the signature of the data-types + of the inputs against the available signatures. + The signatures corresponding to built-in types are stored in the types + member of the ufunc structure. + The signatures corresponding to user-defined types are stored in a linked-list + of function-information with the head element stored as a +\family typewriter +CObject +\family default + in the userloops dictionary keyed by the data-type number (the first user-defin +ed type in the argument list is used as the key). + The signatures are searched until a signature is found to which the input + arrays can all be cast safely (ignoring any scalar arguments which are + not allowed to determine the type of the result). + The implication of this search procedure is that +\begin_inset Quotes eld +\end_inset + +lesser types +\begin_inset Quotes erd +\end_inset + + should be placed below +\begin_inset Quotes eld +\end_inset + +larger types +\begin_inset Quotes erd +\end_inset + + when the signatures are stored. + If no 1-d loop is found, then an error is reported. + Otherwise, the argument_list is updated with the stored signature --- in + case casting is necessary and to fix the output types assumed by the 1-d + loop. +\end_layout + +\begin_layout Standard +If the ufunc has 2 inputs and 1 output and the second input is an Object + array then a special-case check is performed so that NotImplemented is + returned if the second input is not an ndarray, has the __array_priority__ + attribute, and has an __r<op>__ special method. + In this way, Python is signaled to give the other object a chance to complete + the operation instead of using generic object-array calculations. + This allows (for example) sparse matrices to override the multiplication + operator 1-d loop. + +\end_layout + +\begin_layout Standard +For input arrays that are smaller than the specified buffer size, copies + are made of all non-contiguous, mis-aligned, or out-of-byteorder arrays + to ensure that for small arrays, a single-loop is used. + Then, array iterators are created for all the input arrays and the resulting + collection of iterators is broadcast to a single shape. + +\end_layout + +\begin_layout Standard +The output arguments (if any) are then processed and any missing return + arrays are constructed. + If any provided output array doesn't have the correct type (or is mis-aligned) + and is smaller than the buffer size, then a new output array is constructed + with the special UPDATEIFCOPY flag set so that when it is DECREF'd on completio +n of the function, it's contents will be copied back into the output array. + Iterators for the output arguments are then processed. + +\end_layout + +\begin_layout Standard +Finally, the decision is made about how to execute the looping mechanism + to ensure that all elements of the input arrays are combined to produce + the output arrays of the correct type. + The options for loop execution are one-loop (for contiguous, aligned, and + correct data-type), strided-loop (for non-contiguous but still aligned + and correct data-type), and a buffered loop (for mis-aligned or incorrect + data-type situations). + Depending on which execution method is called for, the loop is then setup + and computed. + +\end_layout + +\begin_layout Subsection +Function call +\end_layout + +\begin_layout Standard +This section describes how the basic universal function computation loop + is setup and executed for each of the three different kinds of execution + possibilities. + If NPY_ALLOW_THREADS is defined during compilation, then the Python Global + Interpreter Lock (GIL) is released prior to calling all of these loops + (as long as they don't involve object arrays). + It is re-acquired if necessary to handle error conditions. + The hardware error flags are checked only after the 1-d loop is calcluated. + +\end_layout + +\begin_layout Subsubsection +One Loop +\end_layout + +\begin_layout Standard +This is the simplest case of all. + The ufunc is executed by calling the underlying 1-d loop exactly once. + This is possible only when we have aligned data of the correct type (including + byte-order) for both input and output and all arrays have uniform strides + (either contiguous, 0-d, or 1-d). + In this case, the 1-d computational loop is called once to compute the + calculation for the entire array. + Note that the hardware error flags are only checked after the entire calculatio +n is complete. + +\end_layout + +\begin_layout Subsubsection +Strided Loop +\end_layout + +\begin_layout Standard +When the input and output arrays are aligned and of the correct type, but + the striding is not uniform (non-contiguous and 2-d or larger), then a + second looping structure is employed for the calculation. + This approach converts all of the iterators for the input and output arguments + to iterate over all but the largest dimension. + The inner loop is then handled by the underlying 1-d computational loop. + The outer loop is a standard iterator loop on the converted iterators. + The hardware error flags are checked after each 1-d loop is completed. + +\end_layout + +\begin_layout Subsubsection +Buffered Loop +\end_layout + +\begin_layout Standard +This is the code that handles the situation whenever the input and/or output + arrays are either misaligned or of the wrong data-type (including being + byte-swapped) from what the underlying 1-d loop expects. + The arrays are also assumed to be non-contiguous. + The code works very much like the strided loop except for the inner 1-d + loop is modified so that pre-processing is performed on the inputs and + post-processing is performed on the outputs in bufsize chunks (where bufsize + is a user-settable parameter). + The underlying 1-d computational loop is called on data that is copied + over (if it needs to be). + The setup code and the loop code is considerably more complicated in this + case because it has to handle: +\end_layout + +\begin_layout Itemize +memory allocation of the temporary buffers +\end_layout + +\begin_layout Itemize +deciding whether or not to use buffers on the input and output data (mis-aligned + and/or wrong data-type) +\end_layout + +\begin_layout Itemize +copying and possibly casting data for any inputs or outputs for which buffers + are necessary. +\end_layout + +\begin_layout Itemize +special-casing Object arrays so that reference counts are properly handled + when copies and/or casts are necessary. + +\end_layout + +\begin_layout Itemize +breaking up the inner 1-d loop into bufsize chunks (with a possible remainder). + +\end_layout + +\begin_layout Standard +Again, the hardware error flags are checked at the end of each 1-d loop. +\end_layout + +\begin_layout Subsection +Final output manipulation +\end_layout + +\begin_layout Standard +Ufuncs allow other array-like classes to be passed seamlessly through the + interface in that inputs of a particular class will induce the outputs + to be of that same class. + The mechanism by which this works is the following. + If any of the inputs are not ndarrays and define the +\series bold +__array_wrap__ +\series default + method, then the class with the largest +\series bold +__array_priority__ +\series default + attribute determines the type of all the outputs (with the exception of + any output arrays passed in). + The +\series bold +__array_wrap__ +\series default + method of the input array will be called with the ndarray being returned + from the ufunc as it's input. + There are two calling styles of the +\series bold +__array_wrap__ +\series default + function supported. + The first takes the ndarray as the first argument and a tuple of +\begin_inset Quotes eld +\end_inset + +context +\begin_inset Quotes erd +\end_inset + + as the second argument. + The context is (ufunc, arguments, output argument number). + This is the first call tried. + If a TypeError occurs, then the function is called with just the ndarray + as the first argument. + +\end_layout + +\begin_layout Subsection +Methods +\end_layout + +\begin_layout Standard +Their are three methods of ufuncs that require calculation similar to the + general-purpose ufuncs. + These are reduce, accumulate, and reduceat. + Each of these methods requires a setup command followed by a loop. + There are four loop styles possible for the methods corresponding to no-element +s, one-element, strided-loop, and buffered-loop. + These are the same basic loop styles as implemented for the general purpose + function call except for the no-element and one-element cases which are + special-cases occurring when the input array objects have 0 and 1 elements + respectively. + +\end_layout + +\begin_layout Subsubsection +Setup +\end_layout + +\begin_layout Standard +The setup function for all three methods is +\family typewriter +construct_reduce +\family default +. + This function creates a reducing loop object and fills it with parameters + needed to complete the loop. + All of the methods only work on ufuncs that take 2-inputs and return 1 + output. + Therefore, the underlying 1-d loop is selected assuming a signature of + [ +\family typewriter +otype +\family default +, +\family typewriter +otype +\family default +, +\family typewriter +otype +\family default +] where +\family typewriter +otype +\family default + is the requested reduction data-type. + The buffer size and error handling is then retrieved from (per-thread) + global storage. + For small arrays that are mis-aligned or have incorrect data-type, a copy + is made so that the un-buffered section of code is used. + Then, the looping strategy is selected. + If there is 1 element or 0 elements in the array, then a simple looping + method is selected. + If the array is not mis-aligned and has the correct data-type, then strided + looping is selected. + Otherwise, buffered looping must be performed. + Looping parameters are then established, and the return array is constructed. + The output array is of a different shape depending on whether the method + is reduce, accumulate, or reduceat. + If an output array is already provided, then it's shape is checked. + If the output array is not C-contiguous, aligned, and of the correct data + type, then a temporary copy is made with the UPDATEIFCOPY flag set. + In this way, the methods will be able to work with a well-behaved output + array but the result will be copied back into the true output array when + the method computation is complete. + Finally, iterators are set up to loop over the correct axis (depending + on the value of axis provided to the method) and the setup routine returns + to the actual computation routine. + +\end_layout + +\begin_layout Subsubsection +Reduce +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ufunc!methods!reduce" + +\end_inset + +All of the ufunc methods use the same underlying 1-d computational loops + with input and output arguments adjusted so that the appropriate reduction + takes place. + For example, the key to the functioning of reduce is that the 1-d loop + is called with the output and the second input pointing to the same position + in memory and both having a step-size of 0. + The first input is pointing to the input array with a step-size given by + the appropriate stride for the selected axis. + In this way, the operation performed is +\begin_inset Formula \begin{eqnarray*} +o & = & i[0]\\ +o & = & i[k]\textrm{ <op> }o\quad k=1\ldots N\end{eqnarray*} + +\end_inset + + where +\begin_inset Formula $N+1$ +\end_inset + + is the number of elements in the input, +\begin_inset Formula $i$ +\end_inset + +, +\begin_inset Formula $o$ +\end_inset + + is the output, and +\begin_inset Formula $i[k]$ +\end_inset + + is the +\begin_inset Formula $k^{\textrm{th}}$ +\end_inset + + element of +\begin_inset Formula $i$ +\end_inset + + along the selected axis. + This basic operations is repeated for arrays with greater than 1 dimension + so that the reduction takes place for every 1-d sub-array along the selected + axis. + An iterator with the selected dimension removed handles this looping. + +\end_layout + +\begin_layout Standard +For buffered loops, care must be taken to copy and cast data before the + loop function is called because the underlying loop expects aligned data + of the correct data-type (including byte-order). + The buffered loop must handle this copying and casting prior to calling + the loop function on chunks no greater than the user-specified bufsize. + +\end_layout + +\begin_layout Subsubsection +Accumulate +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ufunc!methods!accumulate" + +\end_inset + +The accumulate function is very similar to the reduce function in that the + output and the second input both point to the output. + The difference is that the second input points to memory one stride behind + the current output pointer. + Thus, the operation performed is +\end_layout + +\begin_layout Standard +\begin_inset Formula \begin{eqnarray*} +o[0] & = & i[0]\\ +o[k] & = & i[k]\textrm{ <op> }o[k-1]\quad k=1\ldots N.\end{eqnarray*} + +\end_inset + + The output has the same shape as the input and each 1-d loop operates over + +\begin_inset Formula $N$ +\end_inset + + elements when the shape in the selected axis is +\begin_inset Formula $N+1$ +\end_inset + +. + Again, buffered loops take care to copy and cast the data before calling + the underlying 1-d computational loop. + +\end_layout + +\begin_layout Subsubsection +Reduceat +\end_layout + +\begin_layout Standard +\begin_inset LatexCommand index +name "ufunc!methods!reduceat" + +\end_inset + +The reduceat function is a generalization of both the reduce and accumulate + functions. + It implements a reduce over ranges of the input array specified by indices. + The extra indices argument is checked to be sure that every input is not + too large for the input array along the selected dimension before the loop + calculations take place. + The loop implementation is handled using code that is very similar to the + reduce code repeated as many times as there are elements in the indices + input. + In particular: the first input pointer passed to the underlying 1-d computation +al loop points to the input array at the correct location indicated by the + index array. + In addition, the output pointer and the second input pointer passed to + the underlying 1-d loop point to the same position in memory. + The size of the 1-d computational loop is fixed to be the difference between + the current index and the next index (when the current index is the last + index, then the next index is assumed to be the length of the array along + the selected dimension). + In this way, the 1-d loop will implement a reduce over the specified indices. + +\end_layout + +\begin_layout Standard +Mis-aligned or a loop data-type that does not match the input and/or output + data-type is handled using buffered code where-in data is copied to a temporary + buffer and cast to the correct data-type if necessary prior to calling + the underlying 1-d function. + The temporary buffers are created in (element) sizes no bigger than the + user settable buffer-size value. + Thus, the loop must be flexible enough to call the underlying 1-d computational + loop enough times to complete the total calculation in chunks no bigger + than the buffer-size. + +\begin_inset LatexCommand index +name "ufunc|)" + +\end_inset + + +\end_layout + +\end_body +\end_document |