/numpy/core/src/multiarray/common.h

http://github.com/numpy/numpy · C Header · 346 lines · 192 code · 34 blank · 120 comment · 40 complexity · 455a44531c9f4900df695cc87796eaa7 MD5 · raw file

  1. #ifndef _NPY_PRIVATE_COMMON_H_
  2. #define _NPY_PRIVATE_COMMON_H_
  3. #include "structmember.h"
  4. #include <numpy/npy_common.h>
  5. #include <numpy/npy_cpu.h>
  6. #include <numpy/ndarraytypes.h>
  7. #include <limits.h>
  8. #define error_converting(x) (((x) == -1) && PyErr_Occurred())
  9. #ifdef NPY_ALLOW_THREADS
  10. #define NPY_BEGIN_THREADS_NDITER(iter) \
  11. do { \
  12. if (!NpyIter_IterationNeedsAPI(iter)) { \
  13. NPY_BEGIN_THREADS_THRESHOLDED(NpyIter_GetIterSize(iter)); \
  14. } \
  15. } while(0)
  16. #else
  17. #define NPY_BEGIN_THREADS_NDITER(iter)
  18. #endif
  19. /*
  20. * Recursively examines the object to determine an appropriate dtype
  21. * to use for converting to an ndarray.
  22. *
  23. * 'obj' is the object to be converted to an ndarray.
  24. *
  25. * 'maxdims' is the maximum recursion depth.
  26. *
  27. * 'out_dtype' should be either NULL or a minimal starting dtype when
  28. * the function is called. It is updated with the results of type
  29. * promotion. This dtype does not get updated when processing NA objects.
  30. *
  31. * Returns 0 on success, -1 on failure.
  32. */
  33. NPY_NO_EXPORT int
  34. PyArray_DTypeFromObject(PyObject *obj, int maxdims,
  35. PyArray_Descr **out_dtype);
  36. NPY_NO_EXPORT int
  37. PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
  38. PyArray_Descr **out_dtype, int string_status);
  39. /*
  40. * Returns NULL without setting an exception if no scalar is matched, a
  41. * new dtype reference otherwise.
  42. */
  43. NPY_NO_EXPORT PyArray_Descr *
  44. _array_find_python_scalar_type(PyObject *op);
  45. NPY_NO_EXPORT PyArray_Descr *
  46. _array_typedescr_fromstr(char const *str);
  47. NPY_NO_EXPORT char *
  48. index2ptr(PyArrayObject *mp, npy_intp i);
  49. NPY_NO_EXPORT int
  50. _zerofill(PyArrayObject *ret);
  51. NPY_NO_EXPORT npy_bool
  52. _IsWriteable(PyArrayObject *ap);
  53. NPY_NO_EXPORT PyObject *
  54. convert_shape_to_string(npy_intp n, npy_intp const *vals, char *ending);
  55. /*
  56. * Sets ValueError with "matrices not aligned" message for np.dot and friends
  57. * when a.shape[i] should match b.shape[j], but doesn't.
  58. */
  59. NPY_NO_EXPORT void
  60. dot_alignment_error(PyArrayObject *a, int i, PyArrayObject *b, int j);
  61. /**
  62. * unpack tuple of dtype->fields (descr, offset, title[not-needed])
  63. *
  64. * @param "value" should be the tuple.
  65. *
  66. * @return "descr" will be set to the field's dtype
  67. * @return "offset" will be set to the field's offset
  68. *
  69. * returns -1 on failure, 0 on success.
  70. */
  71. NPY_NO_EXPORT int
  72. _unpack_field(PyObject *value, PyArray_Descr **descr, npy_intp *offset);
  73. /*
  74. * check whether arrays with datatype dtype might have object fields. This will
  75. * only happen for structured dtypes (which may have hidden objects even if the
  76. * HASOBJECT flag is false), object dtypes, or subarray dtypes whose base type
  77. * is either of these.
  78. */
  79. NPY_NO_EXPORT int
  80. _may_have_objects(PyArray_Descr *dtype);
  81. /*
  82. * Returns -1 and sets an exception if *index is an invalid index for
  83. * an array of size max_item, otherwise adjusts it in place to be
  84. * 0 <= *index < max_item, and returns 0.
  85. * 'axis' should be the array axis that is being indexed over, if known. If
  86. * unknown, use -1.
  87. * If _save is NULL it is assumed the GIL is taken
  88. * If _save is not NULL it is assumed the GIL is not taken and it
  89. * is acquired in the case of an error
  90. */
  91. static NPY_INLINE int
  92. check_and_adjust_index(npy_intp *index, npy_intp max_item, int axis,
  93. PyThreadState * _save)
  94. {
  95. /* Check that index is valid, taking into account negative indices */
  96. if (NPY_UNLIKELY((*index < -max_item) || (*index >= max_item))) {
  97. NPY_END_THREADS;
  98. /* Try to be as clear as possible about what went wrong. */
  99. if (axis >= 0) {
  100. PyErr_Format(PyExc_IndexError,
  101. "index %"NPY_INTP_FMT" is out of bounds "
  102. "for axis %d with size %"NPY_INTP_FMT,
  103. *index, axis, max_item);
  104. } else {
  105. PyErr_Format(PyExc_IndexError,
  106. "index %"NPY_INTP_FMT" is out of bounds "
  107. "for size %"NPY_INTP_FMT, *index, max_item);
  108. }
  109. return -1;
  110. }
  111. /* adjust negative indices */
  112. if (*index < 0) {
  113. *index += max_item;
  114. }
  115. return 0;
  116. }
  117. /*
  118. * Returns -1 and sets an exception if *axis is an invalid axis for
  119. * an array of dimension ndim, otherwise adjusts it in place to be
  120. * 0 <= *axis < ndim, and returns 0.
  121. *
  122. * msg_prefix: borrowed reference, a string to prepend to the message
  123. */
  124. static NPY_INLINE int
  125. check_and_adjust_axis_msg(int *axis, int ndim, PyObject *msg_prefix)
  126. {
  127. /* Check that index is valid, taking into account negative indices */
  128. if (NPY_UNLIKELY((*axis < -ndim) || (*axis >= ndim))) {
  129. /*
  130. * Load the exception type, if we don't already have it. Unfortunately
  131. * we don't have access to npy_cache_import here
  132. */
  133. static PyObject *AxisError_cls = NULL;
  134. PyObject *exc;
  135. if (AxisError_cls == NULL) {
  136. PyObject *mod = PyImport_ImportModule("numpy.core._exceptions");
  137. if (mod != NULL) {
  138. AxisError_cls = PyObject_GetAttrString(mod, "AxisError");
  139. Py_DECREF(mod);
  140. }
  141. }
  142. /* Invoke the AxisError constructor */
  143. exc = PyObject_CallFunction(AxisError_cls, "iiO",
  144. *axis, ndim, msg_prefix);
  145. if (exc == NULL) {
  146. return -1;
  147. }
  148. PyErr_SetObject(AxisError_cls, exc);
  149. Py_DECREF(exc);
  150. return -1;
  151. }
  152. /* adjust negative indices */
  153. if (*axis < 0) {
  154. *axis += ndim;
  155. }
  156. return 0;
  157. }
  158. static NPY_INLINE int
  159. check_and_adjust_axis(int *axis, int ndim)
  160. {
  161. return check_and_adjust_axis_msg(axis, ndim, Py_None);
  162. }
  163. /* used for some alignment checks */
  164. #define _ALIGN(type) offsetof(struct {char c; type v;}, v)
  165. #define _UINT_ALIGN(type) npy_uint_alignment(sizeof(type))
  166. /*
  167. * Disable harmless compiler warning "4116: unnamed type definition in
  168. * parentheses" which is caused by the _ALIGN macro.
  169. */
  170. #if defined(_MSC_VER)
  171. #pragma warning(disable:4116)
  172. #endif
  173. /*
  174. * return true if pointer is aligned to 'alignment'
  175. */
  176. static NPY_INLINE int
  177. npy_is_aligned(const void * p, const npy_uintp alignment)
  178. {
  179. /*
  180. * Assumes alignment is a power of two, as required by the C standard.
  181. * Assumes cast from pointer to uintp gives a sensible representation we
  182. * can use bitwise & on (not required by C standard, but used by glibc).
  183. * This test is faster than a direct modulo.
  184. * Note alignment value of 0 is allowed and returns False.
  185. */
  186. return ((npy_uintp)(p) & ((alignment) - 1)) == 0;
  187. }
  188. /* Get equivalent "uint" alignment given an itemsize, for use in copy code */
  189. static NPY_INLINE int
  190. npy_uint_alignment(int itemsize)
  191. {
  192. npy_uintp alignment = 0; /* return value of 0 means unaligned */
  193. switch(itemsize){
  194. case 1:
  195. return 1;
  196. case 2:
  197. alignment = _ALIGN(npy_uint16);
  198. break;
  199. case 4:
  200. alignment = _ALIGN(npy_uint32);
  201. break;
  202. case 8:
  203. alignment = _ALIGN(npy_uint64);
  204. break;
  205. case 16:
  206. /*
  207. * 16 byte types are copied using 2 uint64 assignments.
  208. * See the strided copy function in lowlevel_strided_loops.c.
  209. */
  210. alignment = _ALIGN(npy_uint64);
  211. break;
  212. default:
  213. break;
  214. }
  215. return alignment;
  216. }
  217. /*
  218. * memchr with stride and invert argument
  219. * intended for small searches where a call out to libc memchr is costly.
  220. * stride must be a multiple of size.
  221. * compared to memchr it returns one stride past end instead of NULL if needle
  222. * is not found.
  223. */
  224. static NPY_INLINE char *
  225. npy_memchr(char * haystack, char needle,
  226. npy_intp stride, npy_intp size, npy_intp * psubloopsize, int invert)
  227. {
  228. char * p = haystack;
  229. npy_intp subloopsize = 0;
  230. if (!invert) {
  231. /*
  232. * this is usually the path to determine elements to process,
  233. * performance less important here.
  234. * memchr has large setup cost if 0 byte is close to start.
  235. */
  236. while (subloopsize < size && *p != needle) {
  237. subloopsize++;
  238. p += stride;
  239. }
  240. }
  241. else {
  242. /* usually find elements to skip path */
  243. if (NPY_CPU_HAVE_UNALIGNED_ACCESS && needle == 0 && stride == 1) {
  244. /* iterate until last multiple of 4 */
  245. char * block_end = haystack + size - (size % sizeof(unsigned int));
  246. while (p < block_end) {
  247. unsigned int v = *(unsigned int*)p;
  248. if (v != 0) {
  249. break;
  250. }
  251. p += sizeof(unsigned int);
  252. }
  253. /* handle rest */
  254. subloopsize = (p - haystack);
  255. }
  256. while (subloopsize < size && *p == needle) {
  257. subloopsize++;
  258. p += stride;
  259. }
  260. }
  261. *psubloopsize = subloopsize;
  262. return p;
  263. }
  264. /*
  265. * Convert NumPy stride to BLAS stride. Returns 0 if conversion cannot be done
  266. * (BLAS won't handle negative or zero strides the way we want).
  267. */
  268. static NPY_INLINE int
  269. blas_stride(npy_intp stride, unsigned itemsize)
  270. {
  271. /*
  272. * Should probably check pointer alignment also, but this may cause
  273. * problems if we require complex to be 16 byte aligned.
  274. */
  275. if (stride > 0 && npy_is_aligned((void *)stride, itemsize)) {
  276. stride /= itemsize;
  277. #ifndef HAVE_BLAS_ILP64
  278. if (stride <= INT_MAX) {
  279. #else
  280. if (stride <= NPY_MAX_INT64) {
  281. #endif
  282. return stride;
  283. }
  284. }
  285. return 0;
  286. }
  287. /*
  288. * Define a chunksize for CBLAS. CBLAS counts in integers.
  289. */
  290. #if NPY_MAX_INTP > INT_MAX
  291. # ifndef HAVE_BLAS_ILP64
  292. # define NPY_CBLAS_CHUNK (INT_MAX / 2 + 1)
  293. # else
  294. # define NPY_CBLAS_CHUNK (NPY_MAX_INT64 / 2 + 1)
  295. # endif
  296. #else
  297. # define NPY_CBLAS_CHUNK NPY_MAX_INTP
  298. #endif
  299. #include "ucsnarrow.h"
  300. /*
  301. * Make a new empty array, of the passed size, of a type that takes the
  302. * priority of ap1 and ap2 into account.
  303. *
  304. * If `out` is non-NULL, memory overlap is checked with ap1 and ap2, and an
  305. * updateifcopy temporary array may be returned. If `result` is non-NULL, the
  306. * output array to be returned (`out` if non-NULL and the newly allocated array
  307. * otherwise) is incref'd and put to *result.
  308. */
  309. NPY_NO_EXPORT PyArrayObject *
  310. new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
  311. int nd, npy_intp dimensions[], int typenum, PyArrayObject **result);
  312. #endif