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