numpy
2.0.0
|
00001 #ifndef Py_UFUNCOBJECT_H 00002 #define Py_UFUNCOBJECT_H 00003 00004 #include <numpy/npy_math.h> 00005 #include <numpy/npy_common.h> 00006 00007 #ifdef __cplusplus 00008 extern "C" { 00009 #endif 00010 00011 /* 00012 * The legacy generic inner loop for a standard element-wise or 00013 * generalized ufunc. 00014 */ 00015 typedef void (*PyUFuncGenericFunction) 00016 (char **args, 00017 npy_intp *dimensions, 00018 npy_intp *strides, 00019 void *innerloopdata); 00020 00021 /* 00022 * The most generic one-dimensional inner loop for 00023 * a masked standard element-wise ufunc. "Masked" here means that it skips 00024 * doing calculations on any items for which the maskptr array has a true 00025 * value. 00026 */ 00027 typedef void (PyUFunc_MaskedStridedInnerLoopFunc)( 00028 char **dataptrs, npy_intp *strides, 00029 char *maskptr, npy_intp mask_stride, 00030 npy_intp count, 00031 NpyAuxData *innerloopdata); 00032 00033 /* Forward declaration for the type resolver and loop selector typedefs */ 00034 struct _tagPyUFuncObject; 00035 00036 /* 00037 * Given the operands for calling a ufunc, should determine the 00038 * calculation input and output data types and return an inner loop function. 00039 * This function should validate that the casting rule is being followed, 00040 * and fail if it is not. 00041 * 00042 * For backwards compatibility, the regular type resolution function does not 00043 * support auxiliary data with object semantics. The type resolution call 00044 * which returns a masked generic function returns a standard NpyAuxData 00045 * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros 00046 * work. 00047 * 00048 * ufunc: The ufunc object. 00049 * casting: The 'casting' parameter provided to the ufunc. 00050 * operands: An array of length (ufunc->nin + ufunc->nout), 00051 * with the output parameters possibly NULL. 00052 * type_tup: Either NULL, or the type_tup passed to the ufunc. 00053 * out_dtypes: An array which should be populated with new 00054 * references to (ufunc->nin + ufunc->nout) new 00055 * dtypes, one for each input and output. These 00056 * dtypes should all be in native-endian format. 00057 * 00058 * Should return 0 on success, -1 on failure (with exception set), 00059 * or -2 if Py_NotImplemented should be returned. 00060 */ 00061 typedef int (PyUFunc_TypeResolutionFunc)( 00062 struct _tagPyUFuncObject *ufunc, 00063 NPY_CASTING casting, 00064 PyArrayObject **operands, 00065 PyObject *type_tup, 00066 PyArray_Descr **out_dtypes); 00067 00068 /* 00069 * Given an array of DTypes as returned by the PyUFunc_TypeResolutionFunc, 00070 * and an array of fixed strides (the array will contain NPY_MAX_INTP for 00071 * strides which are not necessarily fixed), returns an inner loop 00072 * with associated auxiliary data. 00073 * 00074 * For backwards compatibility, there is a variant of the inner loop 00075 * selection which returns an inner loop irrespective of the strides, 00076 * and with a void* static auxiliary data instead of an NpyAuxData * 00077 * dynamically allocatable auxiliary data. 00078 * 00079 * ufunc: The ufunc object. 00080 * dtypes: An array which has been populated with dtypes, 00081 * in most cases by the type resolution funciton 00082 * for the same ufunc. 00083 * fixed_strides: For each input/output, either the stride that 00084 * will be used every time the function is called 00085 * or NPY_MAX_INTP if the stride might change or 00086 * is not known ahead of time. The loop selection 00087 * function may use this stride to pick inner loops 00088 * which are optimized for contiguous or 0-stride 00089 * cases. 00090 * out_innerloop: Should be populated with the correct ufunc inner 00091 * loop for the given type. 00092 * out_innerloopdata: Should be populated with the void* data to 00093 * be passed into the out_innerloop function. 00094 * out_needs_api: If the inner loop needs to use the Python API, 00095 * should set the to 1, otherwise should leave 00096 * this untouched. 00097 */ 00098 typedef int (PyUFunc_LegacyInnerLoopSelectionFunc)( 00099 struct _tagPyUFuncObject *ufunc, 00100 PyArray_Descr **dtypes, 00101 PyUFuncGenericFunction *out_innerloop, 00102 void **out_innerloopdata, 00103 int *out_needs_api); 00104 typedef int (PyUFunc_MaskedInnerLoopSelectionFunc)( 00105 struct _tagPyUFuncObject *ufunc, 00106 PyArray_Descr **dtypes, 00107 PyArray_Descr *mask_dtype, 00108 npy_intp *fixed_strides, 00109 npy_intp fixed_mask_stride, 00110 PyUFunc_MaskedStridedInnerLoopFunc **out_innerloop, 00111 NpyAuxData **out_innerloopdata, 00112 int *out_needs_api); 00113 00114 typedef struct _tagPyUFuncObject { 00115 PyObject_HEAD 00116 /* 00117 * nin: Number of inputs 00118 * nout: Number of outputs 00119 * nargs: Always nin + nout (Why is it stored?) 00120 */ 00121 int nin, nout, nargs; 00122 00123 /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */ 00124 int identity; 00125 00126 /* Array of one-dimensional core loops */ 00127 PyUFuncGenericFunction *functions; 00128 /* Array of funcdata that gets passed into the functions */ 00129 void **data; 00130 /* The number of elements in 'functions' and 'data' */ 00131 int ntypes; 00132 00133 /* Used to be unused field 'check_return' */ 00134 int reserved1; 00135 00136 /* The name of the ufunc */ 00137 const char *name; 00138 00139 /* Array of type numbers, of size ('nargs' * 'ntypes') */ 00140 char *types; 00141 00142 /* Documentation string */ 00143 const char *doc; 00144 00145 void *ptr; 00146 PyObject *obj; 00147 PyObject *userloops; 00148 00149 /* generalized ufunc parameters */ 00150 00151 /* 0 for scalar ufunc; 1 for generalized ufunc */ 00152 int core_enabled; 00153 /* number of distinct dimension names in signature */ 00154 int core_num_dim_ix; 00155 00156 /* 00157 * dimension indices of input/output argument k are stored in 00158 * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] 00159 */ 00160 00161 /* numbers of core dimensions of each argument */ 00162 int *core_num_dims; 00163 /* 00164 * dimension indices in a flatted form; indices 00165 * are in the range of [0,core_num_dim_ix) 00166 */ 00167 int *core_dim_ixs; 00168 /* 00169 * positions of 1st core dimensions of each 00170 * argument in core_dim_ixs 00171 */ 00172 int *core_offsets; 00173 /* signature string for printing purpose */ 00174 char *core_signature; 00175 00176 /* 00177 * A function which resolves the types and fills an array 00178 * with the dtypes for the inputs and outputs. 00179 */ 00180 PyUFunc_TypeResolutionFunc *type_resolver; 00181 /* 00182 * A function which returns an inner loop written for 00183 * NumPy 1.6 and earlier ufuncs. This is for backwards 00184 * compatibility, and may be NULL if inner_loop_selector 00185 * is specified. 00186 */ 00187 PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector; 00188 /* 00189 * This was blocked off to be the "new" inner loop selector in 1.7, 00190 * but this was never implemented. (This is also why the above 00191 * selector is called the "legacy" selector.) 00192 */ 00193 void *reserved2; 00194 /* 00195 * A function which returns a masked inner loop for the ufunc. 00196 */ 00197 PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector; 00198 00199 /* 00200 * List of flags for each operand when ufunc is called by nditer object. 00201 * These flags will be used in addition to the default flags for each 00202 * operand set by nditer object. 00203 */ 00204 npy_uint32 *op_flags; 00205 00206 /* 00207 * List of global flags used when ufunc is called by nditer object. 00208 * These flags will be used in addition to the default global flags 00209 * set by nditer object. 00210 */ 00211 npy_uint32 iter_flags; 00212 } PyUFuncObject; 00213 00214 #include "arrayobject.h" 00215 00216 #define UFUNC_ERR_IGNORE 0 00217 #define UFUNC_ERR_WARN 1 00218 #define UFUNC_ERR_RAISE 2 00219 #define UFUNC_ERR_CALL 3 00220 #define UFUNC_ERR_PRINT 4 00221 #define UFUNC_ERR_LOG 5 00222 00223 /* Python side integer mask */ 00224 00225 #define UFUNC_MASK_DIVIDEBYZERO 0x07 00226 #define UFUNC_MASK_OVERFLOW 0x3f 00227 #define UFUNC_MASK_UNDERFLOW 0x1ff 00228 #define UFUNC_MASK_INVALID 0xfff 00229 00230 #define UFUNC_SHIFT_DIVIDEBYZERO 0 00231 #define UFUNC_SHIFT_OVERFLOW 3 00232 #define UFUNC_SHIFT_UNDERFLOW 6 00233 #define UFUNC_SHIFT_INVALID 9 00234 00235 00236 #define UFUNC_OBJ_ISOBJECT 1 00237 #define UFUNC_OBJ_NEEDS_API 2 00238 00239 /* Default user error mode */ 00240 #define UFUNC_ERR_DEFAULT \ 00241 (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) + \ 00242 (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) + \ 00243 (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID) 00244 00245 #if NPY_ALLOW_THREADS 00246 #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0); 00247 #define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0); 00248 #else 00249 #define NPY_LOOP_BEGIN_THREADS 00250 #define NPY_LOOP_END_THREADS 00251 #endif 00252 00253 /* 00254 * UFunc has unit of 0, and the order of operations can be reordered 00255 * This case allows reduction with multiple axes at once. 00256 */ 00257 #define PyUFunc_Zero 0 00258 /* 00259 * UFunc has unit of 1, and the order of operations can be reordered 00260 * This case allows reduction with multiple axes at once. 00261 */ 00262 #define PyUFunc_One 1 00263 /* 00264 * UFunc has unit of -1, and the order of operations can be reordered 00265 * This case allows reduction with multiple axes at once. Intended for 00266 * bitwise_and reduction. 00267 */ 00268 #define PyUFunc_MinusOne 2 00269 /* 00270 * UFunc has no unit, and the order of operations cannot be reordered. 00271 * This case does not allow reduction with multiple axes at once. 00272 */ 00273 #define PyUFunc_None -1 00274 /* 00275 * UFunc has no unit, and the order of operations can be reordered 00276 * This case allows reduction with multiple axes at once. 00277 */ 00278 #define PyUFunc_ReorderableNone -2 00279 00280 #define UFUNC_REDUCE 0 00281 #define UFUNC_ACCUMULATE 1 00282 #define UFUNC_REDUCEAT 2 00283 #define UFUNC_OUTER 3 00284 00285 00286 typedef struct { 00287 int nin; 00288 int nout; 00289 PyObject *callable; 00290 } PyUFunc_PyFuncData; 00291 00292 /* A linked-list of function information for 00293 user-defined 1-d loops. 00294 */ 00295 typedef struct _loop1d_info { 00296 PyUFuncGenericFunction func; 00297 void *data; 00298 int *arg_types; 00299 struct _loop1d_info *next; 00300 int nargs; 00301 PyArray_Descr **arg_dtypes; 00302 } PyUFunc_Loop1d; 00303 00304 00305 #include "__ufunc_api.h" 00306 00307 #define UFUNC_PYVALS_NAME "UFUNC_PYVALS" 00308 00309 #define UFUNC_CHECK_ERROR(arg) \ 00310 do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) || \ 00311 ((arg)->errormask && \ 00312 PyUFunc_checkfperr((arg)->errormask, \ 00313 (arg)->errobj, \ 00314 &(arg)->first))) \ 00315 goto fail;} while (0) 00316 00317 00318 /* keep in sync with ieee754.c.src */ 00319 #if defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || \ 00320 (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || \ 00321 defined(__NetBSD__) || \ 00322 defined(__GLIBC__) || defined(__APPLE__) || \ 00323 defined(__CYGWIN__) || defined(__MINGW32__) || \ 00324 (defined(__FreeBSD__) && (__FreeBSD_version >= 502114)) || \ 00325 defined(_AIX) || \ 00326 defined(_MSC_VER) || \ 00327 defined(__osf__) && defined(__alpha) 00328 #else 00329 #define NO_FLOATING_POINT_SUPPORT 00330 #endif 00331 00332 00333 /* 00334 * THESE MACROS ARE DEPRECATED. 00335 * Use npy_set_floatstatus_* in the npymath library. 00336 */ 00337 #define UFUNC_FPE_DIVIDEBYZERO NPY_FPE_DIVIDEBYZERO 00338 #define UFUNC_FPE_OVERFLOW NPY_FPE_OVERFLOW 00339 #define UFUNC_FPE_UNDERFLOW NPY_FPE_UNDERFLOW 00340 #define UFUNC_FPE_INVALID NPY_FPE_INVALID 00341 00342 #define UFUNC_CHECK_STATUS(ret) \ 00343 { \ 00344 ret = npy_clear_floatstatus(); \ 00345 } 00346 #define generate_divbyzero_error() npy_set_floatstatus_divbyzero() 00347 #define generate_overflow_error() npy_set_floatstatus_overflow() 00348 00349 /* Make sure it gets defined if it isn't already */ 00350 #ifndef UFUNC_NOFPE 00351 /* Clear the floating point exception default of Borland C++ */ 00352 #if defined(__BORLANDC__) 00353 #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM); 00354 #else 00355 #define UFUNC_NOFPE 00356 #endif 00357 #endif 00358 00359 00360 #ifdef __cplusplus 00361 } 00362 #endif 00363 #endif /* !Py_UFUNCOBJECT_H */