/ lib / numpy / core / include / numpy / ufuncobject.h
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_ */