numpy 2.0.0
|
00001 #ifndef Py_UFUNCOBJECT_H 00002 #define Py_UFUNCOBJECT_H 00003 00004 #include <numpy/npy_math.h> 00005 00006 #ifdef __cplusplus 00007 extern "C" { 00008 #endif 00009 00010 /* The most generic inner loop for a standard element-wise ufunc */ 00011 typedef void (*PyUFuncGenericFunction) 00012 (char **args, 00013 npy_intp *dimensions, 00014 npy_intp *steps, 00015 void *innerloopdata); 00016 00017 /* 00018 * The most generic inner loop for a masked standard element-wise ufunc. 00019 * The mask data and step is at args[narg] and steps[narg], after all 00020 * the operands. 00021 */ 00022 typedef void (*PyUFuncGenericMaskedFunction) 00023 (char **args, 00024 npy_intp *dimensions, 00025 npy_intp *steps, 00026 NpyAuxData *innerloopdata); 00027 00028 /* Forward declaration for the type resolution function */ 00029 struct _tagPyUFuncObject; 00030 00031 /* 00032 * Given the operands for calling a ufunc, should determine the 00033 * calculation input and output data types and return an inner loop function. 00034 * This function should validate that the casting rule is being followed, 00035 * and fail if it is not. 00036 * 00037 * For backwards compatibility, the regular type resolution function does not 00038 * support auxiliary data with object semantics. The type resolution call 00039 * which returns a masked generic function returns a standard NpyAuxData 00040 * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros 00041 * work. 00042 * 00043 * ufunc: The ufunc object. 00044 * casting: The 'casting' parameter provided to the ufunc. 00045 * operands: An array of length (ufunc->nin + ufunc->nout), 00046 * with the output parameters possibly NULL. 00047 * type_tup: Either NULL, or the type_tup passed to the ufunc. 00048 * out_dtypes: An array which should be populated with new 00049 * references to (ufunc->nin + ufunc->nout) new 00050 * dtypes, one for each input and output. These 00051 * dtypes should all be in native-endian format. 00052 * out_innerloop: Should be populated with the correct ufunc inner 00053 * loop for the given type. 00054 * out_innerloopdata: Should be populated with the void* data to 00055 * be passed into the out_innerloop function. 00056 * 00057 * Should return 0 on success, -1 on failure (with exception set), 00058 * or -2 if Py_NotImplemented should be returned. 00059 */ 00060 typedef int (PyUFunc_TypeResolutionFunc)( 00061 struct _tagPyUFuncObject *ufunc, 00062 NPY_CASTING casting, 00063 PyArrayObject **operands, 00064 PyObject *type_tup, 00065 PyArray_Descr **out_dtypes, 00066 PyUFuncGenericFunction *out_innerloop, 00067 void **out_innerloopdata); 00068 typedef int (PyUFunc_TypeResolutionMaskedFunc)( 00069 struct _tagPyUFuncObject *ufunc, 00070 NPY_CASTING casting, 00071 PyArrayObject **operands, 00072 PyObject *type_tup, 00073 PyArray_Descr **out_dtypes, 00074 PyUFuncGenericMaskedFunction *out_innerloop, 00075 NpyAuxData **out_innerloopdata); 00076 00077 typedef struct _tagPyUFuncObject { 00078 PyObject_HEAD 00079 /* 00080 * nin: Number of inputs 00081 * nout: Number of outputs 00082 * nargs: Always nin + nout (Why is it stored?) 00083 */ 00084 int nin, nout, nargs; 00085 00086 /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */ 00087 int identity; 00088 00089 /* Array of one-dimensional core loops */ 00090 PyUFuncGenericFunction *functions; 00091 /* Array of funcdata that gets passed into the functions */ 00092 void **data; 00093 /* The number of elements in 'functions' and 'data' */ 00094 int ntypes; 00095 00096 /* Does not appear to be used */ 00097 int check_return; 00098 00099 /* The name of the ufunc */ 00100 char *name; 00101 00102 /* Array of type numbers, of size ('nargs' * 'ntypes') */ 00103 char *types; 00104 00105 /* Documentation string */ 00106 char *doc; 00107 00108 void *ptr; 00109 PyObject *obj; 00110 PyObject *userloops; 00111 00112 /* generalized ufunc parameters */ 00113 00114 /* 0 for scalar ufunc; 1 for generalized ufunc */ 00115 int core_enabled; 00116 /* number of distinct dimension names in signature */ 00117 int core_num_dim_ix; 00118 00119 /* 00120 * dimension indices of input/output argument k are stored in 00121 * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] 00122 */ 00123 00124 /* numbers of core dimensions of each argument */ 00125 int *core_num_dims; 00126 /* 00127 * dimension indices in a flatted form; indices 00128 * are in the range of [0,core_num_dim_ix) 00129 */ 00130 int *core_dim_ixs; 00131 /* 00132 * positions of 1st core dimensions of each 00133 * argument in core_dim_ixs 00134 */ 00135 int *core_offsets; 00136 /* signature string for printing purpose */ 00137 char *core_signature; 00138 00139 /* 00140 * A function which resolves the types and returns an inner loop. 00141 * This is used by the regular ufunc, the reduction operations 00142 * have a different set of rules. 00143 */ 00144 PyUFunc_TypeResolutionFunc *type_resolution_function; 00145 /* 00146 * A function which resolves the types and returns an inner loop. 00147 * This is used by the regular ufunc when it requires using 00148 * a mask to select which elements to compute. 00149 */ 00150 PyUFunc_TypeResolutionMaskedFunc *type_resolution_masked_function; 00151 } PyUFuncObject; 00152 00153 #include "arrayobject.h" 00154 00155 #define UFUNC_ERR_IGNORE 0 00156 #define UFUNC_ERR_WARN 1 00157 #define UFUNC_ERR_RAISE 2 00158 #define UFUNC_ERR_CALL 3 00159 #define UFUNC_ERR_PRINT 4 00160 #define UFUNC_ERR_LOG 5 00161 00162 /* Python side integer mask */ 00163 00164 #define UFUNC_MASK_DIVIDEBYZERO 0x07 00165 #define UFUNC_MASK_OVERFLOW 0x3f 00166 #define UFUNC_MASK_UNDERFLOW 0x1ff 00167 #define UFUNC_MASK_INVALID 0xfff 00168 00169 #define UFUNC_SHIFT_DIVIDEBYZERO 0 00170 #define UFUNC_SHIFT_OVERFLOW 3 00171 #define UFUNC_SHIFT_UNDERFLOW 6 00172 #define UFUNC_SHIFT_INVALID 9 00173 00174 00175 /* platform-dependent code translates floating point 00176 status to an integer sum of these values 00177 */ 00178 #define UFUNC_FPE_DIVIDEBYZERO 1 00179 #define UFUNC_FPE_OVERFLOW 2 00180 #define UFUNC_FPE_UNDERFLOW 4 00181 #define UFUNC_FPE_INVALID 8 00182 00183 /* Error mode that avoids look-up (no checking) */ 00184 #define UFUNC_ERR_DEFAULT 0 00185 00186 #define UFUNC_OBJ_ISOBJECT 1 00187 #define UFUNC_OBJ_NEEDS_API 2 00188 00189 /* Default user error mode */ 00190 #define UFUNC_ERR_DEFAULT2 \ 00191 (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) + \ 00192 (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) + \ 00193 (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID) 00194 00195 #if NPY_ALLOW_THREADS 00196 #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0) 00197 #define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0) 00198 #else 00199 #define NPY_LOOP_BEGIN_THREADS 00200 #define NPY_LOOP_END_THREADS 00201 #endif 00202 00203 #define PyUFunc_One 1 00204 #define PyUFunc_Zero 0 00205 #define PyUFunc_None -1 00206 00207 #define UFUNC_REDUCE 0 00208 #define UFUNC_ACCUMULATE 1 00209 #define UFUNC_REDUCEAT 2 00210 #define UFUNC_OUTER 3 00211 00212 00213 typedef struct { 00214 int nin; 00215 int nout; 00216 PyObject *callable; 00217 } PyUFunc_PyFuncData; 00218 00219 /* A linked-list of function information for 00220 user-defined 1-d loops. 00221 */ 00222 typedef struct _loop1d_info { 00223 PyUFuncGenericFunction func; 00224 void *data; 00225 int *arg_types; 00226 struct _loop1d_info *next; 00227 } PyUFunc_Loop1d; 00228 00229 00230 #include "__ufunc_api.h" 00231 00232 #define UFUNC_PYVALS_NAME "UFUNC_PYVALS" 00233 00234 #define UFUNC_CHECK_ERROR(arg) \ 00235 do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) || \ 00236 ((arg)->errormask && \ 00237 PyUFunc_checkfperr((arg)->errormask, \ 00238 (arg)->errobj, \ 00239 &(arg)->first))) \ 00240 goto fail;} while (0) 00241 00242 /* This code checks the IEEE status flags in a platform-dependent way */ 00243 /* Adapted from Numarray */ 00244 00245 #if (defined(__unix__) || defined(unix)) && !defined(USG) 00246 #include <sys/param.h> 00247 #endif 00248 00249 /* OSF/Alpha (Tru64) ---------------------------------------------*/ 00250 #if defined(__osf__) && defined(__alpha) 00251 00252 #include <machine/fpu.h> 00253 00254 #define UFUNC_CHECK_STATUS(ret) { \ 00255 unsigned long fpstatus; \ 00256 \ 00257 fpstatus = ieee_get_fp_control(); \ 00258 /* clear status bits as well as disable exception mode if on */ \ 00259 ieee_set_fp_control( 0 ); \ 00260 ret = ((IEEE_STATUS_DZE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \ 00261 | ((IEEE_STATUS_OVF & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \ 00262 | ((IEEE_STATUS_UNF & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \ 00263 | ((IEEE_STATUS_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \ 00264 } 00265 00266 /* MS Windows -----------------------------------------------------*/ 00267 #elif defined(_MSC_VER) 00268 00269 #include <float.h> 00270 00271 /* Clear the floating point exception default of Borland C++ */ 00272 #if defined(__BORLANDC__) 00273 #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM); 00274 #endif 00275 00276 #define UFUNC_CHECK_STATUS(ret) { \ 00277 int fpstatus = (int) _clearfp(); \ 00278 \ 00279 ret = ((SW_ZERODIVIDE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \ 00280 | ((SW_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \ 00281 | ((SW_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \ 00282 | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \ 00283 } 00284 00285 /* Solaris --------------------------------------------------------*/ 00286 /* --------ignoring SunOS ieee_flags approach, someone else can 00287 ** deal with that! */ 00288 #elif defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || \ 00289 (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || \ 00290 defined(__NetBSD__) 00291 #include <ieeefp.h> 00292 00293 #define UFUNC_CHECK_STATUS(ret) { \ 00294 int fpstatus; \ 00295 \ 00296 fpstatus = (int) fpgetsticky(); \ 00297 ret = ((FP_X_DZ & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \ 00298 | ((FP_X_OFL & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \ 00299 | ((FP_X_UFL & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \ 00300 | ((FP_X_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \ 00301 (void) fpsetsticky(0); \ 00302 } 00303 00304 #elif defined(__GLIBC__) || defined(__APPLE__) || \ 00305 defined(__CYGWIN__) || defined(__MINGW32__) || \ 00306 (defined(__FreeBSD__) && (__FreeBSD_version >= 502114)) 00307 00308 #if defined(__GLIBC__) || defined(__APPLE__) || \ 00309 defined(__MINGW32__) || defined(__FreeBSD__) 00310 #include <fenv.h> 00311 #elif defined(__CYGWIN__) 00312 #include "fenv/fenv.c" 00313 #endif 00314 00315 #define UFUNC_CHECK_STATUS(ret) { \ 00316 int fpstatus = (int) fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | \ 00317 FE_UNDERFLOW | FE_INVALID); \ 00318 ret = ((FE_DIVBYZERO & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \ 00319 | ((FE_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \ 00320 | ((FE_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \ 00321 | ((FE_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \ 00322 (void) feclearexcept(FE_DIVBYZERO | FE_OVERFLOW | \ 00323 FE_UNDERFLOW | FE_INVALID); \ 00324 } 00325 00326 #elif defined(_AIX) 00327 00328 #include <float.h> 00329 #include <fpxcp.h> 00330 00331 #define UFUNC_CHECK_STATUS(ret) { \ 00332 fpflag_t fpstatus; \ 00333 \ 00334 fpstatus = fp_read_flag(); \ 00335 ret = ((FP_DIV_BY_ZERO & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \ 00336 | ((FP_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \ 00337 | ((FP_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \ 00338 | ((FP_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \ 00339 fp_swap_flag(0); \ 00340 } 00341 00342 #else 00343 00344 #define NO_FLOATING_POINT_SUPPORT 00345 #define UFUNC_CHECK_STATUS(ret) { \ 00346 ret = 0; \ 00347 } 00348 00349 #endif 00350 00351 /* 00352 * THESE MACROS ARE DEPRECATED. 00353 * Use npy_set_floatstatus_* in the npymath library. 00354 */ 00355 #define generate_divbyzero_error() npy_set_floatstatus_divbyzero() 00356 #define generate_overflow_error() npy_set_floatstatus_overflow() 00357 00358 /* Make sure it gets defined if it isn't already */ 00359 #ifndef UFUNC_NOFPE 00360 #define UFUNC_NOFPE 00361 #endif 00362 00363 00364 #ifdef __cplusplus 00365 } 00366 #endif 00367 #endif /* !Py_UFUNCOBJECT_H */