numpy 2.0.0
include/numpy/ufuncobject.h
Go to the documentation of this file.
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 typedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *);
00011 
00012 typedef struct {
00013         PyObject_HEAD
00014         /*
00015          * nin: Number of inputs
00016          * nout: Number of outputs
00017          * nargs: Always nin + nout (Why is it stored?)
00018          */
00019         int nin, nout, nargs;
00020 
00021         /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */
00022         int identity;
00023 
00024         /* Array of one-dimensional core loops */
00025         PyUFuncGenericFunction *functions;
00026         /* Array of funcdata that gets passed into the functions */
00027         void **data;
00028         /* The number of elements in 'functions' and 'data' */
00029         int ntypes;
00030 
00031         /* Does not appear to be used */
00032         int check_return;
00033 
00034         /* The name of the ufunc */
00035         char *name;
00036 
00037         /* Array of type numbers, of size ('nargs' * 'ntypes') */
00038         char *types;
00039 
00040         /* Documentation string */
00041         char *doc;
00042 
00043         void *ptr;
00044         PyObject *obj;
00045         PyObject *userloops;
00046     
00047         /* generalized ufunc parameters */
00048 
00049         /* 0 for scalar ufunc; 1 for generalized ufunc */
00050         int core_enabled;
00051         /* number of distinct dimension names in signature */
00052         int core_num_dim_ix;
00053  
00054         /*
00055          * dimension indices of input/output argument k are stored in
00056          * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1]
00057          */
00058 
00059         /* numbers of core dimensions of each argument */
00060         int *core_num_dims;
00061         /*
00062          * dimension indices in a flatted form; indices
00063          * are in the range of [0,core_num_dim_ix)
00064          */
00065         int *core_dim_ixs;
00066         /*
00067          * positions of 1st core dimensions of each
00068          * argument in core_dim_ixs
00069          */
00070         int *core_offsets;
00071         /* signature string for printing purpose */
00072         char *core_signature;
00073 } PyUFuncObject;
00074 
00075 #include "arrayobject.h"
00076 
00077 #define UFUNC_ERR_IGNORE 0
00078 #define UFUNC_ERR_WARN   1
00079 #define UFUNC_ERR_RAISE  2
00080 #define UFUNC_ERR_CALL   3
00081 #define UFUNC_ERR_PRINT  4
00082 #define UFUNC_ERR_LOG    5
00083 
00084         /* Python side integer mask */
00085 
00086 #define UFUNC_MASK_DIVIDEBYZERO 0x07
00087 #define UFUNC_MASK_OVERFLOW 0x3f
00088 #define UFUNC_MASK_UNDERFLOW 0x1ff
00089 #define UFUNC_MASK_INVALID 0xfff
00090 
00091 #define UFUNC_SHIFT_DIVIDEBYZERO 0
00092 #define UFUNC_SHIFT_OVERFLOW     3
00093 #define UFUNC_SHIFT_UNDERFLOW    6
00094 #define UFUNC_SHIFT_INVALID      9
00095 
00096 
00097 /* platform-dependent code translates floating point
00098    status to an integer sum of these values
00099 */
00100 #define UFUNC_FPE_DIVIDEBYZERO  1
00101 #define UFUNC_FPE_OVERFLOW      2
00102 #define UFUNC_FPE_UNDERFLOW     4
00103 #define UFUNC_FPE_INVALID       8
00104 
00105 /* Error mode that avoids look-up (no checking) */
00106 #define UFUNC_ERR_DEFAULT       0
00107 
00108 #define UFUNC_OBJ_ISOBJECT      1
00109 #define UFUNC_OBJ_NEEDS_API     2
00110 
00111    /* Default user error mode */
00112 #define UFUNC_ERR_DEFAULT2                               \
00113         (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) +  \
00114         (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) +      \
00115         (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID)
00116 
00117 #if NPY_ALLOW_THREADS
00118 #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0)
00119 #define NPY_LOOP_END_THREADS   do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0)
00120 #else
00121 #define NPY_LOOP_BEGIN_THREADS
00122 #define NPY_LOOP_END_THREADS
00123 #endif
00124 
00125 #define PyUFunc_One 1
00126 #define PyUFunc_Zero 0
00127 #define PyUFunc_None -1
00128 
00129 #define UFUNC_REDUCE 0
00130 #define UFUNC_ACCUMULATE 1
00131 #define UFUNC_REDUCEAT 2
00132 #define UFUNC_OUTER 3
00133 
00134 
00135 typedef struct {
00136         int nin;
00137         int nout;
00138         PyObject *callable;
00139 } PyUFunc_PyFuncData;
00140 
00141 /* A linked-list of function information for
00142    user-defined 1-d loops.
00143  */
00144 typedef struct _loop1d_info {
00145         PyUFuncGenericFunction func;
00146         void *data;
00147         int *arg_types;
00148         struct _loop1d_info *next;
00149 } PyUFunc_Loop1d;
00150 
00151 
00152 #include "__ufunc_api.h"
00153 
00154 #define UFUNC_PYVALS_NAME "UFUNC_PYVALS"
00155 
00156 #define UFUNC_CHECK_ERROR(arg)                                          \
00157         do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) ||                         \
00158             ((arg)->errormask &&                                        \
00159              PyUFunc_checkfperr((arg)->errormask,                       \
00160                                 (arg)->errobj,                          \
00161                                 &(arg)->first)))                        \
00162                 goto fail;} while (0)
00163 
00164 /* This code checks the IEEE status flags in a platform-dependent way */
00165 /* Adapted from Numarray  */
00166 
00167 #if (defined(__unix__) || defined(unix)) && !defined(USG)
00168 #include <sys/param.h>
00169 #endif
00170 
00171 /*  OSF/Alpha (Tru64)  ---------------------------------------------*/
00172 #if defined(__osf__) && defined(__alpha)
00173 
00174 #include <machine/fpu.h>
00175 
00176 #define UFUNC_CHECK_STATUS(ret) {               \
00177         unsigned long fpstatus;                 \
00178                                                 \
00179         fpstatus = ieee_get_fp_control();                               \
00180         /* clear status bits as well as disable exception mode if on */ \
00181         ieee_set_fp_control( 0 );                                       \
00182         ret = ((IEEE_STATUS_DZE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
00183                 | ((IEEE_STATUS_OVF & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
00184                 | ((IEEE_STATUS_UNF & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
00185                 | ((IEEE_STATUS_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \
00186         }
00187 
00188 /* MS Windows -----------------------------------------------------*/
00189 #elif defined(_MSC_VER)
00190 
00191 #include <float.h>
00192 
00193   /* Clear the floating point exception default of Borland C++ */
00194 #if defined(__BORLANDC__)
00195 #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM);
00196 #endif
00197 
00198 #define UFUNC_CHECK_STATUS(ret) {                \
00199         int fpstatus = (int) _clearfp();                        \
00200                                                                         \
00201         ret = ((SW_ZERODIVIDE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
00202                 | ((SW_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)   \
00203                 | ((SW_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
00204                 | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0);    \
00205         }
00206 
00207 /* Solaris --------------------------------------------------------*/
00208 /* --------ignoring SunOS ieee_flags approach, someone else can
00209 **         deal with that! */
00210 #elif defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || \
00211       (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || \
00212       defined(__NetBSD__)
00213 #include <ieeefp.h>
00214 
00215 #define UFUNC_CHECK_STATUS(ret) {                               \
00216         int fpstatus;                                           \
00217                                                                 \
00218         fpstatus = (int) fpgetsticky();                                 \
00219         ret = ((FP_X_DZ  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0)      \
00220                 | ((FP_X_OFL & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)      \
00221                 | ((FP_X_UFL & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0)     \
00222                 | ((FP_X_INV & fpstatus) ? UFUNC_FPE_INVALID : 0);      \
00223         (void) fpsetsticky(0);                                          \
00224         }
00225 
00226 #elif defined(__GLIBC__) || defined(__APPLE__) || \
00227       defined(__CYGWIN__) || defined(__MINGW32__) || \
00228       (defined(__FreeBSD__) && (__FreeBSD_version >= 502114))
00229 
00230 #if defined(__GLIBC__) || defined(__APPLE__) || \
00231     defined(__MINGW32__) || defined(__FreeBSD__)
00232 #include <fenv.h>
00233 #elif defined(__CYGWIN__)
00234 #include "fenv/fenv.c"
00235 #endif
00236 
00237 #define UFUNC_CHECK_STATUS(ret) {                                       \
00238         int fpstatus = (int) fetestexcept(FE_DIVBYZERO | FE_OVERFLOW |  \
00239                                           FE_UNDERFLOW | FE_INVALID);   \
00240         ret = ((FE_DIVBYZERO  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
00241                 | ((FE_OVERFLOW   & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
00242                 | ((FE_UNDERFLOW  & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
00243                 | ((FE_INVALID    & fpstatus) ? UFUNC_FPE_INVALID : 0); \
00244         (void) feclearexcept(FE_DIVBYZERO | FE_OVERFLOW |               \
00245                              FE_UNDERFLOW | FE_INVALID);                \
00246 }
00247 
00248 #elif defined(_AIX)
00249 
00250 #include <float.h>
00251 #include <fpxcp.h>
00252 
00253 #define UFUNC_CHECK_STATUS(ret) { \
00254         fpflag_t fpstatus; \
00255  \
00256         fpstatus = fp_read_flag(); \
00257         ret = ((FP_DIV_BY_ZERO & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
00258                 | ((FP_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)   \
00259                 | ((FP_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
00260                 | ((FP_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \
00261         fp_swap_flag(0); \
00262 }
00263 
00264 #else
00265 
00266 #define NO_FLOATING_POINT_SUPPORT
00267 #define UFUNC_CHECK_STATUS(ret) { \
00268     ret = 0; \
00269   }
00270 
00271 #endif
00272 
00273 /*
00274  * THESE MACROS ARE DEPRECATED.
00275  * Use npy_set_floatstatus_* in the npymath library.
00276  */
00277 #define generate_divbyzero_error() npy_set_floatstatus_divbyzero()
00278 #define generate_overflow_error() npy_set_floatstatus_overflow()
00279 
00280   /* Make sure it gets defined if it isn't already */
00281 #ifndef UFUNC_NOFPE
00282 #define UFUNC_NOFPE
00283 #endif
00284 
00285 
00286 #ifdef __cplusplus
00287 }
00288 #endif
00289 #endif /* !Py_UFUNCOBJECT_H */