ufuncobject.h
1 #ifndef NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ 2 #define NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ 3 4 #include <numpy/npy_math.h> 5 #include <numpy/npy_common.h> 6 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 11 /* 12 * The legacy generic inner loop for a standard element-wise or 13 * generalized ufunc. 14 */ 15 typedef void (*PyUFuncGenericFunction) 16 (char **args, 17 npy_intp const *dimensions, 18 npy_intp const *strides, 19 void *innerloopdata); 20 21 /* 22 * The most generic one-dimensional inner loop for 23 * a masked standard element-wise ufunc. "Masked" here means that it skips 24 * doing calculations on any items for which the maskptr array has a true 25 * value. 26 */ 27 typedef void (PyUFunc_MaskedStridedInnerLoopFunc)( 28 char **dataptrs, npy_intp *strides, 29 char *maskptr, npy_intp mask_stride, 30 npy_intp count, 31 NpyAuxData *innerloopdata); 32 33 /* Forward declaration for the type resolver and loop selector typedefs */ 34 struct _tagPyUFuncObject; 35 36 /* 37 * Given the operands for calling a ufunc, should determine the 38 * calculation input and output data types and return an inner loop function. 39 * This function should validate that the casting rule is being followed, 40 * and fail if it is not. 41 * 42 * For backwards compatibility, the regular type resolution function does not 43 * support auxiliary data with object semantics. The type resolution call 44 * which returns a masked generic function returns a standard NpyAuxData 45 * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros 46 * work. 47 * 48 * ufunc: The ufunc object. 49 * casting: The 'casting' parameter provided to the ufunc. 50 * operands: An array of length (ufunc->nin + ufunc->nout), 51 * with the output parameters possibly NULL. 52 * type_tup: Either NULL, or the type_tup passed to the ufunc. 53 * out_dtypes: An array which should be populated with new 54 * references to (ufunc->nin + ufunc->nout) new 55 * dtypes, one for each input and output. These 56 * dtypes should all be in native-endian format. 57 * 58 * Should return 0 on success, -1 on failure (with exception set), 59 * or -2 if Py_NotImplemented should be returned. 60 */ 61 typedef int (PyUFunc_TypeResolutionFunc)( 62 struct _tagPyUFuncObject *ufunc, 63 NPY_CASTING casting, 64 PyArrayObject **operands, 65 PyObject *type_tup, 66 PyArray_Descr **out_dtypes); 67 68 /* 69 * Legacy loop selector. (This should NOT normally be used and we can expect 70 * that only the `PyUFunc_DefaultLegacyInnerLoopSelector` is ever set). 71 * However, unlike the masked version, it probably still works. 72 * 73 * ufunc: The ufunc object. 74 * dtypes: An array which has been populated with dtypes, 75 * in most cases by the type resolution function 76 * for the same ufunc. 77 * out_innerloop: Should be populated with the correct ufunc inner 78 * loop for the given type. 79 * out_innerloopdata: Should be populated with the void* data to 80 * be passed into the out_innerloop function. 81 * out_needs_api: If the inner loop needs to use the Python API, 82 * should set the to 1, otherwise should leave 83 * this untouched. 84 */ 85 typedef int (PyUFunc_LegacyInnerLoopSelectionFunc)( 86 struct _tagPyUFuncObject *ufunc, 87 PyArray_Descr **dtypes, 88 PyUFuncGenericFunction *out_innerloop, 89 void **out_innerloopdata, 90 int *out_needs_api); 91 92 93 typedef struct _tagPyUFuncObject { 94 PyObject_HEAD 95 /* 96 * nin: Number of inputs 97 * nout: Number of outputs 98 * nargs: Always nin + nout (Why is it stored?) 99 */ 100 int nin, nout, nargs; 101 102 /* 103 * Identity for reduction, any of PyUFunc_One, PyUFunc_Zero 104 * PyUFunc_MinusOne, PyUFunc_None, PyUFunc_ReorderableNone, 105 * PyUFunc_IdentityValue. 106 */ 107 int identity; 108 109 /* Array of one-dimensional core loops */ 110 PyUFuncGenericFunction *functions; 111 /* Array of funcdata that gets passed into the functions */ 112 void **data; 113 /* The number of elements in 'functions' and 'data' */ 114 int ntypes; 115 116 /* Used to be unused field 'check_return' */ 117 int reserved1; 118 119 /* The name of the ufunc */ 120 const char *name; 121 122 /* Array of type numbers, of size ('nargs' * 'ntypes') */ 123 char *types; 124 125 /* Documentation string */ 126 const char *doc; 127 128 void *ptr; 129 PyObject *obj; 130 PyObject *userloops; 131 132 /* generalized ufunc parameters */ 133 134 /* 0 for scalar ufunc; 1 for generalized ufunc */ 135 int core_enabled; 136 /* number of distinct dimension names in signature */ 137 int core_num_dim_ix; 138 139 /* 140 * dimension indices of input/output argument k are stored in 141 * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] 142 */ 143 144 /* numbers of core dimensions of each argument */ 145 int *core_num_dims; 146 /* 147 * dimension indices in a flatted form; indices 148 * are in the range of [0,core_num_dim_ix) 149 */ 150 int *core_dim_ixs; 151 /* 152 * positions of 1st core dimensions of each 153 * argument in core_dim_ixs, equivalent to cumsum(core_num_dims) 154 */ 155 int *core_offsets; 156 /* signature string for printing purpose */ 157 char *core_signature; 158 159 /* 160 * A function which resolves the types and fills an array 161 * with the dtypes for the inputs and outputs. 162 */ 163 PyUFunc_TypeResolutionFunc *type_resolver; 164 /* 165 * A function which returns an inner loop written for 166 * NumPy 1.6 and earlier ufuncs. This is for backwards 167 * compatibility, and may be NULL if inner_loop_selector 168 * is specified. 169 */ 170 PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector; 171 /* 172 * This was blocked off to be the "new" inner loop selector in 1.7, 173 * but this was never implemented. (This is also why the above 174 * selector is called the "legacy" selector.) 175 */ 176 #ifndef Py_LIMITED_API 177 vectorcallfunc vectorcall; 178 #else 179 void *vectorcall; 180 #endif 181 182 /* Was previously the `PyUFunc_MaskedInnerLoopSelectionFunc` */ 183 void *_always_null_previously_masked_innerloop_selector; 184 185 /* 186 * List of flags for each operand when ufunc is called by nditer object. 187 * These flags will be used in addition to the default flags for each 188 * operand set by nditer object. 189 */ 190 npy_uint32 *op_flags; 191 192 /* 193 * List of global flags used when ufunc is called by nditer object. 194 * These flags will be used in addition to the default global flags 195 * set by nditer object. 196 */ 197 npy_uint32 iter_flags; 198 199 /* New in NPY_API_VERSION 0x0000000D and above */ 200 201 /* 202 * for each core_num_dim_ix distinct dimension names, 203 * the possible "frozen" size (-1 if not frozen). 204 */ 205 npy_intp *core_dim_sizes; 206 207 /* 208 * for each distinct core dimension, a set of UFUNC_CORE_DIM* flags 209 */ 210 npy_uint32 *core_dim_flags; 211 212 /* Identity for reduction, when identity == PyUFunc_IdentityValue */ 213 PyObject *identity_value; 214 215 /* New in NPY_API_VERSION 0x0000000F and above */ 216 217 /* New private fields related to dispatching */ 218 void *_dispatch_cache; 219 /* A PyListObject of `(tuple of DTypes, ArrayMethod/Promoter)` */ 220 PyObject *_loops; 221 } PyUFuncObject; 222 223 #include "arrayobject.h" 224 /* Generalized ufunc; 0x0001 reserved for possible use as CORE_ENABLED */ 225 /* the core dimension's size will be determined by the operands. */ 226 #define UFUNC_CORE_DIM_SIZE_INFERRED 0x0002 227 /* the core dimension may be absent */ 228 #define UFUNC_CORE_DIM_CAN_IGNORE 0x0004 229 /* flags inferred during execution */ 230 #define UFUNC_CORE_DIM_MISSING 0x00040000 231 232 #define UFUNC_ERR_IGNORE 0 233 #define UFUNC_ERR_WARN 1 234 #define UFUNC_ERR_RAISE 2 235 #define UFUNC_ERR_CALL 3 236 #define UFUNC_ERR_PRINT 4 237 #define UFUNC_ERR_LOG 5 238 239 /* Python side integer mask */ 240 241 #define UFUNC_MASK_DIVIDEBYZERO 0x07 242 #define UFUNC_MASK_OVERFLOW 0x3f 243 #define UFUNC_MASK_UNDERFLOW 0x1ff 244 #define UFUNC_MASK_INVALID 0xfff 245 246 #define UFUNC_SHIFT_DIVIDEBYZERO 0 247 #define UFUNC_SHIFT_OVERFLOW 3 248 #define UFUNC_SHIFT_UNDERFLOW 6 249 #define UFUNC_SHIFT_INVALID 9 250 251 252 #define UFUNC_OBJ_ISOBJECT 1 253 #define UFUNC_OBJ_NEEDS_API 2 254 255 /* Default user error mode */ 256 #define UFUNC_ERR_DEFAULT \ 257 (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) + \ 258 (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) + \ 259 (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID) 260 261 #if NPY_ALLOW_THREADS 262 #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0); 263 #define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0); 264 #else 265 #define NPY_LOOP_BEGIN_THREADS 266 #define NPY_LOOP_END_THREADS 267 #endif 268 269 /* 270 * UFunc has unit of 0, and the order of operations can be reordered 271 * This case allows reduction with multiple axes at once. 272 */ 273 #define PyUFunc_Zero 0 274 /* 275 * UFunc has unit of 1, and the order of operations can be reordered 276 * This case allows reduction with multiple axes at once. 277 */ 278 #define PyUFunc_One 1 279 /* 280 * UFunc has unit of -1, and the order of operations can be reordered 281 * This case allows reduction with multiple axes at once. Intended for 282 * bitwise_and reduction. 283 */ 284 #define PyUFunc_MinusOne 2 285 /* 286 * UFunc has no unit, and the order of operations cannot be reordered. 287 * This case does not allow reduction with multiple axes at once. 288 */ 289 #define PyUFunc_None -1 290 /* 291 * UFunc has no unit, and the order of operations can be reordered 292 * This case allows reduction with multiple axes at once. 293 */ 294 #define PyUFunc_ReorderableNone -2 295 /* 296 * UFunc unit is an identity_value, and the order of operations can be reordered 297 * This case allows reduction with multiple axes at once. 298 */ 299 #define PyUFunc_IdentityValue -3 300 301 302 #define UFUNC_REDUCE 0 303 #define UFUNC_ACCUMULATE 1 304 #define UFUNC_REDUCEAT 2 305 #define UFUNC_OUTER 3 306 307 308 typedef struct { 309 int nin; 310 int nout; 311 PyObject *callable; 312 } PyUFunc_PyFuncData; 313 314 /* A linked-list of function information for 315 user-defined 1-d loops. 316 */ 317 typedef struct _loop1d_info { 318 PyUFuncGenericFunction func; 319 void *data; 320 int *arg_types; 321 struct _loop1d_info *next; 322 int nargs; 323 PyArray_Descr **arg_dtypes; 324 } PyUFunc_Loop1d; 325 326 327 #include "__ufunc_api.h" 328 329 #define UFUNC_PYVALS_NAME "UFUNC_PYVALS" 330 331 /* 332 * THESE MACROS ARE DEPRECATED. 333 * Use npy_set_floatstatus_* in the npymath library. 334 */ 335 #define UFUNC_FPE_DIVIDEBYZERO NPY_FPE_DIVIDEBYZERO 336 #define UFUNC_FPE_OVERFLOW NPY_FPE_OVERFLOW 337 #define UFUNC_FPE_UNDERFLOW NPY_FPE_UNDERFLOW 338 #define UFUNC_FPE_INVALID NPY_FPE_INVALID 339 340 #define generate_divbyzero_error() npy_set_floatstatus_divbyzero() 341 #define generate_overflow_error() npy_set_floatstatus_overflow() 342 343 /* Make sure it gets defined if it isn't already */ 344 #ifndef UFUNC_NOFPE 345 /* Clear the floating point exception default of Borland C++ */ 346 #if defined(__BORLANDC__) 347 #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM); 348 #else 349 #define UFUNC_NOFPE 350 #endif 351 #endif 352 353 #ifdef __cplusplus 354 } 355 #endif 356 357 #endif /* NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ */