1 /*
2 Provide multidimensional arrays as a basic object type in python.
3
4 Based on Original Numeric implementation
5 Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu
6
7 with contributions from many Numeric Python developers 1995-2004
8
9 Heavily modified in 2005 with inspiration from Numarray
10
11 by
12
13 Travis Oliphant, oliphant@ee.byu.edu
14 Brigham Young University
15
16
17 maintainer email: oliphant.travis@ieee.org
18
19 Numarray design (which provided guidance) by
20 Space Science Telescope Institute
21 (J. Todd Miller, Perry Greenfield, Rick White)
22 */
23 #define PY_SSIZE_T_CLEAN
24 #include <Python.h>
25 #include "structmember.h"
26
27 /*#include <stdio.h>*/
28 #define NPY_NO_DEPRECATED_API NPY_API_VERSION
29 #define _MULTIARRAYMODULE
30 #include "numpy/arrayobject.h"
31 #include "numpy/arrayscalars.h"
32
33 #include "npy_config.h"
34
35 #include "npy_pycompat.h"
36
37 #include "common.h"
38
39 #include "number.h"
40 #include "usertypes.h"
41 #include "arraytypes.h"
42 #include "scalartypes.h"
43 #include "arrayobject.h"
44 #include "conversion_utils.h"
45 #include "ctors.h"
46 #include "dtypemeta.h"
47 #include "methods.h"
48 #include "descriptor.h"
49 #include "iterators.h"
50 #include "mapping.h"
51 #include "getset.h"
52 #include "sequence.h"
53 #include "npy_buffer.h"
54 #include "array_assign.h"
55 #include "alloc.h"
56 #include "mem_overlap.h"
57 #include "numpyos.h"
58 #include "strfuncs.h"
59
60 #include "binop_override.h"
61 #include "array_coercion.h"
62
63 /*NUMPY_API
64 Compute the size of an array (in number of items)
65 */
66 NPY_NO_EXPORT npy_intp
PyArray_Size(PyObject * op)67 PyArray_Size(PyObject *op)
68 {
69 if (PyArray_Check(op)) {
70 return PyArray_SIZE((PyArrayObject *)op);
71 }
72 else {
73 return 0;
74 }
75 }
76
77 /*NUMPY_API
78 *
79 * Precondition: 'arr' is a copy of 'base' (though possibly with different
80 * strides, ordering, etc.). This function sets the UPDATEIFCOPY flag and the
81 * ->base pointer on 'arr', so that when 'arr' is destructed, it will copy any
82 * changes back to 'base'. DEPRECATED, use PyArray_SetWritebackIfCopyBase
83 *
84 * Steals a reference to 'base'.
85 *
86 * Returns 0 on success, -1 on failure.
87 */
88 NPY_NO_EXPORT int
PyArray_SetUpdateIfCopyBase(PyArrayObject * arr,PyArrayObject * base)89 PyArray_SetUpdateIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
90 {
91 int ret;
92 /* 2017-Nov -10 1.14 (for PyPy only) */
93 /* 2018-April-21 1.15 (all Python implementations) */
94 if (DEPRECATE("PyArray_SetUpdateIfCopyBase is deprecated, use "
95 "PyArray_SetWritebackIfCopyBase instead, and be sure to call "
96 "PyArray_ResolveWritebackIfCopy before the array is deallocated, "
97 "i.e. before the last call to Py_DECREF. If cleaning up from an "
98 "error, PyArray_DiscardWritebackIfCopy may be called instead to "
99 "throw away the scratch buffer.") < 0)
100 return -1;
101 ret = PyArray_SetWritebackIfCopyBase(arr, base);
102 if (ret >=0) {
103 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY);
104 PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
105 }
106 return ret;
107 }
108
109 /*NUMPY_API
110 *
111 * Precondition: 'arr' is a copy of 'base' (though possibly with different
112 * strides, ordering, etc.). This function sets the WRITEBACKIFCOPY flag and the
113 * ->base pointer on 'arr', call PyArray_ResolveWritebackIfCopy to copy any
114 * changes back to 'base' before deallocating the array.
115 *
116 * Steals a reference to 'base'.
117 *
118 * Returns 0 on success, -1 on failure.
119 */
120 NPY_NO_EXPORT int
PyArray_SetWritebackIfCopyBase(PyArrayObject * arr,PyArrayObject * base)121 PyArray_SetWritebackIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
122 {
123 if (base == NULL) {
124 PyErr_SetString(PyExc_ValueError,
125 "Cannot WRITEBACKIFCOPY to NULL array");
126 return -1;
127 }
128 if (PyArray_BASE(arr) != NULL) {
129 PyErr_SetString(PyExc_ValueError,
130 "Cannot set array with existing base to WRITEBACKIFCOPY");
131 goto fail;
132 }
133 if (PyArray_FailUnlessWriteable(base, "WRITEBACKIFCOPY base") < 0) {
134 goto fail;
135 }
136
137 /*
138 * Any writes to 'arr' will magically turn into writes to 'base', so we
139 * should warn if necessary.
140 */
141 if (PyArray_FLAGS(base) & NPY_ARRAY_WARN_ON_WRITE) {
142 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
143 }
144
145 /*
146 * Unlike PyArray_SetBaseObject, we do not compress the chain of base
147 * references.
148 */
149 ((PyArrayObject_fields *)arr)->base = (PyObject *)base;
150 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
151 PyArray_CLEARFLAGS(base, NPY_ARRAY_WRITEABLE);
152
153 return 0;
154
155 fail:
156 Py_DECREF(base);
157 return -1;
158 }
159
160 /*NUMPY_API
161 * Sets the 'base' attribute of the array. This steals a reference
162 * to 'obj'.
163 *
164 * Returns 0 on success, -1 on failure.
165 */
166 NPY_NO_EXPORT int
PyArray_SetBaseObject(PyArrayObject * arr,PyObject * obj)167 PyArray_SetBaseObject(PyArrayObject *arr, PyObject *obj)
168 {
169 if (obj == NULL) {
170 PyErr_SetString(PyExc_ValueError,
171 "Cannot set the NumPy array 'base' "
172 "dependency to NULL after initialization");
173 return -1;
174 }
175 /*
176 * Allow the base to be set only once. Once the object which
177 * owns the data is set, it doesn't make sense to change it.
178 */
179 if (PyArray_BASE(arr) != NULL) {
180 Py_DECREF(obj);
181 PyErr_SetString(PyExc_ValueError,
182 "Cannot set the NumPy array 'base' "
183 "dependency more than once");
184 return -1;
185 }
186
187 /*
188 * Don't allow infinite chains of views, always set the base
189 * to the first owner of the data.
190 * That is, either the first object which isn't an array,
191 * or the first object which owns its own data.
192 */
193
194 while (PyArray_Check(obj) && (PyObject *)arr != obj) {
195 PyArrayObject *obj_arr = (PyArrayObject *)obj;
196 PyObject *tmp;
197
198 /* Propagate WARN_ON_WRITE through views. */
199 if (PyArray_FLAGS(obj_arr) & NPY_ARRAY_WARN_ON_WRITE) {
200 PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
201 }
202
203 /* If this array owns its own data, stop collapsing */
204 if (PyArray_CHKFLAGS(obj_arr, NPY_ARRAY_OWNDATA)) {
205 break;
206 }
207
208 tmp = PyArray_BASE(obj_arr);
209 /* If there's no base, stop collapsing */
210 if (tmp == NULL) {
211 break;
212 }
213 /* Stop the collapse new base when the would not be of the same
214 * type (i.e. different subclass).
215 */
216 if (Py_TYPE(tmp) != Py_TYPE(arr)) {
217 break;
218 }
219
220
221 Py_INCREF(tmp);
222 Py_DECREF(obj);
223 obj = tmp;
224 }
225
226 /* Disallow circular references */
227 if ((PyObject *)arr == obj) {
228 Py_DECREF(obj);
229 PyErr_SetString(PyExc_ValueError,
230 "Cannot create a circular NumPy array 'base' dependency");
231 return -1;
232 }
233
234 ((PyArrayObject_fields *)arr)->base = obj;
235
236 return 0;
237 }
238
239
240 /**
241 * Assign an arbitrary object a NumPy array. This is largely basically
242 * identical to PyArray_FromAny, but assigns directly to the output array.
243 *
244 * @param dest Array to be written to
245 * @param src_object Object to be assigned, array-coercion rules apply.
246 * @return 0 on success -1 on failures.
247 */
248 /*NUMPY_API*/
249 NPY_NO_EXPORT int
PyArray_CopyObject(PyArrayObject * dest,PyObject * src_object)250 PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
251 {
252 int ret = 0;
253 PyArrayObject *view;
254 PyArray_Descr *dtype = NULL;
255 int ndim;
256 npy_intp dims[NPY_MAXDIMS];
257 coercion_cache_obj *cache = NULL;
258
259 /*
260 * We have to set the maximum number of dimensions here to support
261 * sequences within object arrays.
262 */
263 ndim = PyArray_DiscoverDTypeAndShape(src_object,
264 PyArray_NDIM(dest), dims, &cache,
265 NPY_DTYPE(PyArray_DESCR(dest)), PyArray_DESCR(dest), &dtype);
266 if (ndim < 0) {
267 return -1;
268 }
269
270 if (cache != NULL && !(cache->sequence)) {
271 /* The input is an array or array object, so assign directly */
272 assert(cache->converted_obj == src_object);
273 view = (PyArrayObject *)cache->arr_or_sequence;
274 Py_DECREF(dtype);
275 ret = PyArray_AssignArray(dest, view, NULL, NPY_UNSAFE_CASTING);
276 npy_free_coercion_cache(cache);
277 return ret;
278 }
279
280 /*
281 * We may need to broadcast, due to shape mismatches, in this case
282 * create a temporary array first, and assign that after filling
283 * it from the sequences/scalar.
284 */
285 if (ndim != PyArray_NDIM(dest) ||
286 !PyArray_CompareLists(PyArray_DIMS(dest), dims, ndim)) {
287 /*
288 * Broadcasting may be necessary, so assign to a view first.
289 * This branch could lead to a shape mismatch error later.
290 */
291 assert (ndim <= PyArray_NDIM(dest)); /* would error during discovery */
292 view = (PyArrayObject *) PyArray_NewFromDescr(
293 &PyArray_Type, dtype, ndim, dims, NULL, NULL,
294 PyArray_FLAGS(dest) & NPY_ARRAY_F_CONTIGUOUS, NULL);
295 if (view == NULL) {
296 npy_free_coercion_cache(cache);
297 return -1;
298 }
299 }
300 else {
301 Py_DECREF(dtype);
302 view = dest;
303 }
304
305 /* Assign the values to `view` (whichever array that is) */
306 if (cache == NULL) {
307 /* single (non-array) item, assign immediately */
308 if (PyArray_Pack(
309 PyArray_DESCR(view), PyArray_DATA(view), src_object) < 0) {
310 goto fail;
311 }
312 }
313 else {
314 if (PyArray_AssignFromCache(view, cache) < 0) {
315 goto fail;
316 }
317 }
318 if (view == dest) {
319 return 0;
320 }
321 ret = PyArray_AssignArray(dest, view, NULL, NPY_UNSAFE_CASTING);
322 Py_DECREF(view);
323 return ret;
324
325 fail:
326 if (view != dest) {
327 Py_DECREF(view);
328 }
329 return -1;
330 }
331
332
333 /* returns an Array-Scalar Object of the type of arr
334 from the given pointer to memory -- main Scalar creation function
335 default new method calls this.
336 */
337
338 /* Ideally, here the descriptor would contain all the information needed.
339 So, that we simply need the data and the descriptor, and perhaps
340 a flag
341 */
342
343
344 /*
345 Given a string return the type-number for
346 the data-type with that string as the type-object name.
347 Returns NPY_NOTYPE without setting an error if no type can be
348 found. Only works for user-defined data-types.
349 */
350
351 /*NUMPY_API
352 */
353 NPY_NO_EXPORT int
PyArray_TypeNumFromName(char const * str)354 PyArray_TypeNumFromName(char const *str)
355 {
356 int i;
357 PyArray_Descr *descr;
358
359 for (i = 0; i < NPY_NUMUSERTYPES; i++) {
360 descr = userdescrs[i];
361 if (strcmp(descr->typeobj->tp_name, str) == 0) {
362 return descr->type_num;
363 }
364 }
365 return NPY_NOTYPE;
366 }
367
368 /*NUMPY_API
369 *
370 * If WRITEBACKIFCOPY and self has data, reset the base WRITEABLE flag,
371 * copy the local data to base, release the local data, and set flags
372 * appropriately. Return 0 if not relevant, 1 if success, < 0 on failure
373 */
374 NPY_NO_EXPORT int
PyArray_ResolveWritebackIfCopy(PyArrayObject * self)375 PyArray_ResolveWritebackIfCopy(PyArrayObject * self)
376 {
377 PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
378 if (fa && fa->base) {
379 if ((fa->flags & NPY_ARRAY_UPDATEIFCOPY) || (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY)) {
380 /*
381 * UPDATEIFCOPY or WRITEBACKIFCOPY means that fa->base's data
382 * should be updated with the contents
383 * of self.
384 * fa->base->flags is not WRITEABLE to protect the relationship
385 * unlock it.
386 */
387 int retval = 0;
388 PyArray_ENABLEFLAGS(((PyArrayObject *)fa->base),
389 NPY_ARRAY_WRITEABLE);
390 PyArray_CLEARFLAGS(self, NPY_ARRAY_UPDATEIFCOPY);
391 PyArray_CLEARFLAGS(self, NPY_ARRAY_WRITEBACKIFCOPY);
392 retval = PyArray_CopyAnyInto((PyArrayObject *)fa->base, self);
393 Py_DECREF(fa->base);
394 fa->base = NULL;
395 if (retval < 0) {
396 /* this should never happen, how did the two copies of data
397 * get out of sync?
398 */
399 return retval;
400 }
401 return 1;
402 }
403 }
404 return 0;
405 }
406
407 /*********************** end C-API functions **********************/
408
409
410 /* dealloc must not raise an error, best effort try to write
411 to stderr and clear the error
412 */
413
414 static NPY_INLINE void
WARN_IN_DEALLOC(PyObject * warning,const char * msg)415 WARN_IN_DEALLOC(PyObject* warning, const char * msg) {
416 if (PyErr_WarnEx(warning, msg, 1) < 0) {
417 PyObject * s;
418
419 s = PyUnicode_FromString("array_dealloc");
420 if (s) {
421 PyErr_WriteUnraisable(s);
422 Py_DECREF(s);
423 }
424 else {
425 PyErr_WriteUnraisable(Py_None);
426 }
427 }
428 }
429
430 /* array object functions */
431
432 static void
array_dealloc(PyArrayObject * self)433 array_dealloc(PyArrayObject *self)
434 {
435 PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
436
437 if (_buffer_info_free(fa->_buffer_info, (PyObject *)self) < 0) {
438 PyErr_WriteUnraisable(NULL);
439 }
440
441 if (fa->weakreflist != NULL) {
442 PyObject_ClearWeakRefs((PyObject *)self);
443 }
444 if (fa->base) {
445 int retval;
446 if (PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY)
447 {
448 char const * msg = "WRITEBACKIFCOPY detected in array_dealloc. "
449 " Required call to PyArray_ResolveWritebackIfCopy or "
450 "PyArray_DiscardWritebackIfCopy is missing.";
451 /*
452 * prevent reaching 0 twice and thus recursing into dealloc.
453 * Increasing sys.gettotalrefcount, but path should not be taken.
454 */
455 Py_INCREF(self);
456 WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg);
457 retval = PyArray_ResolveWritebackIfCopy(self);
458 if (retval < 0)
459 {
460 PyErr_Print();
461 PyErr_Clear();
462 }
463 }
464 if (PyArray_FLAGS(self) & NPY_ARRAY_UPDATEIFCOPY) {
465 /* DEPRECATED, remove once the flag is removed */
466 char const * msg = "UPDATEIFCOPY detected in array_dealloc. "
467 " Required call to PyArray_ResolveWritebackIfCopy or "
468 "PyArray_DiscardWritebackIfCopy is missing";
469 /*
470 * prevent reaching 0 twice and thus recursing into dealloc.
471 * Increasing sys.gettotalrefcount, but path should not be taken.
472 */
473 Py_INCREF(self);
474 /* 2017-Nov-10 1.14 */
475 WARN_IN_DEALLOC(PyExc_DeprecationWarning, msg);
476 retval = PyArray_ResolveWritebackIfCopy(self);
477 if (retval < 0)
478 {
479 PyErr_Print();
480 PyErr_Clear();
481 }
482 }
483 /*
484 * If fa->base is non-NULL, it is something
485 * to DECREF -- either a view or a buffer object
486 */
487 Py_XDECREF(fa->base);
488 }
489
490 if ((fa->flags & NPY_ARRAY_OWNDATA) && fa->data) {
491 /* Free internal references if an Object array */
492 if (PyDataType_FLAGCHK(fa->descr, NPY_ITEM_REFCOUNT)) {
493 PyArray_XDECREF(self);
494 }
495 npy_free_cache(fa->data, PyArray_NBYTES(self));
496 }
497
498 /* must match allocation in PyArray_NewFromDescr */
499 npy_free_cache_dim(fa->dimensions, 2 * fa->nd);
500 Py_DECREF(fa->descr);
501 Py_TYPE(self)->tp_free((PyObject *)self);
502 }
503
504 /*NUMPY_API
505 * Prints the raw data of the ndarray in a form useful for debugging
506 * low-level C issues.
507 */
508 NPY_NO_EXPORT void
PyArray_DebugPrint(PyArrayObject * obj)509 PyArray_DebugPrint(PyArrayObject *obj)
510 {
511 int i;
512 PyArrayObject_fields *fobj = (PyArrayObject_fields *)obj;
513
514 printf("-------------------------------------------------------\n");
515 printf(" Dump of NumPy ndarray at address %p\n", obj);
516 if (obj == NULL) {
517 printf(" It's NULL!\n");
518 printf("-------------------------------------------------------\n");
519 fflush(stdout);
520 return;
521 }
522 printf(" ndim : %d\n", fobj->nd);
523 printf(" shape :");
524 for (i = 0; i < fobj->nd; ++i) {
525 printf(" %" NPY_INTP_FMT, fobj->dimensions[i]);
526 }
527 printf("\n");
528
529 printf(" dtype : ");
530 PyObject_Print((PyObject *)fobj->descr, stdout, 0);
531 printf("\n");
532 printf(" data : %p\n", fobj->data);
533 printf(" strides:");
534 for (i = 0; i < fobj->nd; ++i) {
535 printf(" %" NPY_INTP_FMT, fobj->strides[i]);
536 }
537 printf("\n");
538
539 printf(" base : %p\n", fobj->base);
540
541 printf(" flags :");
542 if (fobj->flags & NPY_ARRAY_C_CONTIGUOUS)
543 printf(" NPY_C_CONTIGUOUS");
544 if (fobj->flags & NPY_ARRAY_F_CONTIGUOUS)
545 printf(" NPY_F_CONTIGUOUS");
546 if (fobj->flags & NPY_ARRAY_OWNDATA)
547 printf(" NPY_OWNDATA");
548 if (fobj->flags & NPY_ARRAY_ALIGNED)
549 printf(" NPY_ALIGNED");
550 if (fobj->flags & NPY_ARRAY_WRITEABLE)
551 printf(" NPY_WRITEABLE");
552 if (fobj->flags & NPY_ARRAY_UPDATEIFCOPY)
553 printf(" NPY_UPDATEIFCOPY");
554 if (fobj->flags & NPY_ARRAY_WRITEBACKIFCOPY)
555 printf(" NPY_WRITEBACKIFCOPY");
556 printf("\n");
557
558 if (fobj->base != NULL && PyArray_Check(fobj->base)) {
559 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
560 printf("Dump of array's BASE:\n");
561 PyArray_DebugPrint((PyArrayObject *)fobj->base);
562 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
563 }
564 printf("-------------------------------------------------------\n");
565 fflush(stdout);
566 }
567
568
569 /*NUMPY_API
570 * This function is scheduled to be removed
571 *
572 * TO BE REMOVED - NOT USED INTERNALLY.
573 */
574 NPY_NO_EXPORT void
PyArray_SetDatetimeParseFunction(PyObject * NPY_UNUSED (op))575 PyArray_SetDatetimeParseFunction(PyObject *NPY_UNUSED(op))
576 {
577 }
578
579 /*NUMPY_API
580 */
581 NPY_NO_EXPORT int
PyArray_CompareUCS4(npy_ucs4 const * s1,npy_ucs4 const * s2,size_t len)582 PyArray_CompareUCS4(npy_ucs4 const *s1, npy_ucs4 const *s2, size_t len)
583 {
584 npy_ucs4 c1, c2;
585 while(len-- > 0) {
586 c1 = *s1++;
587 c2 = *s2++;
588 if (c1 != c2) {
589 return (c1 < c2) ? -1 : 1;
590 }
591 }
592 return 0;
593 }
594
595 /*NUMPY_API
596 */
597 NPY_NO_EXPORT int
PyArray_CompareString(const char * s1,const char * s2,size_t len)598 PyArray_CompareString(const char *s1, const char *s2, size_t len)
599 {
600 const unsigned char *c1 = (unsigned char *)s1;
601 const unsigned char *c2 = (unsigned char *)s2;
602 size_t i;
603
604 for(i = 0; i < len; ++i) {
605 if (c1[i] != c2[i]) {
606 return (c1[i] > c2[i]) ? 1 : -1;
607 }
608 }
609 return 0;
610 }
611
612
613 /* Call this from contexts where an array might be written to, but we have no
614 * way to tell. (E.g., when converting to a read-write buffer.)
615 */
616 NPY_NO_EXPORT int
array_might_be_written(PyArrayObject * obj)617 array_might_be_written(PyArrayObject *obj)
618 {
619 const char *msg =
620 "Numpy has detected that you (may be) writing to an array with\n"
621 "overlapping memory from np.broadcast_arrays. If this is intentional\n"
622 "set the WRITEABLE flag True or make a copy immediately before writing.";
623 if (PyArray_FLAGS(obj) & NPY_ARRAY_WARN_ON_WRITE) {
624 if (DEPRECATE(msg) < 0) {
625 return -1;
626 }
627 /* Only warn once per array */
628 while (1) {
629 PyArray_CLEARFLAGS(obj, NPY_ARRAY_WARN_ON_WRITE);
630 if (!PyArray_BASE(obj) || !PyArray_Check(PyArray_BASE(obj))) {
631 break;
632 }
633 obj = (PyArrayObject *)PyArray_BASE(obj);
634 }
635 }
636 return 0;
637 }
638
639 /*NUMPY_API
640 *
641 * This function does nothing if obj is writeable, and raises an exception
642 * (and returns -1) if obj is not writeable. It may also do other
643 * house-keeping, such as issuing warnings on arrays which are transitioning
644 * to become views. Always call this function at some point before writing to
645 * an array.
646 *
647 * 'name' is a name for the array, used to give better error
648 * messages. Something like "assignment destination", "output array", or even
649 * just "array".
650 */
651 NPY_NO_EXPORT int
PyArray_FailUnlessWriteable(PyArrayObject * obj,const char * name)652 PyArray_FailUnlessWriteable(PyArrayObject *obj, const char *name)
653 {
654 if (!PyArray_ISWRITEABLE(obj)) {
655 PyErr_Format(PyExc_ValueError, "%s is read-only", name);
656 return -1;
657 }
658 if (array_might_be_written(obj) < 0) {
659 return -1;
660 }
661 return 0;
662 }
663
664 /* This also handles possibly mis-aligned data */
665 /* Compare s1 and s2 which are not necessarily NULL-terminated.
666 s1 is of length len1
667 s2 is of length len2
668 If they are NULL terminated, then stop comparison.
669 */
670 static int
_myunincmp(npy_ucs4 const * s1,npy_ucs4 const * s2,int len1,int len2)671 _myunincmp(npy_ucs4 const *s1, npy_ucs4 const *s2, int len1, int len2)
672 {
673 npy_ucs4 const *sptr;
674 npy_ucs4 *s1t = NULL;
675 npy_ucs4 *s2t = NULL;
676 int val;
677 npy_intp size;
678 int diff;
679
680 /* Replace `s1` and `s2` with aligned copies if needed */
681 if ((npy_intp)s1 % sizeof(npy_ucs4) != 0) {
682 size = len1*sizeof(npy_ucs4);
683 s1t = malloc(size);
684 memcpy(s1t, s1, size);
685 s1 = s1t;
686 }
687 if ((npy_intp)s2 % sizeof(npy_ucs4) != 0) {
688 size = len2*sizeof(npy_ucs4);
689 s2t = malloc(size);
690 memcpy(s2t, s2, size);
691 s2 = s1t;
692 }
693
694 val = PyArray_CompareUCS4(s1, s2, PyArray_MIN(len1,len2));
695 if ((val != 0) || (len1 == len2)) {
696 goto finish;
697 }
698 if (len2 > len1) {
699 sptr = s2+len1;
700 val = -1;
701 diff = len2-len1;
702 }
703 else {
704 sptr = s1+len2;
705 val = 1;
706 diff=len1-len2;
707 }
708 while (diff--) {
709 if (*sptr != 0) {
710 goto finish;
711 }
712 sptr++;
713 }
714 val = 0;
715
716 finish:
717 /* Cleanup the aligned copies */
718 if (s1t) {
719 free(s1t);
720 }
721 if (s2t) {
722 free(s2t);
723 }
724 return val;
725 }
726
727
728
729
730 /*
731 * Compare s1 and s2 which are not necessarily NULL-terminated.
732 * s1 is of length len1
733 * s2 is of length len2
734 * If they are NULL terminated, then stop comparison.
735 */
736 static int
_mystrncmp(char const * s1,char const * s2,int len1,int len2)737 _mystrncmp(char const *s1, char const *s2, int len1, int len2)
738 {
739 char const *sptr;
740 int val;
741 int diff;
742
743 val = memcmp(s1, s2, PyArray_MIN(len1, len2));
744 if ((val != 0) || (len1 == len2)) {
745 return val;
746 }
747 if (len2 > len1) {
748 sptr = s2 + len1;
749 val = -1;
750 diff = len2 - len1;
751 }
752 else {
753 sptr = s1 + len2;
754 val = 1;
755 diff = len1 - len2;
756 }
757 while (diff--) {
758 if (*sptr != 0) {
759 return val;
760 }
761 sptr++;
762 }
763 return 0; /* Only happens if NULLs are everywhere */
764 }
765
766 /* Borrowed from Numarray */
767
768 #define SMALL_STRING 2048
769
_rstripw(char * s,int n)770 static void _rstripw(char *s, int n)
771 {
772 int i;
773 for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
774 int c = s[i];
775
776 if (!c || NumPyOS_ascii_isspace((int)c)) {
777 s[i] = 0;
778 }
779 else {
780 break;
781 }
782 }
783 }
784
_unistripw(npy_ucs4 * s,int n)785 static void _unistripw(npy_ucs4 *s, int n)
786 {
787 int i;
788 for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
789 npy_ucs4 c = s[i];
790 if (!c || NumPyOS_ascii_isspace((int)c)) {
791 s[i] = 0;
792 }
793 else {
794 break;
795 }
796 }
797 }
798
799
800 static char *
_char_copy_n_strip(char const * original,char * temp,int nc)801 _char_copy_n_strip(char const *original, char *temp, int nc)
802 {
803 if (nc > SMALL_STRING) {
804 temp = malloc(nc);
805 if (!temp) {
806 PyErr_NoMemory();
807 return NULL;
808 }
809 }
810 memcpy(temp, original, nc);
811 _rstripw(temp, nc);
812 return temp;
813 }
814
815 static void
_char_release(char * ptr,int nc)816 _char_release(char *ptr, int nc)
817 {
818 if (nc > SMALL_STRING) {
819 free(ptr);
820 }
821 }
822
823 static char *
_uni_copy_n_strip(char const * original,char * temp,int nc)824 _uni_copy_n_strip(char const *original, char *temp, int nc)
825 {
826 if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
827 temp = malloc(nc*sizeof(npy_ucs4));
828 if (!temp) {
829 PyErr_NoMemory();
830 return NULL;
831 }
832 }
833 memcpy(temp, original, nc*sizeof(npy_ucs4));
834 _unistripw((npy_ucs4 *)temp, nc);
835 return temp;
836 }
837
838 static void
_uni_release(char * ptr,int nc)839 _uni_release(char *ptr, int nc)
840 {
841 if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
842 free(ptr);
843 }
844 }
845
846
847 /* End borrowed from numarray */
848
849 #define _rstrip_loop(CMP) { \
850 void *aptr, *bptr; \
851 char atemp[SMALL_STRING], btemp[SMALL_STRING]; \
852 while(size--) { \
853 aptr = stripfunc(iself->dataptr, atemp, N1); \
854 if (!aptr) return -1; \
855 bptr = stripfunc(iother->dataptr, btemp, N2); \
856 if (!bptr) { \
857 relfunc(aptr, N1); \
858 return -1; \
859 } \
860 val = compfunc(aptr, bptr, N1, N2); \
861 *dptr = (val CMP 0); \
862 PyArray_ITER_NEXT(iself); \
863 PyArray_ITER_NEXT(iother); \
864 dptr += 1; \
865 relfunc(aptr, N1); \
866 relfunc(bptr, N2); \
867 } \
868 }
869
870 #define _reg_loop(CMP) { \
871 while(size--) { \
872 val = compfunc((void *)iself->dataptr, \
873 (void *)iother->dataptr, \
874 N1, N2); \
875 *dptr = (val CMP 0); \
876 PyArray_ITER_NEXT(iself); \
877 PyArray_ITER_NEXT(iother); \
878 dptr += 1; \
879 } \
880 }
881
882 static int
_compare_strings(PyArrayObject * result,PyArrayMultiIterObject * multi,int cmp_op,void * func,int rstrip)883 _compare_strings(PyArrayObject *result, PyArrayMultiIterObject *multi,
884 int cmp_op, void *func, int rstrip)
885 {
886 PyArrayIterObject *iself, *iother;
887 npy_bool *dptr;
888 npy_intp size;
889 int val;
890 int N1, N2;
891 int (*compfunc)(void *, void *, int, int);
892 void (*relfunc)(char *, int);
893 char* (*stripfunc)(char const *, char *, int);
894
895 compfunc = func;
896 dptr = (npy_bool *)PyArray_DATA(result);
897 iself = multi->iters[0];
898 iother = multi->iters[1];
899 size = multi->size;
900 N1 = PyArray_DESCR(iself->ao)->elsize;
901 N2 = PyArray_DESCR(iother->ao)->elsize;
902 if ((void *)compfunc == (void *)_myunincmp) {
903 N1 >>= 2;
904 N2 >>= 2;
905 stripfunc = _uni_copy_n_strip;
906 relfunc = _uni_release;
907 }
908 else {
909 stripfunc = _char_copy_n_strip;
910 relfunc = _char_release;
911 }
912 switch (cmp_op) {
913 case Py_EQ:
914 if (rstrip) {
915 _rstrip_loop(==);
916 } else {
917 _reg_loop(==);
918 }
919 break;
920 case Py_NE:
921 if (rstrip) {
922 _rstrip_loop(!=);
923 } else {
924 _reg_loop(!=);
925 }
926 break;
927 case Py_LT:
928 if (rstrip) {
929 _rstrip_loop(<);
930 } else {
931 _reg_loop(<);
932 }
933 break;
934 case Py_LE:
935 if (rstrip) {
936 _rstrip_loop(<=);
937 } else {
938 _reg_loop(<=);
939 }
940 break;
941 case Py_GT:
942 if (rstrip) {
943 _rstrip_loop(>);
944 } else {
945 _reg_loop(>);
946 }
947 break;
948 case Py_GE:
949 if (rstrip) {
950 _rstrip_loop(>=);
951 } else {
952 _reg_loop(>=);
953 }
954 break;
955 default:
956 PyErr_SetString(PyExc_RuntimeError, "bad comparison operator");
957 return -1;
958 }
959 return 0;
960 }
961
962 #undef _reg_loop
963 #undef _rstrip_loop
964 #undef SMALL_STRING
965
966 NPY_NO_EXPORT PyObject *
_strings_richcompare(PyArrayObject * self,PyArrayObject * other,int cmp_op,int rstrip)967 _strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
968 int rstrip)
969 {
970 PyArrayObject *result;
971 PyArrayMultiIterObject *mit;
972 int val;
973
974 /* Cast arrays to a common type */
975 if (PyArray_TYPE(self) != PyArray_DESCR(other)->type_num) {
976 /*
977 * Comparison between Bytes and Unicode is not defined in Py3K;
978 * we follow.
979 */
980 Py_INCREF(Py_NotImplemented);
981 return Py_NotImplemented;
982 }
983 if (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other)) {
984 PyObject *new;
985 if (PyArray_TYPE(self) == NPY_STRING &&
986 PyArray_DESCR(other)->type_num == NPY_UNICODE) {
987 PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(other));
988 unicode->elsize = PyArray_DESCR(self)->elsize << 2;
989 new = PyArray_FromAny((PyObject *)self, unicode,
990 0, 0, 0, NULL);
991 if (new == NULL) {
992 return NULL;
993 }
994 Py_INCREF(other);
995 self = (PyArrayObject *)new;
996 }
997 else if ((PyArray_TYPE(self) == NPY_UNICODE) &&
998 ((PyArray_DESCR(other)->type_num == NPY_STRING) ||
999 (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other)))) {
1000 PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(self));
1001
1002 if (PyArray_DESCR(other)->type_num == NPY_STRING) {
1003 unicode->elsize = PyArray_DESCR(other)->elsize << 2;
1004 }
1005 else {
1006 unicode->elsize = PyArray_DESCR(other)->elsize;
1007 }
1008 new = PyArray_FromAny((PyObject *)other, unicode,
1009 0, 0, 0, NULL);
1010 if (new == NULL) {
1011 return NULL;
1012 }
1013 Py_INCREF(self);
1014 other = (PyArrayObject *)new;
1015 }
1016 else {
1017 PyErr_SetString(PyExc_TypeError,
1018 "invalid string data-types "
1019 "in comparison");
1020 return NULL;
1021 }
1022 }
1023 else {
1024 Py_INCREF(self);
1025 Py_INCREF(other);
1026 }
1027
1028 /* Broad-cast the arrays to a common shape */
1029 mit = (PyArrayMultiIterObject *)PyArray_MultiIterNew(2, self, other);
1030 Py_DECREF(self);
1031 Py_DECREF(other);
1032 if (mit == NULL) {
1033 return NULL;
1034 }
1035
1036 result = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
1037 PyArray_DescrFromType(NPY_BOOL),
1038 mit->nd,
1039 mit->dimensions,
1040 NULL, NULL, 0,
1041 NULL);
1042 if (result == NULL) {
1043 goto finish;
1044 }
1045
1046 if (PyArray_TYPE(self) == NPY_UNICODE) {
1047 val = _compare_strings(result, mit, cmp_op, _myunincmp, rstrip);
1048 }
1049 else {
1050 val = _compare_strings(result, mit, cmp_op, _mystrncmp, rstrip);
1051 }
1052
1053 if (val < 0) {
1054 Py_DECREF(result);
1055 result = NULL;
1056 }
1057
1058 finish:
1059 Py_DECREF(mit);
1060 return (PyObject *)result;
1061 }
1062
1063 /*
1064 * VOID-type arrays can only be compared equal and not-equal
1065 * in which case the fields are all compared by extracting the fields
1066 * and testing one at a time...
1067 * equality testing is performed using logical_ands on all the fields.
1068 * in-equality testing is performed using logical_ors on all the fields.
1069 *
1070 * VOID-type arrays without fields are compared for equality by comparing their
1071 * memory at each location directly (using string-code).
1072 */
1073 static PyObject *
_void_compare(PyArrayObject * self,PyArrayObject * other,int cmp_op)1074 _void_compare(PyArrayObject *self, PyArrayObject *other, int cmp_op)
1075 {
1076 if (!(cmp_op == Py_EQ || cmp_op == Py_NE)) {
1077 PyErr_SetString(PyExc_ValueError,
1078 "Void-arrays can only be compared for equality.");
1079 return NULL;
1080 }
1081 if (PyArray_HASFIELDS(self)) {
1082 PyObject *res = NULL, *temp, *a, *b;
1083 PyObject *key, *value, *temp2;
1084 PyObject *op;
1085 Py_ssize_t pos = 0;
1086 npy_intp result_ndim = PyArray_NDIM(self) > PyArray_NDIM(other) ?
1087 PyArray_NDIM(self) : PyArray_NDIM(other);
1088
1089 op = (cmp_op == Py_EQ ? n_ops.logical_and : n_ops.logical_or);
1090 while (PyDict_Next(PyArray_DESCR(self)->fields, &pos, &key, &value)) {
1091 if (NPY_TITLE_KEY(key, value)) {
1092 continue;
1093 }
1094 a = array_subscript_asarray(self, key);
1095 if (a == NULL) {
1096 Py_XDECREF(res);
1097 return NULL;
1098 }
1099 b = array_subscript_asarray(other, key);
1100 if (b == NULL) {
1101 Py_XDECREF(res);
1102 Py_DECREF(a);
1103 return NULL;
1104 }
1105 temp = array_richcompare((PyArrayObject *)a,b,cmp_op);
1106 Py_DECREF(a);
1107 Py_DECREF(b);
1108 if (temp == NULL) {
1109 Py_XDECREF(res);
1110 return NULL;
1111 }
1112
1113 /*
1114 * If the field type has a non-trivial shape, additional
1115 * dimensions will have been appended to `a` and `b`.
1116 * In that case, reduce them using `op`.
1117 */
1118 if (PyArray_Check(temp) &&
1119 PyArray_NDIM((PyArrayObject *)temp) > result_ndim) {
1120 /* If the type was multidimensional, collapse that part to 1-D
1121 */
1122 if (PyArray_NDIM((PyArrayObject *)temp) != result_ndim+1) {
1123 npy_intp dimensions[NPY_MAXDIMS];
1124 PyArray_Dims newdims;
1125
1126 newdims.ptr = dimensions;
1127 newdims.len = result_ndim+1;
1128 if (result_ndim) {
1129 memcpy(dimensions, PyArray_DIMS((PyArrayObject *)temp),
1130 sizeof(npy_intp)*result_ndim);
1131 }
1132 dimensions[result_ndim] = -1;
1133 temp2 = PyArray_Newshape((PyArrayObject *)temp,
1134 &newdims, NPY_ANYORDER);
1135 if (temp2 == NULL) {
1136 Py_DECREF(temp);
1137 Py_XDECREF(res);
1138 return NULL;
1139 }
1140 Py_DECREF(temp);
1141 temp = temp2;
1142 }
1143 /* Reduce the extra dimension of `temp` using `op` */
1144 temp2 = PyArray_GenericReduceFunction((PyArrayObject *)temp,
1145 op, result_ndim,
1146 NPY_BOOL, NULL);
1147 if (temp2 == NULL) {
1148 Py_DECREF(temp);
1149 Py_XDECREF(res);
1150 return NULL;
1151 }
1152 Py_DECREF(temp);
1153 temp = temp2;
1154 }
1155
1156 if (res == NULL) {
1157 res = temp;
1158 }
1159 else {
1160 temp2 = PyObject_CallFunction(op, "OO", res, temp);
1161 Py_DECREF(temp);
1162 Py_DECREF(res);
1163 if (temp2 == NULL) {
1164 return NULL;
1165 }
1166 res = temp2;
1167 }
1168 }
1169 if (res == NULL && !PyErr_Occurred()) {
1170 /* these dtypes had no fields. Use a MultiIter to broadcast them
1171 * to an output array, and fill with True (for EQ)*/
1172 PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)
1173 PyArray_MultiIterNew(2, self, other);
1174 if (mit == NULL) {
1175 return NULL;
1176 }
1177
1178 res = PyArray_NewFromDescr(&PyArray_Type,
1179 PyArray_DescrFromType(NPY_BOOL),
1180 mit->nd, mit->dimensions,
1181 NULL, NULL, 0, NULL);
1182 Py_DECREF(mit);
1183 if (res) {
1184 PyArray_FILLWBYTE((PyArrayObject *)res,
1185 cmp_op == Py_EQ ? 1 : 0);
1186 }
1187 }
1188 return res;
1189 }
1190 else {
1191 /* compare as a string. Assumes self and other have same descr->type */
1192 return _strings_richcompare(self, other, cmp_op, 0);
1193 }
1194 }
1195
1196 /*
1197 * Silence the current error and emit a deprecation warning instead.
1198 *
1199 * If warnings are raised as errors, this sets the warning __cause__ to the
1200 * silenced error.
1201 */
1202 NPY_NO_EXPORT int
DEPRECATE_silence_error(const char * msg)1203 DEPRECATE_silence_error(const char *msg) {
1204 PyObject *exc, *val, *tb;
1205 PyErr_Fetch(&exc, &val, &tb);
1206 if (DEPRECATE(msg) < 0) {
1207 npy_PyErr_ChainExceptionsCause(exc, val, tb);
1208 return -1;
1209 }
1210 Py_XDECREF(exc);
1211 Py_XDECREF(val);
1212 Py_XDECREF(tb);
1213 return 0;
1214 }
1215
1216 /*
1217 * Comparisons can fail, but we do not always want to pass on the exception
1218 * (see comment in array_richcompare below), but rather return NotImplemented.
1219 * Here, an exception should be set on entrance.
1220 * Returns either NotImplemented with the exception cleared, or NULL
1221 * with the exception set.
1222 * Raises deprecation warnings for cases where behaviour is meant to change
1223 * (2015-05-14, 1.10)
1224 */
1225
1226 NPY_NO_EXPORT PyObject *
_failed_comparison_workaround(PyArrayObject * self,PyObject * other,int cmp_op)1227 _failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
1228 {
1229 PyObject *exc, *val, *tb;
1230 PyArrayObject *array_other;
1231 int other_is_flexible, ndim_other;
1232 int self_is_flexible = PyTypeNum_ISFLEXIBLE(PyArray_DESCR(self)->type_num);
1233
1234 PyErr_Fetch(&exc, &val, &tb);
1235 /*
1236 * Determine whether other has a flexible dtype; here, inconvertible
1237 * is counted as inflexible. (This repeats work done in the ufunc,
1238 * but OK to waste some time in an unlikely path.)
1239 */
1240 array_other = (PyArrayObject *)PyArray_FROM_O(other);
1241 if (array_other) {
1242 other_is_flexible = PyTypeNum_ISFLEXIBLE(
1243 PyArray_DESCR(array_other)->type_num);
1244 ndim_other = PyArray_NDIM(array_other);
1245 Py_DECREF(array_other);
1246 }
1247 else {
1248 PyErr_Clear(); /* we restore the original error if needed */
1249 other_is_flexible = 0;
1250 ndim_other = 0;
1251 }
1252 if (cmp_op == Py_EQ || cmp_op == Py_NE) {
1253 /*
1254 * note: for == and !=, a structured dtype self cannot get here,
1255 * but a string can. Other can be string or structured.
1256 */
1257 if (other_is_flexible || self_is_flexible) {
1258 /*
1259 * For scalars, returning NotImplemented is correct.
1260 * For arrays, we emit a future deprecation warning.
1261 * When this warning is removed, a correctly shaped
1262 * array of bool should be returned.
1263 */
1264 if (ndim_other != 0 || PyArray_NDIM(self) != 0) {
1265 /* 2015-05-14, 1.10 */
1266 if (DEPRECATE_FUTUREWARNING(
1267 "elementwise comparison failed; returning scalar "
1268 "instead, but in the future will perform "
1269 "elementwise comparison") < 0) {
1270 goto fail;
1271 }
1272 }
1273 }
1274 else {
1275 /*
1276 * If neither self nor other had a flexible dtype, the error cannot
1277 * have been caused by a lack of implementation in the ufunc.
1278 *
1279 * 2015-05-14, 1.10
1280 */
1281 if (DEPRECATE(
1282 "elementwise comparison failed; "
1283 "this will raise an error in the future.") < 0) {
1284 goto fail;
1285 }
1286 }
1287 Py_XDECREF(exc);
1288 Py_XDECREF(val);
1289 Py_XDECREF(tb);
1290 Py_INCREF(Py_NotImplemented);
1291 return Py_NotImplemented;
1292 }
1293 else if (other_is_flexible || self_is_flexible) {
1294 /*
1295 * For LE, LT, GT, GE and a flexible self or other, we return
1296 * NotImplemented, which is the correct answer since the ufuncs do
1297 * not in fact implement loops for those. This will get us the
1298 * desired TypeError.
1299 */
1300 Py_XDECREF(exc);
1301 Py_XDECREF(val);
1302 Py_XDECREF(tb);
1303 Py_INCREF(Py_NotImplemented);
1304 return Py_NotImplemented;
1305 }
1306 else {
1307 /* LE, LT, GT, or GE with non-flexible other; just pass on error */
1308 goto fail;
1309 }
1310
1311 fail:
1312 /*
1313 * Reraise the original exception, possibly chaining with a new one.
1314 */
1315 npy_PyErr_ChainExceptionsCause(exc, val, tb);
1316 return NULL;
1317 }
1318
1319 NPY_NO_EXPORT PyObject *
array_richcompare(PyArrayObject * self,PyObject * other,int cmp_op)1320 array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
1321 {
1322 PyArrayObject *array_other;
1323 PyObject *obj_self = (PyObject *)self;
1324 PyObject *result = NULL;
1325
1326 /* Special case for string arrays (which don't and currently can't have
1327 * ufunc loops defined, so there's no point in trying).
1328 */
1329 if (PyArray_ISSTRING(self)) {
1330 array_other = (PyArrayObject *)PyArray_FromObject(other,
1331 NPY_NOTYPE, 0, 0);
1332 if (array_other == NULL) {
1333 PyErr_Clear();
1334 /* Never mind, carry on, see what happens */
1335 }
1336 else if (!PyArray_ISSTRING(array_other)) {
1337 Py_DECREF(array_other);
1338 /* Never mind, carry on, see what happens */
1339 }
1340 else {
1341 result = _strings_richcompare(self, array_other, cmp_op, 0);
1342 Py_DECREF(array_other);
1343 return result;
1344 }
1345 /* If we reach this point, it means that we are not comparing
1346 * string-to-string. It's possible that this will still work out,
1347 * e.g. if the other array is an object array, then both will be cast
1348 * to object or something? I don't know how that works actually, but
1349 * it does, b/c this works:
1350 * l = ["a", "b"]
1351 * assert np.array(l, dtype="S1") == np.array(l, dtype="O")
1352 * So we fall through and see what happens.
1353 */
1354 }
1355
1356 switch (cmp_op) {
1357 case Py_LT:
1358 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1359 result = PyArray_GenericBinaryFunction(self, other, n_ops.less);
1360 break;
1361 case Py_LE:
1362 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1363 result = PyArray_GenericBinaryFunction(self, other, n_ops.less_equal);
1364 break;
1365 case Py_EQ:
1366 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1367 /*
1368 * The ufunc does not support void/structured types, so these
1369 * need to be handled specifically. Only a few cases are supported.
1370 */
1371
1372 if (PyArray_TYPE(self) == NPY_VOID) {
1373 int _res;
1374
1375 array_other = (PyArrayObject *)PyArray_FROM_O(other);
1376 /*
1377 * If not successful, indicate that the items cannot be compared
1378 * this way.
1379 */
1380 if (array_other == NULL) {
1381 /* 2015-05-07, 1.10 */
1382 if (DEPRECATE_silence_error(
1383 "elementwise == comparison failed and returning scalar "
1384 "instead; this will raise an error in the future.") < 0) {
1385 return NULL;
1386 }
1387 Py_INCREF(Py_NotImplemented);
1388 return Py_NotImplemented;
1389 }
1390
1391 _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1392 PyArray_DESCR(array_other),
1393 NPY_EQUIV_CASTING);
1394 if (_res == 0) {
1395 /* 2015-05-07, 1.10 */
1396 Py_DECREF(array_other);
1397 if (DEPRECATE_FUTUREWARNING(
1398 "elementwise == comparison failed and returning scalar "
1399 "instead; this will raise an error or perform "
1400 "elementwise comparison in the future.") < 0) {
1401 return NULL;
1402 }
1403 Py_INCREF(Py_False);
1404 return Py_False;
1405 }
1406 else {
1407 result = _void_compare(self, array_other, cmp_op);
1408 }
1409 Py_DECREF(array_other);
1410 return result;
1411 }
1412
1413 result = PyArray_GenericBinaryFunction(self,
1414 (PyObject *)other,
1415 n_ops.equal);
1416 break;
1417 case Py_NE:
1418 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1419 /*
1420 * The ufunc does not support void/structured types, so these
1421 * need to be handled specifically. Only a few cases are supported.
1422 */
1423
1424 if (PyArray_TYPE(self) == NPY_VOID) {
1425 int _res;
1426
1427 array_other = (PyArrayObject *)PyArray_FROM_O(other);
1428 /*
1429 * If not successful, indicate that the items cannot be compared
1430 * this way.
1431 */
1432 if (array_other == NULL) {
1433 /* 2015-05-07, 1.10 */
1434 if (DEPRECATE_silence_error(
1435 "elementwise != comparison failed and returning scalar "
1436 "instead; this will raise an error in the future.") < 0) {
1437 return NULL;
1438 }
1439 Py_INCREF(Py_NotImplemented);
1440 return Py_NotImplemented;
1441 }
1442
1443 _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1444 PyArray_DESCR(array_other),
1445 NPY_EQUIV_CASTING);
1446 if (_res == 0) {
1447 /* 2015-05-07, 1.10 */
1448 Py_DECREF(array_other);
1449 if (DEPRECATE_FUTUREWARNING(
1450 "elementwise != comparison failed and returning scalar "
1451 "instead; this will raise an error or perform "
1452 "elementwise comparison in the future.") < 0) {
1453 return NULL;
1454 }
1455 Py_INCREF(Py_True);
1456 return Py_True;
1457 }
1458 else {
1459 result = _void_compare(self, array_other, cmp_op);
1460 Py_DECREF(array_other);
1461 }
1462 return result;
1463 }
1464
1465 result = PyArray_GenericBinaryFunction(self, (PyObject *)other,
1466 n_ops.not_equal);
1467 break;
1468 case Py_GT:
1469 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1470 result = PyArray_GenericBinaryFunction(self, other,
1471 n_ops.greater);
1472 break;
1473 case Py_GE:
1474 RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1475 result = PyArray_GenericBinaryFunction(self, other,
1476 n_ops.greater_equal);
1477 break;
1478 default:
1479 Py_INCREF(Py_NotImplemented);
1480 return Py_NotImplemented;
1481 }
1482 if (result == NULL) {
1483 /*
1484 * 2015-05-14, 1.10; updated 2018-06-18, 1.16.
1485 *
1486 * Comparisons can raise errors when element-wise comparison is not
1487 * possible. Some of these, though, should not be passed on.
1488 * In particular, the ufuncs do not have loops for flexible dtype,
1489 * so those should be treated separately. Furthermore, for EQ and NE,
1490 * we should never fail.
1491 *
1492 * Our ideal behaviour would be:
1493 *
1494 * 1. For EQ and NE:
1495 * - If self and other are scalars, return NotImplemented,
1496 * so that python can assign True of False as appropriate.
1497 * - If either is an array, return an array of False or True.
1498 *
1499 * 2. For LT, LE, GE, GT:
1500 * - If self or other was flexible, return NotImplemented
1501 * (as is in fact the case), so python can raise a TypeError.
1502 * - If other is not convertible to an array, pass on the error
1503 * (MHvK, 2018-06-18: not sure about this, but it's what we have).
1504 *
1505 * However, for backwards compatibility, we cannot yet return arrays,
1506 * so we raise warnings instead.
1507 */
1508 result = _failed_comparison_workaround(self, other, cmp_op);
1509 }
1510 return result;
1511 }
1512
1513 /*NUMPY_API
1514 */
1515 NPY_NO_EXPORT int
PyArray_ElementStrides(PyObject * obj)1516 PyArray_ElementStrides(PyObject *obj)
1517 {
1518 PyArrayObject *arr;
1519 int itemsize;
1520 int i, ndim;
1521 npy_intp *strides;
1522
1523 if (!PyArray_Check(obj)) {
1524 return 0;
1525 }
1526
1527 arr = (PyArrayObject *)obj;
1528
1529 itemsize = PyArray_ITEMSIZE(arr);
1530 ndim = PyArray_NDIM(arr);
1531 strides = PyArray_STRIDES(arr);
1532
1533 for (i = 0; i < ndim; i++) {
1534 if ((strides[i] % itemsize) != 0) {
1535 return 0;
1536 }
1537 }
1538 return 1;
1539 }
1540
1541 /*
1542 * This routine checks to see if newstrides (of length nd) will not
1543 * ever be able to walk outside of the memory implied numbytes and offset.
1544 *
1545 * The available memory is assumed to start at -offset and proceed
1546 * to numbytes-offset. The strides are checked to ensure
1547 * that accessing memory using striding will not try to reach beyond
1548 * this memory for any of the axes.
1549 *
1550 * If numbytes is 0 it will be calculated using the dimensions and
1551 * element-size.
1552 *
1553 * This function checks for walking beyond the beginning and right-end
1554 * of the buffer and therefore works for any integer stride (positive
1555 * or negative).
1556 */
1557
1558 /*NUMPY_API*/
1559 NPY_NO_EXPORT npy_bool
PyArray_CheckStrides(int elsize,int nd,npy_intp numbytes,npy_intp offset,npy_intp const * dims,npy_intp const * newstrides)1560 PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp offset,
1561 npy_intp const *dims, npy_intp const *newstrides)
1562 {
1563 npy_intp begin, end;
1564 npy_intp lower_offset;
1565 npy_intp upper_offset;
1566
1567 if (numbytes == 0) {
1568 numbytes = PyArray_MultiplyList(dims, nd) * elsize;
1569 }
1570
1571 begin = -offset;
1572 end = numbytes - offset;
1573
1574 offset_bounds_from_strides(elsize, nd, dims, newstrides,
1575 &lower_offset, &upper_offset);
1576
1577 if ((upper_offset > end) || (lower_offset < begin)) {
1578 return NPY_FALSE;
1579 }
1580 return NPY_TRUE;
1581 }
1582
1583
1584 static PyObject *
array_new(PyTypeObject * subtype,PyObject * args,PyObject * kwds)1585 array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
1586 {
1587 static char *kwlist[] = {"shape", "dtype", "buffer", "offset", "strides",
1588 "order", NULL};
1589 PyArray_Descr *descr = NULL;
1590 int itemsize;
1591 PyArray_Dims dims = {NULL, 0};
1592 PyArray_Dims strides = {NULL, -1};
1593 PyArray_Chunk buffer;
1594 npy_longlong offset = 0;
1595 NPY_ORDER order = NPY_CORDER;
1596 int is_f_order = 0;
1597 PyArrayObject *ret;
1598
1599 buffer.ptr = NULL;
1600 /*
1601 * Usually called with shape and type but can also be called with buffer,
1602 * strides, and swapped info For now, let's just use this to create an
1603 * empty, contiguous array of a specific type and shape.
1604 */
1605 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&LO&O&:ndarray",
1606 kwlist, PyArray_IntpConverter,
1607 &dims,
1608 PyArray_DescrConverter,
1609 &descr,
1610 PyArray_BufferConverter,
1611 &buffer,
1612 &offset,
1613 &PyArray_OptionalIntpConverter,
1614 &strides,
1615 &PyArray_OrderConverter,
1616 &order)) {
1617 goto fail;
1618 }
1619 if (order == NPY_FORTRANORDER) {
1620 is_f_order = 1;
1621 }
1622 if (descr == NULL) {
1623 descr = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
1624 }
1625
1626 itemsize = descr->elsize;
1627
1628 if (strides.len != -1) {
1629 npy_intp nb, off;
1630 if (strides.len != dims.len) {
1631 PyErr_SetString(PyExc_ValueError,
1632 "strides, if given, must be " \
1633 "the same length as shape");
1634 goto fail;
1635 }
1636
1637 if (buffer.ptr == NULL) {
1638 nb = 0;
1639 off = 0;
1640 }
1641 else {
1642 nb = buffer.len;
1643 off = (npy_intp) offset;
1644 }
1645
1646
1647 if (!PyArray_CheckStrides(itemsize, dims.len,
1648 nb, off,
1649 dims.ptr, strides.ptr)) {
1650 PyErr_SetString(PyExc_ValueError,
1651 "strides is incompatible " \
1652 "with shape of requested " \
1653 "array and size of buffer");
1654 goto fail;
1655 }
1656 }
1657
1658 if (buffer.ptr == NULL) {
1659 ret = (PyArrayObject *)
1660 PyArray_NewFromDescr_int(subtype, descr,
1661 (int)dims.len,
1662 dims.ptr,
1663 strides.ptr, NULL, is_f_order, NULL, NULL,
1664 0, 1);
1665 if (ret == NULL) {
1666 descr = NULL;
1667 goto fail;
1668 }
1669 if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT)) {
1670 /* place Py_None in object positions */
1671 PyArray_FillObjectArray(ret, Py_None);
1672 if (PyErr_Occurred()) {
1673 descr = NULL;
1674 goto fail;
1675 }
1676 }
1677 }
1678 else {
1679 /* buffer given -- use it */
1680 if (dims.len == 1 && dims.ptr[0] == -1) {
1681 dims.ptr[0] = (buffer.len-(npy_intp)offset) / itemsize;
1682 }
1683 else if ((strides.ptr == NULL) &&
1684 (buffer.len < (offset + (((npy_intp)itemsize)*
1685 PyArray_MultiplyList(dims.ptr,
1686 dims.len))))) {
1687 PyErr_SetString(PyExc_TypeError,
1688 "buffer is too small for " \
1689 "requested array");
1690 goto fail;
1691 }
1692 /* get writeable and aligned */
1693 if (is_f_order) {
1694 buffer.flags |= NPY_ARRAY_F_CONTIGUOUS;
1695 }
1696 ret = (PyArrayObject *)PyArray_NewFromDescr_int(
1697 subtype, descr,
1698 dims.len, dims.ptr, strides.ptr, offset + (char *)buffer.ptr,
1699 buffer.flags, NULL, buffer.base,
1700 0, 1);
1701 if (ret == NULL) {
1702 descr = NULL;
1703 goto fail;
1704 }
1705 }
1706
1707 npy_free_cache_dim_obj(dims);
1708 npy_free_cache_dim_obj(strides);
1709 return (PyObject *)ret;
1710
1711 fail:
1712 Py_XDECREF(descr);
1713 npy_free_cache_dim_obj(dims);
1714 npy_free_cache_dim_obj(strides);
1715 return NULL;
1716 }
1717
1718
1719 static PyObject *
array_iter(PyArrayObject * arr)1720 array_iter(PyArrayObject *arr)
1721 {
1722 if (PyArray_NDIM(arr) == 0) {
1723 PyErr_SetString(PyExc_TypeError,
1724 "iteration over a 0-d array");
1725 return NULL;
1726 }
1727 return PySeqIter_New((PyObject *)arr);
1728 }
1729
1730 static PyObject *
array_alloc(PyTypeObject * type,Py_ssize_t NPY_UNUSED (nitems))1731 array_alloc(PyTypeObject *type, Py_ssize_t NPY_UNUSED(nitems))
1732 {
1733 /* nitems will always be 0 */
1734 PyObject *obj = PyObject_Malloc(type->tp_basicsize);
1735 PyObject_Init(obj, type);
1736 return obj;
1737 }
1738
1739 static void
array_free(PyObject * v)1740 array_free(PyObject * v)
1741 {
1742 /* avoid same deallocator as PyBaseObject, see gentype_free */
1743 PyObject_Free(v);
1744 }
1745
1746
1747 NPY_NO_EXPORT PyTypeObject PyArray_Type = {
1748 PyVarObject_HEAD_INIT(NULL, 0)
1749 .tp_name = "numpy.ndarray",
1750 .tp_basicsize = sizeof(PyArrayObject_fields),
1751 /* methods */
1752 .tp_dealloc = (destructor)array_dealloc,
1753 .tp_repr = (reprfunc)array_repr,
1754 .tp_as_number = &array_as_number,
1755 .tp_as_sequence = &array_as_sequence,
1756 .tp_as_mapping = &array_as_mapping,
1757 /*
1758 * The tp_hash slot will be set PyObject_HashNotImplemented when the
1759 * module is loaded.
1760 */
1761 .tp_str = (reprfunc)array_str,
1762 .tp_as_buffer = &array_as_buffer,
1763 .tp_flags =(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE),
1764
1765 .tp_richcompare = (richcmpfunc)array_richcompare,
1766 .tp_weaklistoffset = offsetof(PyArrayObject_fields, weakreflist),
1767 .tp_iter = (getiterfunc)array_iter,
1768 .tp_methods = array_methods,
1769 .tp_getset = array_getsetlist,
1770 .tp_alloc = (allocfunc)array_alloc,
1771 .tp_new = (newfunc)array_new,
1772 .tp_free = (freefunc)array_free,
1773 };
1774