text: #ifndef Py_UFUNCOBJECT_H
  #define Py_UFUNCOBJECT_H
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *);
  
  typedef struct {
          PyObject_HEAD
          int nin, nout, nargs;
          int identity;
          PyUFuncGenericFunction *functions;
          void **data;
          int ntypes;
          int check_return;
          char *name, *types;
          char *doc;
          void *ptr;
          PyObject *obj;
          PyObject *userloops;
      
          /* generalized ufunc */
          int core_enabled;      /* 0 for scalar ufunc; 1 for generalized ufunc */
          int core_num_dim_ix;   /* number of distinct dimension names in
                                    signature */
   
          /* dimension indices of input/output argument k are stored in
             core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] */
          int *core_num_dims;    /* numbers of core dimensions of each argument */
          int *core_dim_ixs;     /* dimension indices in a flatted form; indices
                                    are in the range of [0,core_num_dim_ix) */
          int *core_offsets;     /* positions of 1st core dimensions of each
                                    argument in core_dim_ixs */
          char *core_signature;  /* signature string for printing purpose */
  } PyUFuncObject;
  
  #include "arrayobject.h"
  
  #define UFUNC_ERR_IGNORE 0
  #define UFUNC_ERR_WARN   1
  #define UFUNC_ERR_RAISE  2
  #define UFUNC_ERR_CALL   3
  #define UFUNC_ERR_PRINT  4
  #define UFUNC_ERR_LOG    5
  
          /* Python side integer mask */
  
  #define UFUNC_MASK_DIVIDEBYZERO 0x07
  #define UFUNC_MASK_OVERFLOW 0x3f
  #define UFUNC_MASK_UNDERFLOW 0x1ff
  #define UFUNC_MASK_INVALID 0xfff
  
  #define UFUNC_SHIFT_DIVIDEBYZERO 0
  #define UFUNC_SHIFT_OVERFLOW     3
  #define UFUNC_SHIFT_UNDERFLOW    6
  #define UFUNC_SHIFT_INVALID      9
  
  
  /* platform-dependent code translates floating point
     status to an integer sum of these values
  */
  #define UFUNC_FPE_DIVIDEBYZERO  1
  #define UFUNC_FPE_OVERFLOW      2
  #define UFUNC_FPE_UNDERFLOW     4
  #define UFUNC_FPE_INVALID       8
  
  #define UFUNC_ERR_DEFAULT  0      /* Error mode that avoids look-up (no checking) */
  
  #define UFUNC_OBJ_ISOBJECT      1
  #define UFUNC_OBJ_NEEDS_API     2
  
     /* Default user error mode */
  #define UFUNC_ERR_DEFAULT2                               \
          (UFUNC_ERR_PRINT << UFUNC_SHIFT_DIVIDEBYZERO) +  \
          (UFUNC_ERR_PRINT << UFUNC_SHIFT_OVERFLOW) +      \
          (UFUNC_ERR_PRINT << UFUNC_SHIFT_INVALID)
  
          /* Only internal -- not exported, yet*/
  typedef struct {
          /* Multi-iterator portion --- needs to be present in this order
             to work with PyArray_Broadcast */
          PyObject_HEAD
          int  numiter;
          npy_intp size;
          npy_intp index;
          int nd;
          npy_intp dimensions[NPY_MAXDIMS];
          PyArrayIterObject *iters[NPY_MAXARGS];
          /*  End of Multi-iterator portion */
  
          /* The ufunc */
          PyUFuncObject *ufunc;
  
          /* The error handling */
          int errormask;         /* Integer showing desired error handling */
          PyObject *errobj;      /* currently a tuple with
                                    (string, func or obj with write method or None)
                                 */
          int first;
  
          /* Specific function and data to use */
          PyUFuncGenericFunction function;
          void *funcdata;
  
          /* Loop method */
          int meth;
  
          /* Whether we need to copy to a buffer or not.*/
          int needbuffer[NPY_MAXARGS];
          int leftover;
          int ninnerloops;
          int lastdim;
  
          /* Whether or not to swap */
          int swap[NPY_MAXARGS];
  
          /* Buffers for the loop */
          char *buffer[NPY_MAXARGS];
          int bufsize;
          npy_intp bufcnt;
          char *dptr[NPY_MAXARGS];
  
          /* For casting */
          char *castbuf[NPY_MAXARGS];
          PyArray_VectorUnaryFunc *cast[NPY_MAXARGS];
  
          /* usually points to buffer but when a cast is to be
             done it switches for that argument to castbuf.
          */
          char *bufptr[NPY_MAXARGS];
  
          /* Steps filled in from iters or sizeof(item)
             depending on loop method.
          */
          npy_intp steps[NPY_MAXARGS];
  
          int obj;  /* This loop uses object arrays or needs the Python API */
                    /* Flags: UFUNC_OBJ_ISOBJECT, UFUNC_OBJ_NEEDS_API */
          int notimplemented; /* The loop caused notimplemented */
          int objfunc; /* This loop calls object functions
                          (an inner-loop function with argument types */
      
          /* generalized ufunc */
          npy_intp *core_dim_sizes;   /* stores sizes of core dimensions;
                                         contains 1 + core_num_dim_ix elements */
          npy_intp *core_strides;     /* strides of loop and core dimensions */
  } PyUFuncLoopObject;
  
  /* Could make this more clever someday */
  #define UFUNC_MAXIDENTITY 32
  
  typedef struct {
          PyObject_HEAD
          PyArrayIterObject *it;
          PyArrayObject *ret;
          PyArrayIterObject *rit;   /* Needed for Accumulate */
          int  outsize;
          npy_intp  index;
          npy_intp  size;
          char idptr[UFUNC_MAXIDENTITY];
  
          /* The ufunc */
          PyUFuncObject *ufunc;
  
          /* The error handling */
          int errormask;
          PyObject *errobj;
          int first;
  
          PyUFuncGenericFunction function;
          void *funcdata;
          int meth;
          int swap;
  
          char *buffer;
          int bufsize;
  
          char *castbuf;
          PyArray_VectorUnaryFunc *cast;
  
          char *bufptr[3];
          npy_intp steps[3];
  
          npy_intp N;
          int  instrides;
          int  insize;
          char *inptr;
  
          /* For copying small arrays */
          PyObject *decref;
  
          int obj;
          int retbase;
  
  } PyUFuncReduceObject;
  
  
  #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
  
  #define PyUFunc_One 1
  #define PyUFunc_Zero 0
  #define PyUFunc_None -1
  
  #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;
  } PyUFunc_Loop1d;
  
  
  #include "__ufunc_api.h"
  
  #define UFUNC_PYVALS_NAME "UFUNC_PYVALS"
  
  #define UFUNC_CHECK_ERROR(arg)                                          \
          do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) ||                         \
              ((arg)->errormask &&                                        \
               PyUFunc_checkfperr((arg)->errormask,                       \
                                  (arg)->errobj,                          \
                                  &(arg)->first)))                        \
                  goto fail;} while (0)
  
  /* This code checks the IEEE status flags in a platform-dependent way */
  /* Adapted from Numarray  */
  
  #if (defined(__unix__) || defined(unix)) && !defined(USG)
  #include <sys/param.h>
  #endif
  
  /*  OSF/Alpha (Tru64)  ---------------------------------------------*/
  #if defined(__osf__) && defined(__alpha)
  
  #include <machine/fpu.h>
  
  #define UFUNC_CHECK_STATUS(ret) {               \
          unsigned long fpstatus;                 \
                                                  \
          fpstatus = ieee_get_fp_control();                               \
          /* clear status bits as well as disable exception mode if on */ \
          ieee_set_fp_control( 0 );                                       \
          ret = ((IEEE_STATUS_DZE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
                  | ((IEEE_STATUS_OVF & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
                  | ((IEEE_STATUS_UNF & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
                  | ((IEEE_STATUS_INV & fpstatus) ? UFUNC_FPE_INVALID : 0); \
          }
  
  /* MS Windows -----------------------------------------------------*/
  #elif defined(_MSC_VER)
  
  #include <float.h>
  
    /* Clear the floating point exception default of Borland C++ */
  #if defined(__BORLANDC__)
  #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM);
  #endif
  
  #define UFUNC_CHECK_STATUS(ret) {                \
          int fpstatus = (int) _clearfp();                        \
                                                                          \
          ret = ((SW_ZERODIVIDE & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
                  | ((SW_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)   \
                  | ((SW_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
                  | ((SW_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0);    \
          }
  
  /* Solaris --------------------------------------------------------*/
  /* --------ignoring SunOS ieee_flags approach, someone else can
  **         deal with that! */
  #elif defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || defined(__NetBSD__)
  #include <ieeefp.h>
  
  #define UFUNC_CHECK_STATUS(ret) {                               \
          int fpstatus;                                           \
                                                                  \
          fpstatus = (int) fpgetsticky();                                 \
          ret = ((FP_X_DZ  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0)      \
                  | ((FP_X_OFL & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)      \
                  | ((FP_X_UFL & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0)     \
                  | ((FP_X_INV & fpstatus) ? UFUNC_FPE_INVALID : 0);      \
          (void) fpsetsticky(0);                                          \
          }
  
  #elif defined(__GLIBC__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__MINGW32__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 502114))
  
  #if defined(__GLIBC__) || defined(__APPLE__) || defined(__MINGW32__) || defined(__FreeBSD__)
  #include <fenv.h>
  #elif defined(__CYGWIN__)
  #include "fenv/fenv.c"
  #endif
  
  #define UFUNC_CHECK_STATUS(ret) {                                       \
          int fpstatus = (int) fetestexcept(FE_DIVBYZERO | FE_OVERFLOW |  \
                                            FE_UNDERFLOW | FE_INVALID);   \
          ret = ((FE_DIVBYZERO  & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
                  | ((FE_OVERFLOW   & fpstatus) ? UFUNC_FPE_OVERFLOW : 0) \
                  | ((FE_UNDERFLOW  & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
                  | ((FE_INVALID    & fpstatus) ? UFUNC_FPE_INVALID : 0); \
          (void) feclearexcept(FE_DIVBYZERO | FE_OVERFLOW |               \
                               FE_UNDERFLOW | FE_INVALID);                \
  }
  
  #define generate_divbyzero_error() feraiseexcept(FE_DIVBYZERO)
  #define generate_overflow_error() feraiseexcept(FE_OVERFLOW)
  
  #elif defined(_AIX)
  
  #include <float.h>
  #include <fpxcp.h>
  
  #define UFUNC_CHECK_STATUS(ret) { \
          fpflag_t fpstatus; \
                                                  \
          fpstatus = fp_read_flag(); \
          ret = ((FP_DIV_BY_ZERO & fpstatus) ? UFUNC_FPE_DIVIDEBYZERO : 0) \
                  | ((FP_OVERFLOW & fpstatus) ? UFUNC_FPE_OVERFLOW : 0)   \
                  | ((FP_UNDERFLOW & fpstatus) ? UFUNC_FPE_UNDERFLOW : 0) \
                  | ((FP_INVALID & fpstatus) ? UFUNC_FPE_INVALID : 0); \
          fp_swap_flag(0); \
  }
  
  #define generate_divbyzero_error() fp_raise_xcp(FP_DIV_BY_ZERO)
  #define generate_overflow_error() fp_raise_xcp(FP_OVERFLOW)
  
  #else
  
  #define NO_FLOATING_POINT_SUPPORT
  #define UFUNC_CHECK_STATUS(ret) { \
      ret = 0;                                                         \
    }
  
  #endif
  
  /* These should really be altered to just set the corresponding bit
     in the floating point status flag.  Need to figure out how to do that
     on all the platforms...
  */
  
  #if !defined(generate_divbyzero_error)
  static int numeric_zero2 = 0;
  static void generate_divbyzero_error(void) {
          double dummy;
          dummy = 1./numeric_zero2;
          if (dummy) /* to prevent optimizer from eliminating expression */
             return;
          else /* should never be called */
             numeric_zero2 += 1;
          return;
  }
  #endif
  
  #if !defined(generate_overflow_error)
  static double numeric_two = 2.0;
  static void generate_overflow_error(void) {
          double dummy;
          dummy = pow(numeric_two,1000);
          if (dummy)
             return;
          else
             numeric_two += 0.1;
          return;
          return;
  }
  #endif
  
    /* Make sure it gets defined if it isn't already */
  #ifndef UFUNC_NOFPE
  #define UFUNC_NOFPE
  #endif
  
  
  #ifdef __cplusplus
  }
  #endif
  #endif /* !Py_UFUNCOBJECT_H */
  