#ifndef NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ #define NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* * The legacy generic inner loop for a standard element-wise or * generalized ufunc. */ typedef void (*PyUFuncGenericFunction) (char **args, npy_intp const *dimensions, npy_intp const *strides, void *innerloopdata); /* * The most generic one-dimensional inner loop for * a masked standard element-wise ufunc. "Masked" here means that it skips * doing calculations on any items for which the maskptr array has a true * value. */ typedef void (PyUFunc_MaskedStridedInnerLoopFunc)( char **dataptrs, npy_intp *strides, char *maskptr, npy_intp mask_stride, npy_intp count, NpyAuxData *innerloopdata); /* Forward declaration for the type resolver and loop selector typedefs */ struct _tagPyUFuncObject; /* * Given the operands for calling a ufunc, should determine the * calculation input and output data types and return an inner loop function. * This function should validate that the casting rule is being followed, * and fail if it is not. * * For backwards compatibility, the regular type resolution function does not * support auxiliary data with object semantics. The type resolution call * which returns a masked generic function returns a standard NpyAuxData * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros * work. * * ufunc: The ufunc object. * casting: The 'casting' parameter provided to the ufunc. * operands: An array of length (ufunc->nin + ufunc->nout), * with the output parameters possibly NULL. * type_tup: Either NULL, or the type_tup passed to the ufunc. * out_dtypes: An array which should be populated with new * references to (ufunc->nin + ufunc->nout) new * dtypes, one for each input and output. These * dtypes should all be in native-endian format. * * Should return 0 on success, -1 on failure (with exception set), * or -2 if Py_NotImplemented should be returned. */ typedef int (PyUFunc_TypeResolutionFunc)( struct _tagPyUFuncObject *ufunc, NPY_CASTING casting, PyArrayObject **operands, PyObject *type_tup, PyArray_Descr **out_dtypes); /* * This is the signature for the functions that may be assigned to the * `process_core_dims_func` field of the PyUFuncObject structure. * Implementation of this function is optional. This function is only used * by generalized ufuncs (i.e. those with the field `core_enabled` set to 1). * The function is called by the ufunc during the processing of the arguments * of a call of the ufunc. The function can check the core dimensions of the * input and output arrays and return -1 with an exception set if any * requirements are not satisfied. If the caller of the ufunc didn't provide * output arrays, the core dimensions associated with the output arrays (i.e. * those that are not also used in input arrays) will have the value -1 in * `core_dim_sizes`. This function can replace any output core dimensions * that are -1 with a value that is appropriate for the ufunc. * * Parameter Description * --------------- ------------------------------------------------------ * ufunc The ufunc object * core_dim_sizes An array with length `ufunc->core_num_dim_ix`. * The core dimensions of the arrays passed to the ufunc * will have been set. If the caller of the ufunc didn't * provide the output array(s), the output-only core * dimensions will have the value -1. * * The function must not change any element in `core_dim_sizes` that is * not -1 on input. Doing so will result in incorrect output from the * ufunc, and could result in a crash of the Python interpreter. * * The function must return 0 on success, -1 on failure (with an exception * set). */ typedef int (PyUFunc_ProcessCoreDimsFunc)( struct _tagPyUFuncObject *ufunc, npy_intp *core_dim_sizes); typedef struct _tagPyUFuncObject { PyObject_HEAD /* * nin: Number of inputs * nout: Number of outputs * nargs: Always nin + nout (Why is it stored?) */ int nin, nout, nargs; /* * Identity for reduction, any of PyUFunc_One, PyUFunc_Zero * PyUFunc_MinusOne, PyUFunc_None, PyUFunc_ReorderableNone, * PyUFunc_IdentityValue. */ int identity; /* Array of one-dimensional core loops */ PyUFuncGenericFunction *functions; /* Array of funcdata that gets passed into the functions */ void *const *data; /* The number of elements in 'functions' and 'data' */ int ntypes; /* Used to be unused field 'check_return' */ int reserved1; /* The name of the ufunc */ const char *name; /* Array of type numbers, of size ('nargs' * 'ntypes') */ const char *types; /* Documentation string */ const char *doc; void *ptr; PyObject *obj; PyObject *userloops; /* generalized ufunc parameters */ /* 0 for scalar ufunc; 1 for generalized ufunc */ int core_enabled; /* number of distinct dimension names in signature */ int core_num_dim_ix; /* * dimension indices of input/output argument k are stored in * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] */ /* numbers of core dimensions of each argument */ int *core_num_dims; /* * dimension indices in a flatted form; indices * are in the range of [0,core_num_dim_ix) */ int *core_dim_ixs; /* * positions of 1st core dimensions of each * argument in core_dim_ixs, equivalent to cumsum(core_num_dims) */ int *core_offsets; /* signature string for printing purpose */ char *core_signature; /* * A function which resolves the types and fills an array * with the dtypes for the inputs and outputs. */ PyUFunc_TypeResolutionFunc *type_resolver; /* A dictionary to monkeypatch ufuncs */ PyObject *dict; /* * This was blocked off to be the "new" inner loop selector in 1.7, * but this was never implemented. (This is also why the above * selector is called the "legacy" selector.) */ #ifndef Py_LIMITED_API vectorcallfunc vectorcall; #else void *vectorcall; #endif /* Was previously the `PyUFunc_MaskedInnerLoopSelectionFunc` */ void *reserved3; /* * List of flags for each operand when ufunc is called by nditer object. * These flags will be used in addition to the default flags for each * operand set by nditer object. */ npy_uint32 *op_flags; /* * List of global flags used when ufunc is called by nditer object. * These flags will be used in addition to the default global flags * set by nditer object. */ npy_uint32 iter_flags; /* New in NPY_API_VERSION 0x0000000D and above */ #if NPY_FEATURE_VERSION >= NPY_1_16_API_VERSION /* * for each core_num_dim_ix distinct dimension names, * the possible "frozen" size (-1 if not frozen). */ npy_intp *core_dim_sizes; /* * for each distinct core dimension, a set of UFUNC_CORE_DIM* flags */ npy_uint32 *core_dim_flags; /* Identity for reduction, when identity == PyUFunc_IdentityValue */ PyObject *identity_value; #endif /* NPY_FEATURE_VERSION >= NPY_1_16_API_VERSION */ /* New in NPY_API_VERSION 0x0000000F and above */ #if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION /* New private fields related to dispatching */ void *_dispatch_cache; /* A PyListObject of `(tuple of DTypes, ArrayMethod/Promoter)` */ PyObject *_loops; #endif #if NPY_FEATURE_VERSION >= NPY_2_1_API_VERSION /* * Optional function to process core dimensions of a gufunc. */ PyUFunc_ProcessCoreDimsFunc *process_core_dims_func; #endif } PyUFuncObject; #include "arrayobject.h" /* Generalized ufunc; 0x0001 reserved for possible use as CORE_ENABLED */ /* the core dimension's size will be determined by the operands. */ #define UFUNC_CORE_DIM_SIZE_INFERRED 0x0002 /* the core dimension may be absent */ #define UFUNC_CORE_DIM_CAN_IGNORE 0x0004 /* flags inferred during execution */ #define UFUNC_CORE_DIM_MISSING 0x00040000 #define UFUNC_OBJ_ISOBJECT 1 #define UFUNC_OBJ_NEEDS_API 2 #if NPY_ALLOW_THREADS #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0); #define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0); #else #define NPY_LOOP_BEGIN_THREADS #define NPY_LOOP_END_THREADS #endif /* * UFunc has unit of 0, and the order of operations can be reordered * This case allows reduction with multiple axes at once. */ #define PyUFunc_Zero 0 /* * UFunc has unit of 1, and the order of operations can be reordered * This case allows reduction with multiple axes at once. */ #define PyUFunc_One 1 /* * UFunc has unit of -1, and the order of operations can be reordered * This case allows reduction with multiple axes at once. Intended for * bitwise_and reduction. */ #define PyUFunc_MinusOne 2 /* * UFunc has no unit, and the order of operations cannot be reordered. * This case does not allow reduction with multiple axes at once. */ #define PyUFunc_None -1 /* * UFunc has no unit, and the order of operations can be reordered * This case allows reduction with multiple axes at once. */ #define PyUFunc_ReorderableNone -2 /* * UFunc unit is an identity_value, and the order of operations can be reordered * This case allows reduction with multiple axes at once. */ #define PyUFunc_IdentityValue -3 #define UFUNC_REDUCE 0 #define UFUNC_ACCUMULATE 1 #define UFUNC_REDUCEAT 2 #define UFUNC_OUTER 3 typedef struct { int nin; int nout; PyObject *callable; } PyUFunc_PyFuncData; /* A linked-list of function information for user-defined 1-d loops. */ typedef struct _loop1d_info { PyUFuncGenericFunction func; void *data; int *arg_types; struct _loop1d_info *next; int nargs; PyArray_Descr **arg_dtypes; } PyUFunc_Loop1d; #define UFUNC_PYVALS_NAME "UFUNC_PYVALS" /* THESE MACROS ARE DEPRECATED. * Use npy_set_floatstatus_* in the npymath library. */ #define UFUNC_FPE_DIVIDEBYZERO NPY_FPE_DIVIDEBYZERO #define UFUNC_FPE_OVERFLOW NPY_FPE_OVERFLOW #define UFUNC_FPE_UNDERFLOW NPY_FPE_UNDERFLOW #define UFUNC_FPE_INVALID NPY_FPE_INVALID /* Make sure it gets defined if it isn't already */ #ifndef UFUNC_NOFPE /* Clear the floating point exception default of Borland C++ */ #if defined(__BORLANDC__) #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM); #else #define UFUNC_NOFPE #endif #endif #include "__ufunc_api.h" #ifdef __cplusplus } #endif #endif /* NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ */