User guide

NumPy User Guide, Release 1.9.0
Registering a casting function
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.
void castfunc( void
*
from, void
*
to, npy_intp n, void
*
fromarr,
void
*
toarr)
Cast n elements from one type to 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).
An example castfunc is:
static void
double_to_float(double
*
from, float
*
to, npy_intp n,
void
*
ig1, void
*
ig2);
while (n--) {
(
*
to++) = (double)
*
(from++);
}
This could then be registered to convert doubles to floats using the code:
doub = PyArray_DescrFromType(NPY_DOUBLE);
PyArray_RegisterCastFunc(doub, NPY_FLOAT,
(PyArray_VectorUnaryFunc
*
)double_to_float);
Py_DECREF(doub);
Registering coercion rules
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 PyArray_RegisterCanCast (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 NPY_NOSCALAR for the scalarkind argument.
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 ”.f 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 NPY_NOSCALAR.
Registering a ufunc loop
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.
Before you can register a 1-d loop for a ufunc, the ufunc must be previously created. Then you call
PyUFunc_RegisterLoopForType (...) with the information needed for the loop. The return value of this func-
tion is 0 if the process was successful and -1 with an error condition set if it was not successful.
102 Chapter 5. Using Numpy C-API