ufuncobject.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #ifndef Py_UFUNCOBJECT_H
  2. #define Py_UFUNCOBJECT_H
  3. #include <numpy/npy_math.h>
  4. #include <numpy/npy_common.h>
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. /*
  9. * The legacy generic inner loop for a standard element-wise or
  10. * generalized ufunc.
  11. */
  12. typedef void (*PyUFuncGenericFunction)
  13. (char **args,
  14. npy_intp *dimensions,
  15. npy_intp *strides,
  16. void *innerloopdata);
  17. /*
  18. * The most generic one-dimensional inner loop for
  19. * a masked standard element-wise ufunc. "Masked" here means that it skips
  20. * doing calculations on any items for which the maskptr array has a true
  21. * value.
  22. */
  23. typedef void (PyUFunc_MaskedStridedInnerLoopFunc)(
  24. char **dataptrs, npy_intp *strides,
  25. char *maskptr, npy_intp mask_stride,
  26. npy_intp count,
  27. NpyAuxData *innerloopdata);
  28. /* Forward declaration for the type resolver and loop selector typedefs */
  29. struct _tagPyUFuncObject;
  30. /*
  31. * Given the operands for calling a ufunc, should determine the
  32. * calculation input and output data types and return an inner loop function.
  33. * This function should validate that the casting rule is being followed,
  34. * and fail if it is not.
  35. *
  36. * For backwards compatibility, the regular type resolution function does not
  37. * support auxiliary data with object semantics. The type resolution call
  38. * which returns a masked generic function returns a standard NpyAuxData
  39. * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros
  40. * work.
  41. *
  42. * ufunc: The ufunc object.
  43. * casting: The 'casting' parameter provided to the ufunc.
  44. * operands: An array of length (ufunc->nin + ufunc->nout),
  45. * with the output parameters possibly NULL.
  46. * type_tup: Either NULL, or the type_tup passed to the ufunc.
  47. * out_dtypes: An array which should be populated with new
  48. * references to (ufunc->nin + ufunc->nout) new
  49. * dtypes, one for each input and output. These
  50. * dtypes should all be in native-endian format.
  51. *
  52. * Should return 0 on success, -1 on failure (with exception set),
  53. * or -2 if Py_NotImplemented should be returned.
  54. */
  55. typedef int (PyUFunc_TypeResolutionFunc)(
  56. struct _tagPyUFuncObject *ufunc,
  57. NPY_CASTING casting,
  58. PyArrayObject **operands,
  59. PyObject *type_tup,
  60. PyArray_Descr **out_dtypes);
  61. /*
  62. * Given an array of DTypes as returned by the PyUFunc_TypeResolutionFunc,
  63. * and an array of fixed strides (the array will contain NPY_MAX_INTP for
  64. * strides which are not necessarily fixed), returns an inner loop
  65. * with associated auxiliary data.
  66. *
  67. * For backwards compatibility, there is a variant of the inner loop
  68. * selection which returns an inner loop irrespective of the strides,
  69. * and with a void* static auxiliary data instead of an NpyAuxData *
  70. * dynamically allocatable auxiliary data.
  71. *
  72. * ufunc: The ufunc object.
  73. * dtypes: An array which has been populated with dtypes,
  74. * in most cases by the type resolution funciton
  75. * for the same ufunc.
  76. * fixed_strides: For each input/output, either the stride that
  77. * will be used every time the function is called
  78. * or NPY_MAX_INTP if the stride might change or
  79. * is not known ahead of time. The loop selection
  80. * function may use this stride to pick inner loops
  81. * which are optimized for contiguous or 0-stride
  82. * cases.
  83. * out_innerloop: Should be populated with the correct ufunc inner
  84. * loop for the given type.
  85. * out_innerloopdata: Should be populated with the void* data to
  86. * be passed into the out_innerloop function.
  87. * out_needs_api: If the inner loop needs to use the Python API,
  88. * should set the to 1, otherwise should leave
  89. * this untouched.
  90. */
  91. typedef int (PyUFunc_LegacyInnerLoopSelectionFunc)(
  92. struct _tagPyUFuncObject *ufunc,
  93. PyArray_Descr **dtypes,
  94. PyUFuncGenericFunction *out_innerloop,
  95. void **out_innerloopdata,
  96. int *out_needs_api);
  97. typedef int (PyUFunc_MaskedInnerLoopSelectionFunc)(
  98. struct _tagPyUFuncObject *ufunc,
  99. PyArray_Descr **dtypes,
  100. PyArray_Descr *mask_dtype,
  101. npy_intp *fixed_strides,
  102. npy_intp fixed_mask_stride,
  103. PyUFunc_MaskedStridedInnerLoopFunc **out_innerloop,
  104. NpyAuxData **out_innerloopdata,
  105. int *out_needs_api);
  106. typedef struct _tagPyUFuncObject {
  107. PyObject_HEAD
  108. /*
  109. * nin: Number of inputs
  110. * nout: Number of outputs
  111. * nargs: Always nin + nout (Why is it stored?)
  112. */
  113. int nin, nout, nargs;
  114. /* Identity for reduction, either PyUFunc_One or PyUFunc_Zero */
  115. int identity;
  116. /* Array of one-dimensional core loops */
  117. PyUFuncGenericFunction *functions;
  118. /* Array of funcdata that gets passed into the functions */
  119. void **data;
  120. /* The number of elements in 'functions' and 'data' */
  121. int ntypes;
  122. /* Used to be unused field 'check_return' */
  123. int reserved1;
  124. /* The name of the ufunc */
  125. const char *name;
  126. /* Array of type numbers, of size ('nargs' * 'ntypes') */
  127. char *types;
  128. /* Documentation string */
  129. const char *doc;
  130. void *ptr;
  131. PyObject *obj;
  132. PyObject *userloops;
  133. /* generalized ufunc parameters */
  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. * dimension indices of input/output argument k are stored in
  140. * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1]
  141. */
  142. /* numbers of core dimensions of each argument */
  143. int *core_num_dims;
  144. /*
  145. * dimension indices in a flatted form; indices
  146. * are in the range of [0,core_num_dim_ix)
  147. */
  148. int *core_dim_ixs;
  149. /*
  150. * positions of 1st core dimensions of each
  151. * argument in core_dim_ixs
  152. */
  153. int *core_offsets;
  154. /* signature string for printing purpose */
  155. char *core_signature;
  156. /*
  157. * A function which resolves the types and fills an array
  158. * with the dtypes for the inputs and outputs.
  159. */
  160. PyUFunc_TypeResolutionFunc *type_resolver;
  161. /*
  162. * A function which returns an inner loop written for
  163. * NumPy 1.6 and earlier ufuncs. This is for backwards
  164. * compatibility, and may be NULL if inner_loop_selector
  165. * is specified.
  166. */
  167. PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector;
  168. /*
  169. * This was blocked off to be the "new" inner loop selector in 1.7,
  170. * but this was never implemented. (This is also why the above
  171. * selector is called the "legacy" selector.)
  172. */
  173. void *reserved2;
  174. /*
  175. * A function which returns a masked inner loop for the ufunc.
  176. */
  177. PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector;
  178. /*
  179. * List of flags for each operand when ufunc is called by nditer object.
  180. * These flags will be used in addition to the default flags for each
  181. * operand set by nditer object.
  182. */
  183. npy_uint32 *op_flags;
  184. /*
  185. * List of global flags used when ufunc is called by nditer object.
  186. * These flags will be used in addition to the default global flags
  187. * set by nditer object.
  188. */
  189. npy_uint32 iter_flags;
  190. } PyUFuncObject;
  191. #include "arrayobject.h"
  192. #define UFUNC_ERR_IGNORE 0
  193. #define UFUNC_ERR_WARN 1
  194. #define UFUNC_ERR_RAISE 2
  195. #define UFUNC_ERR_CALL 3
  196. #define UFUNC_ERR_PRINT 4
  197. #define UFUNC_ERR_LOG 5
  198. /* Python side integer mask */
  199. #define UFUNC_MASK_DIVIDEBYZERO 0x07
  200. #define UFUNC_MASK_OVERFLOW 0x3f
  201. #define UFUNC_MASK_UNDERFLOW 0x1ff
  202. #define UFUNC_MASK_INVALID 0xfff
  203. #define UFUNC_SHIFT_DIVIDEBYZERO 0
  204. #define UFUNC_SHIFT_OVERFLOW 3
  205. #define UFUNC_SHIFT_UNDERFLOW 6
  206. #define UFUNC_SHIFT_INVALID 9
  207. #define UFUNC_OBJ_ISOBJECT 1
  208. #define UFUNC_OBJ_NEEDS_API 2
  209. /* Default user error mode */
  210. #define UFUNC_ERR_DEFAULT \
  211. (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) + \
  212. (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) + \
  213. (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID)
  214. #if NPY_ALLOW_THREADS
  215. #define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0);
  216. #define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0);
  217. #else
  218. #define NPY_LOOP_BEGIN_THREADS
  219. #define NPY_LOOP_END_THREADS
  220. #endif
  221. /*
  222. * UFunc has unit of 1, and the order of operations can be reordered
  223. * This case allows reduction with multiple axes at once.
  224. */
  225. #define PyUFunc_One 1
  226. /*
  227. * UFunc has unit of 0, and the order of operations can be reordered
  228. * This case allows reduction with multiple axes at once.
  229. */
  230. #define PyUFunc_Zero 0
  231. /*
  232. * UFunc has no unit, and the order of operations cannot be reordered.
  233. * This case does not allow reduction with multiple axes at once.
  234. */
  235. #define PyUFunc_None -1
  236. /*
  237. * UFunc has no unit, and the order of operations can be reordered
  238. * This case allows reduction with multiple axes at once.
  239. */
  240. #define PyUFunc_ReorderableNone -2
  241. #define UFUNC_REDUCE 0
  242. #define UFUNC_ACCUMULATE 1
  243. #define UFUNC_REDUCEAT 2
  244. #define UFUNC_OUTER 3
  245. typedef struct {
  246. int nin;
  247. int nout;
  248. PyObject *callable;
  249. } PyUFunc_PyFuncData;
  250. /* A linked-list of function information for
  251. user-defined 1-d loops.
  252. */
  253. typedef struct _loop1d_info {
  254. PyUFuncGenericFunction func;
  255. void *data;
  256. int *arg_types;
  257. struct _loop1d_info *next;
  258. int nargs;
  259. PyArray_Descr **arg_dtypes;
  260. } PyUFunc_Loop1d;
  261. #include "__ufunc_api.h"
  262. #define UFUNC_PYVALS_NAME "UFUNC_PYVALS"
  263. #define UFUNC_CHECK_ERROR(arg) \
  264. do {if ((((arg)->obj & UFUNC_OBJ_NEEDS_API) && PyErr_Occurred()) || \
  265. ((arg)->errormask && \
  266. PyUFunc_checkfperr((arg)->errormask, \
  267. (arg)->errobj, \
  268. &(arg)->first))) \
  269. goto fail;} while (0)
  270. /* keep in sync with ieee754.c.src */
  271. #if defined(sun) || defined(__BSD__) || defined(__OpenBSD__) || \
  272. (defined(__FreeBSD__) && (__FreeBSD_version < 502114)) || \
  273. defined(__NetBSD__) || \
  274. defined(__GLIBC__) || defined(__APPLE__) || \
  275. defined(__CYGWIN__) || defined(__MINGW32__) || \
  276. (defined(__FreeBSD__) && (__FreeBSD_version >= 502114)) || \
  277. defined(_AIX) || \
  278. defined(_MSC_VER) || \
  279. defined(__osf__) && defined(__alpha)
  280. #else
  281. #define NO_FLOATING_POINT_SUPPORT
  282. #endif
  283. /*
  284. * THESE MACROS ARE DEPRECATED.
  285. * Use npy_set_floatstatus_* in the npymath library.
  286. */
  287. #define UFUNC_FPE_DIVIDEBYZERO NPY_FPE_DIVIDEBYZERO
  288. #define UFUNC_FPE_OVERFLOW NPY_FPE_OVERFLOW
  289. #define UFUNC_FPE_UNDERFLOW NPY_FPE_UNDERFLOW
  290. #define UFUNC_FPE_INVALID NPY_FPE_INVALID
  291. #define UFUNC_CHECK_STATUS(ret) \
  292. { \
  293. ret = npy_clear_floatstatus(); \
  294. }
  295. #define generate_divbyzero_error() npy_set_floatstatus_divbyzero()
  296. #define generate_overflow_error() npy_set_floatstatus_overflow()
  297. /* Make sure it gets defined if it isn't already */
  298. #ifndef UFUNC_NOFPE
  299. /* Clear the floating point exception default of Borland C++ */
  300. #if defined(__BORLANDC__)
  301. #define UFUNC_NOFPE _control87(MCW_EM, MCW_EM);
  302. #else
  303. #define UFUNC_NOFPE
  304. #endif
  305. #endif
  306. #ifdef __cplusplus
  307. }
  308. #endif
  309. #endif /* !Py_UFUNCOBJECT_H */