User guide
NumPy User Guide, Release 1.9.0
while(size--) {
ptr1 = PyArray_MultiIter_DATA(mobj, 0);
ptr2 = PyArray_MultiIter_DATA(mobj, 1);
/
*
code using contents of ptr1 and ptr2
*
/
PyArray_MultiIter_NEXT(mobj);
}
The function PyArray_RemoveSmallest ( multi ) 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.
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.
5.4.2 User-defined data-types
NumPy comes with 24 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 “safely” to and
from this new type or not will always return “can cast” 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.
Adding the new data-type
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:
typedef struct {
PyObject_HEAD;
some_data_type obval;
/
*
the name can be whatever you want
*
/
} PySomeDataTypeObject;
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
”.f” member must be defined: nonzero, copyswap, copyswapn, setitem, getitem, and cast. The more functions in the
”.f” 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 PyArray_InitArrFuncs (f).
Once a new PyArray_Descr structure is created and filled with the needed information and useful functions you
call PyArray_RegisterDataType (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
PyArray_TypeNumFromName ).
5.4. Beyond the Basics 101