1 /*
2   Python Multiarray Module -- A useful collection of functions for creating and
3   using ndarrays
4 
5   Original file
6   Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu
7 
8   Modified for numpy in 2005
9 
10   Travis E. Oliphant
11   oliphant@ee.byu.edu
12   Brigham Young University
13 */
14 
15 /* $Id: multiarraymodule.c,v 1.36 2005/09/14 00:14:00 teoliphant Exp $ */
16 
17 #define PY_SSIZE_T_CLEAN
18 #include "Python.h"
19 #include "structmember.h"
20 
21 #define NPY_NO_DEPRECATED_API NPY_API_VERSION
22 #define _UMATHMODULE
23 #define _MULTIARRAYMODULE
24 #include <numpy/npy_common.h>
25 #include "numpy/arrayobject.h"
26 #include "numpy/arrayscalars.h"
27 
28 #include "numpy/npy_math.h"
29 
30 #include "npy_config.h"
31 #include "npy_pycompat.h"
32 #include "npy_import.h"
33 #include "convert_datatype.h"
34 #include "legacy_dtype_implementation.h"
35 
36 NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
37 
38 /* Internal APIs */
39 #include "alloc.h"
40 #include "abstractdtypes.h"
41 #include "array_coercion.h"
42 #include "arrayfunction_override.h"
43 #include "arraytypes.h"
44 #include "arrayobject.h"
45 #include "hashdescr.h"
46 #include "descriptor.h"
47 #include "dragon4.h"
48 #include "calculation.h"
49 #include "number.h"
50 #include "scalartypes.h"
51 #include "convert_datatype.h"
52 #include "conversion_utils.h"
53 #include "nditer_pywrap.h"
54 #include "methods.h"
55 #include "_datetime.h"
56 #include "datetime_strings.h"
57 #include "datetime_busday.h"
58 #include "datetime_busdaycal.h"
59 #include "item_selection.h"
60 #include "shape.h"
61 #include "ctors.h"
62 #include "array_assign.h"
63 #include "common.h"
64 #include "multiarraymodule.h"
65 #include "cblasfuncs.h"
66 #include "vdot.h"
67 #include "templ_common.h" /* for npy_mul_with_overflow_intp */
68 #include "compiled_base.h"
69 #include "mem_overlap.h"
70 #include "typeinfo.h"
71 
72 #include "get_attr_string.h"
73 
74 /*
75  *****************************************************************************
76  **                    INCLUDE GENERATED CODE                               **
77  *****************************************************************************
78  */
79 #include "funcs.inc"
80 #include "umathmodule.h"
81 
82 NPY_NO_EXPORT int initscalarmath(PyObject *);
83 NPY_NO_EXPORT int set_matmul_flags(PyObject *d); /* in ufunc_object.c */
84 
85 /*
86  * global variable to determine if legacy printing is enabled, accessible from
87  * C. For simplicity the mode is encoded as an integer where '0' means no
88  * legacy mode, and '113' means 1.13 legacy mode. We can upgrade this if we
89  * have more complex requirements in the future.
90  */
91 int npy_legacy_print_mode = 0;
92 
93 static PyObject *
set_legacy_print_mode(PyObject * NPY_UNUSED (self),PyObject * args)94 set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args)
95 {
96     if (!PyArg_ParseTuple(args, "i", &npy_legacy_print_mode)) {
97         return NULL;
98     }
99     Py_RETURN_NONE;
100 }
101 
102 
103 /* Only here for API compatibility */
104 NPY_NO_EXPORT PyTypeObject PyBigArray_Type;
105 
106 
107 /*NUMPY_API
108  * Get Priority from object
109  */
110 NPY_NO_EXPORT double
PyArray_GetPriority(PyObject * obj,double default_)111 PyArray_GetPriority(PyObject *obj, double default_)
112 {
113     PyObject *ret;
114     double priority = NPY_PRIORITY;
115 
116     if (PyArray_CheckExact(obj)) {
117         return priority;
118     }
119     else if (PyArray_CheckAnyScalarExact(obj)) {
120         return NPY_SCALAR_PRIORITY;
121     }
122 
123     ret = PyArray_LookupSpecial_OnInstance(obj, "__array_priority__");
124     if (ret == NULL) {
125         if (PyErr_Occurred()) {
126             PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
127         }
128         return default_;
129     }
130 
131     priority = PyFloat_AsDouble(ret);
132     Py_DECREF(ret);
133     return priority;
134 }
135 
136 /*NUMPY_API
137  * Multiply a List of ints
138  */
139 NPY_NO_EXPORT int
PyArray_MultiplyIntList(int const * l1,int n)140 PyArray_MultiplyIntList(int const *l1, int n)
141 {
142     int s = 1;
143 
144     while (n--) {
145         s *= (*l1++);
146     }
147     return s;
148 }
149 
150 /*NUMPY_API
151  * Multiply a List
152  */
153 NPY_NO_EXPORT npy_intp
PyArray_MultiplyList(npy_intp const * l1,int n)154 PyArray_MultiplyList(npy_intp const *l1, int n)
155 {
156     npy_intp s = 1;
157 
158     while (n--) {
159         s *= (*l1++);
160     }
161     return s;
162 }
163 
164 /*NUMPY_API
165  * Multiply a List of Non-negative numbers with over-flow detection.
166  */
167 NPY_NO_EXPORT npy_intp
PyArray_OverflowMultiplyList(npy_intp const * l1,int n)168 PyArray_OverflowMultiplyList(npy_intp const *l1, int n)
169 {
170     npy_intp prod = 1;
171     int i;
172 
173     for (i = 0; i < n; i++) {
174         npy_intp dim = l1[i];
175 
176         if (dim == 0) {
177             return 0;
178         }
179         if (npy_mul_with_overflow_intp(&prod, prod, dim)) {
180             return -1;
181         }
182     }
183     return prod;
184 }
185 
186 /*NUMPY_API
187  * Produce a pointer into array
188  */
189 NPY_NO_EXPORT void *
PyArray_GetPtr(PyArrayObject * obj,npy_intp const * ind)190 PyArray_GetPtr(PyArrayObject *obj, npy_intp const* ind)
191 {
192     int n = PyArray_NDIM(obj);
193     npy_intp *strides = PyArray_STRIDES(obj);
194     char *dptr = PyArray_DATA(obj);
195 
196     while (n--) {
197         dptr += (*strides++) * (*ind++);
198     }
199     return (void *)dptr;
200 }
201 
202 /*NUMPY_API
203  * Compare Lists
204  */
205 NPY_NO_EXPORT int
PyArray_CompareLists(npy_intp const * l1,npy_intp const * l2,int n)206 PyArray_CompareLists(npy_intp const *l1, npy_intp const *l2, int n)
207 {
208     int i;
209 
210     for (i = 0; i < n; i++) {
211         if (l1[i] != l2[i]) {
212             return 0;
213         }
214     }
215     return 1;
216 }
217 
218 /*
219  * simulates a C-style 1-3 dimensional array which can be accessed using
220  * ptr[i]  or ptr[i][j] or ptr[i][j][k] -- requires pointer allocation
221  * for 2-d and 3-d.
222  *
223  * For 2-d and up, ptr is NOT equivalent to a statically defined
224  * 2-d or 3-d array.  In particular, it cannot be passed into a
225  * function that requires a true pointer to a fixed-size array.
226  */
227 
228 /*NUMPY_API
229  * Simulate a C-array
230  * steals a reference to typedescr -- can be NULL
231  */
232 NPY_NO_EXPORT int
PyArray_AsCArray(PyObject ** op,void * ptr,npy_intp * dims,int nd,PyArray_Descr * typedescr)233 PyArray_AsCArray(PyObject **op, void *ptr, npy_intp *dims, int nd,
234                  PyArray_Descr* typedescr)
235 {
236     PyArrayObject *ap;
237     npy_intp n, m, i, j;
238     char **ptr2;
239     char ***ptr3;
240 
241     if ((nd < 1) || (nd > 3)) {
242         PyErr_SetString(PyExc_ValueError,
243                         "C arrays of only 1-3 dimensions available");
244         Py_XDECREF(typedescr);
245         return -1;
246     }
247     if ((ap = (PyArrayObject*)PyArray_FromAny(*op, typedescr, nd, nd,
248                                       NPY_ARRAY_CARRAY, NULL)) == NULL) {
249         return -1;
250     }
251     switch(nd) {
252     case 1:
253         *((char **)ptr) = PyArray_DATA(ap);
254         break;
255     case 2:
256         n = PyArray_DIMS(ap)[0];
257         ptr2 = (char **)PyArray_malloc(n * sizeof(char *));
258         if (!ptr2) {
259             PyErr_NoMemory();
260             return -1;
261         }
262         for (i = 0; i < n; i++) {
263             ptr2[i] = PyArray_BYTES(ap) + i*PyArray_STRIDES(ap)[0];
264         }
265         *((char ***)ptr) = ptr2;
266         break;
267     case 3:
268         n = PyArray_DIMS(ap)[0];
269         m = PyArray_DIMS(ap)[1];
270         ptr3 = (char ***)PyArray_malloc(n*(m+1) * sizeof(char *));
271         if (!ptr3) {
272             PyErr_NoMemory();
273             return -1;
274         }
275         for (i = 0; i < n; i++) {
276             ptr3[i] = (char **) &ptr3[n + m * i];
277             for (j = 0; j < m; j++) {
278                 ptr3[i][j] = PyArray_BYTES(ap) + i*PyArray_STRIDES(ap)[0] + j*PyArray_STRIDES(ap)[1];
279             }
280         }
281         *((char ****)ptr) = ptr3;
282     }
283     if (nd) {
284         memcpy(dims, PyArray_DIMS(ap), nd*sizeof(npy_intp));
285     }
286     *op = (PyObject *)ap;
287     return 0;
288 }
289 
290 /* Deprecated --- Use PyArray_AsCArray instead */
291 
292 /*NUMPY_API
293  * Convert to a 1D C-array
294  */
295 NPY_NO_EXPORT int
PyArray_As1D(PyObject ** NPY_UNUSED (op),char ** NPY_UNUSED (ptr),int * NPY_UNUSED (d1),int NPY_UNUSED (typecode))296 PyArray_As1D(PyObject **NPY_UNUSED(op), char **NPY_UNUSED(ptr),
297              int *NPY_UNUSED(d1), int NPY_UNUSED(typecode))
298 {
299     /* 2008-07-14, 1.5 */
300     PyErr_SetString(PyExc_NotImplementedError,
301                 "PyArray_As1D: use PyArray_AsCArray.");
302     return -1;
303 }
304 
305 /*NUMPY_API
306  * Convert to a 2D C-array
307  */
308 NPY_NO_EXPORT int
PyArray_As2D(PyObject ** NPY_UNUSED (op),char *** NPY_UNUSED (ptr),int * NPY_UNUSED (d1),int * NPY_UNUSED (d2),int NPY_UNUSED (typecode))309 PyArray_As2D(PyObject **NPY_UNUSED(op), char ***NPY_UNUSED(ptr),
310              int *NPY_UNUSED(d1), int *NPY_UNUSED(d2), int NPY_UNUSED(typecode))
311 {
312     /* 2008-07-14, 1.5 */
313     PyErr_SetString(PyExc_NotImplementedError,
314                 "PyArray_As2D: use PyArray_AsCArray.");
315     return -1;
316 }
317 
318 /* End Deprecated */
319 
320 /*NUMPY_API
321  * Free pointers created if As2D is called
322  */
323 NPY_NO_EXPORT int
PyArray_Free(PyObject * op,void * ptr)324 PyArray_Free(PyObject *op, void *ptr)
325 {
326     PyArrayObject *ap = (PyArrayObject *)op;
327 
328     if ((PyArray_NDIM(ap) < 1) || (PyArray_NDIM(ap) > 3)) {
329         return -1;
330     }
331     if (PyArray_NDIM(ap) >= 2) {
332         PyArray_free(ptr);
333     }
334     Py_DECREF(ap);
335     return 0;
336 }
337 
338 /*
339  * Get the ndarray subclass with the highest priority
340  */
341 NPY_NO_EXPORT PyTypeObject *
PyArray_GetSubType(int narrays,PyArrayObject ** arrays)342 PyArray_GetSubType(int narrays, PyArrayObject **arrays) {
343     PyTypeObject *subtype = &PyArray_Type;
344     double priority = NPY_PRIORITY;
345     int i;
346 
347     /* Get the priority subtype for the array */
348     for (i = 0; i < narrays; ++i) {
349         if (Py_TYPE(arrays[i]) != subtype) {
350             double pr = PyArray_GetPriority((PyObject *)(arrays[i]), 0.0);
351             if (pr > priority) {
352                 priority = pr;
353                 subtype = Py_TYPE(arrays[i]);
354             }
355         }
356     }
357 
358     return subtype;
359 }
360 
361 
362 /*
363  * Concatenates a list of ndarrays.
364  */
365 NPY_NO_EXPORT PyArrayObject *
PyArray_ConcatenateArrays(int narrays,PyArrayObject ** arrays,int axis,PyArrayObject * ret,PyArray_Descr * dtype,NPY_CASTING casting)366 PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis,
367                           PyArrayObject* ret, PyArray_Descr *dtype,
368                           NPY_CASTING casting)
369 {
370     int iarrays, idim, ndim;
371     npy_intp shape[NPY_MAXDIMS];
372     PyArrayObject_fields *sliding_view = NULL;
373 
374     if (narrays <= 0) {
375         PyErr_SetString(PyExc_ValueError,
376                         "need at least one array to concatenate");
377         return NULL;
378     }
379 
380     /* All the arrays must have the same 'ndim' */
381     ndim = PyArray_NDIM(arrays[0]);
382 
383     if (ndim == 0) {
384         PyErr_SetString(PyExc_ValueError,
385                         "zero-dimensional arrays cannot be concatenated");
386         return NULL;
387     }
388 
389     /* Handle standard Python negative indexing */
390     if (check_and_adjust_axis(&axis, ndim) < 0) {
391         return NULL;
392     }
393 
394     /*
395      * Figure out the final concatenated shape starting from the first
396      * array's shape.
397      */
398     memcpy(shape, PyArray_SHAPE(arrays[0]), ndim * sizeof(shape[0]));
399     for (iarrays = 1; iarrays < narrays; ++iarrays) {
400         npy_intp *arr_shape;
401 
402         if (PyArray_NDIM(arrays[iarrays]) != ndim) {
403             PyErr_Format(PyExc_ValueError,
404                          "all the input arrays must have same number of "
405                          "dimensions, but the array at index %d has %d "
406                          "dimension(s) and the array at index %d has %d "
407                          "dimension(s)",
408                          0, ndim, iarrays, PyArray_NDIM(arrays[iarrays]));
409             return NULL;
410         }
411         arr_shape = PyArray_SHAPE(arrays[iarrays]);
412 
413         for (idim = 0; idim < ndim; ++idim) {
414             /* Build up the size of the concatenation axis */
415             if (idim == axis) {
416                 shape[idim] += arr_shape[idim];
417             }
418             /* Validate that the rest of the dimensions match */
419             else if (shape[idim] != arr_shape[idim]) {
420                 PyErr_Format(PyExc_ValueError,
421                              "all the input array dimensions for the "
422                              "concatenation axis must match exactly, but "
423                              "along dimension %d, the array at index %d has "
424                              "size %d and the array at index %d has size %d",
425                              idim, 0, shape[idim], iarrays, arr_shape[idim]);
426                 return NULL;
427             }
428         }
429     }
430 
431     if (ret != NULL) {
432         assert(dtype == NULL);
433         if (PyArray_NDIM(ret) != ndim) {
434             PyErr_SetString(PyExc_ValueError,
435                             "Output array has wrong dimensionality");
436             return NULL;
437         }
438         if (!PyArray_CompareLists(shape, PyArray_SHAPE(ret), ndim)) {
439             PyErr_SetString(PyExc_ValueError,
440                             "Output array is the wrong shape");
441             return NULL;
442         }
443         Py_INCREF(ret);
444     }
445     else {
446         npy_intp s, strides[NPY_MAXDIMS];
447         int strideperm[NPY_MAXDIMS];
448 
449         /* Get the priority subtype for the array */
450         PyTypeObject *subtype = PyArray_GetSubType(narrays, arrays);
451         PyArray_Descr *descr = PyArray_FindConcatenationDescriptor(
452                 narrays, arrays,  (PyObject *)dtype);
453         if (descr == NULL) {
454             return NULL;
455         }
456 
457         /*
458          * Figure out the permutation to apply to the strides to match
459          * the memory layout of the input arrays, using ambiguity
460          * resolution rules matching that of the NpyIter.
461          */
462         PyArray_CreateMultiSortedStridePerm(narrays, arrays, ndim, strideperm);
463         s = descr->elsize;
464         for (idim = ndim-1; idim >= 0; --idim) {
465             int iperm = strideperm[idim];
466             strides[iperm] = s;
467             s *= shape[iperm];
468         }
469 
470         /* Allocate the array for the result. This steals the 'dtype' reference. */
471         ret = (PyArrayObject *)PyArray_NewFromDescr_int(
472                 subtype, descr, ndim, shape, strides, NULL, 0, NULL,
473                 NULL, 0, 1);
474         if (ret == NULL) {
475             return NULL;
476         }
477         assert(PyArray_DESCR(ret) == descr);
478     }
479 
480     /*
481      * Create a view which slides through ret for assigning the
482      * successive input arrays.
483      */
484     sliding_view = (PyArrayObject_fields *)PyArray_View(ret,
485                                                         NULL, &PyArray_Type);
486     if (sliding_view == NULL) {
487         Py_DECREF(ret);
488         return NULL;
489     }
490     for (iarrays = 0; iarrays < narrays; ++iarrays) {
491         /* Set the dimension to match the input array's */
492         sliding_view->dimensions[axis] = PyArray_SHAPE(arrays[iarrays])[axis];
493 
494         /* Copy the data for this array */
495         if (PyArray_AssignArray((PyArrayObject *)sliding_view, arrays[iarrays],
496                             NULL, casting) < 0) {
497             Py_DECREF(sliding_view);
498             Py_DECREF(ret);
499             return NULL;
500         }
501 
502         /* Slide to the start of the next window */
503         sliding_view->data += sliding_view->dimensions[axis] *
504                                  sliding_view->strides[axis];
505     }
506 
507     Py_DECREF(sliding_view);
508     return ret;
509 }
510 
511 /*
512  * Concatenates a list of ndarrays, flattening each in the specified order.
513  */
514 NPY_NO_EXPORT PyArrayObject *
PyArray_ConcatenateFlattenedArrays(int narrays,PyArrayObject ** arrays,NPY_ORDER order,PyArrayObject * ret,PyArray_Descr * dtype,NPY_CASTING casting,npy_bool casting_not_passed)515 PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays,
516                                    NPY_ORDER order, PyArrayObject *ret,
517                                    PyArray_Descr *dtype, NPY_CASTING casting,
518                                    npy_bool casting_not_passed)
519 {
520     int iarrays;
521     npy_intp shape = 0;
522     PyArrayObject_fields *sliding_view = NULL;
523 
524     if (narrays <= 0) {
525         PyErr_SetString(PyExc_ValueError,
526                         "need at least one array to concatenate");
527         return NULL;
528     }
529 
530     /*
531      * Figure out the final concatenated shape starting from the first
532      * array's shape.
533      */
534     for (iarrays = 0; iarrays < narrays; ++iarrays) {
535         shape += PyArray_SIZE(arrays[iarrays]);
536         /* Check for overflow */
537         if (shape < 0) {
538             PyErr_SetString(PyExc_ValueError,
539                             "total number of elements "
540                             "too large to concatenate");
541             return NULL;
542         }
543     }
544 
545     int out_passed = 0;
546     if (ret != NULL) {
547         assert(dtype == NULL);
548         out_passed = 1;
549         if (PyArray_NDIM(ret) != 1) {
550             PyErr_SetString(PyExc_ValueError,
551                             "Output array must be 1D");
552             return NULL;
553         }
554         if (shape != PyArray_SIZE(ret)) {
555             PyErr_SetString(PyExc_ValueError,
556                             "Output array is the wrong size");
557             return NULL;
558         }
559         Py_INCREF(ret);
560     }
561     else {
562         npy_intp stride;
563 
564         /* Get the priority subtype for the array */
565         PyTypeObject *subtype = PyArray_GetSubType(narrays, arrays);
566 
567         PyArray_Descr *descr = PyArray_FindConcatenationDescriptor(
568                 narrays, arrays, (PyObject *)dtype);
569         if (descr == NULL) {
570             return NULL;
571         }
572 
573         stride = descr->elsize;
574 
575         /* Allocate the array for the result. This steals the 'dtype' reference. */
576         ret = (PyArrayObject *)PyArray_NewFromDescr_int(
577                 subtype, descr,  1, &shape, &stride, NULL, 0, NULL,
578                 NULL, 0, 1);
579         if (ret == NULL) {
580             return NULL;
581         }
582         assert(PyArray_DESCR(ret) == descr);
583     }
584 
585     /*
586      * Create a view which slides through ret for assigning the
587      * successive input arrays.
588      */
589     sliding_view = (PyArrayObject_fields *)PyArray_View(ret,
590                                                         NULL, &PyArray_Type);
591     if (sliding_view == NULL) {
592         Py_DECREF(ret);
593         return NULL;
594     }
595 
596     int give_deprecation_warning = 1;  /* To give warning for just one input array. */
597     for (iarrays = 0; iarrays < narrays; ++iarrays) {
598         /* Adjust the window dimensions for this array */
599         sliding_view->dimensions[0] = PyArray_SIZE(arrays[iarrays]);
600 
601         if (!PyArray_CanCastArrayTo(
602                 arrays[iarrays], PyArray_DESCR(ret), casting)) {
603             /* This should be an error, but was previously allowed here. */
604             if (casting_not_passed && out_passed) {
605                 /* NumPy 1.20, 2020-09-03 */
606                 if (give_deprecation_warning && DEPRECATE(
607                         "concatenate() with `axis=None` will use same-kind "
608                         "casting by default in the future. Please use "
609                         "`casting='unsafe'` to retain the old behaviour. "
610                         "In the future this will be a TypeError.") < 0) {
611                     Py_DECREF(sliding_view);
612                     Py_DECREF(ret);
613                     return NULL;
614                 }
615                 give_deprecation_warning = 0;
616             }
617             else {
618                 npy_set_invalid_cast_error(
619                         PyArray_DESCR(arrays[iarrays]), PyArray_DESCR(ret),
620                         casting, PyArray_NDIM(arrays[iarrays]) == 0);
621                 Py_DECREF(sliding_view);
622                 Py_DECREF(ret);
623                 return NULL;
624             }
625         }
626 
627         /* Copy the data for this array */
628         if (PyArray_CopyAsFlat((PyArrayObject *)sliding_view, arrays[iarrays],
629                             order) < 0) {
630             Py_DECREF(sliding_view);
631             Py_DECREF(ret);
632             return NULL;
633         }
634 
635         /* Slide to the start of the next window */
636         sliding_view->data +=
637             sliding_view->strides[0] * PyArray_SIZE(arrays[iarrays]);
638     }
639 
640     Py_DECREF(sliding_view);
641     return ret;
642 }
643 
644 
645 /**
646  * Implementation for np.concatenate
647  *
648  * @param op Sequence of arrays to concatenate
649  * @param axis Axis to concatenate along
650  * @param ret output array to fill
651  * @param dtype Forced output array dtype (cannot be combined with ret)
652  * @param casting Casting mode used
653  * @param casting_not_passed Deprecation helper
654  */
655 NPY_NO_EXPORT PyObject *
PyArray_ConcatenateInto(PyObject * op,int axis,PyArrayObject * ret,PyArray_Descr * dtype,NPY_CASTING casting,npy_bool casting_not_passed)656 PyArray_ConcatenateInto(PyObject *op,
657         int axis, PyArrayObject *ret, PyArray_Descr *dtype,
658         NPY_CASTING casting, npy_bool casting_not_passed)
659 {
660     int iarrays, narrays;
661     PyArrayObject **arrays;
662 
663     if (!PySequence_Check(op)) {
664         PyErr_SetString(PyExc_TypeError,
665                         "The first input argument needs to be a sequence");
666         return NULL;
667     }
668     if (ret != NULL && dtype != NULL) {
669         PyErr_SetString(PyExc_TypeError,
670                 "concatenate() only takes `out` or `dtype` as an "
671                 "argument, but both were provided.");
672         return NULL;
673     }
674 
675     /* Convert the input list into arrays */
676     narrays = PySequence_Size(op);
677     if (narrays < 0) {
678         return NULL;
679     }
680     arrays = PyArray_malloc(narrays * sizeof(arrays[0]));
681     if (arrays == NULL) {
682         PyErr_NoMemory();
683         return NULL;
684     }
685     for (iarrays = 0; iarrays < narrays; ++iarrays) {
686         PyObject *item = PySequence_GetItem(op, iarrays);
687         if (item == NULL) {
688             narrays = iarrays;
689             goto fail;
690         }
691         arrays[iarrays] = (PyArrayObject *)PyArray_FROM_O(item);
692         Py_DECREF(item);
693         if (arrays[iarrays] == NULL) {
694             narrays = iarrays;
695             goto fail;
696         }
697     }
698 
699     if (axis >= NPY_MAXDIMS) {
700         ret = PyArray_ConcatenateFlattenedArrays(
701                 narrays, arrays, NPY_CORDER, ret, dtype,
702                 casting, casting_not_passed);
703     }
704     else {
705         ret = PyArray_ConcatenateArrays(
706                 narrays, arrays, axis, ret, dtype, casting);
707     }
708 
709     for (iarrays = 0; iarrays < narrays; ++iarrays) {
710         Py_DECREF(arrays[iarrays]);
711     }
712     PyArray_free(arrays);
713 
714     return (PyObject *)ret;
715 
716 fail:
717     /* 'narrays' was set to how far we got in the conversion */
718     for (iarrays = 0; iarrays < narrays; ++iarrays) {
719         Py_DECREF(arrays[iarrays]);
720     }
721     PyArray_free(arrays);
722 
723     return NULL;
724 }
725 
726 /*NUMPY_API
727  * Concatenate
728  *
729  * Concatenate an arbitrary Python sequence into an array.
730  * op is a python object supporting the sequence interface.
731  * Its elements will be concatenated together to form a single
732  * multidimensional array. If axis is NPY_MAXDIMS or bigger, then
733  * each sequence object will be flattened before concatenation
734 */
735 NPY_NO_EXPORT PyObject *
PyArray_Concatenate(PyObject * op,int axis)736 PyArray_Concatenate(PyObject *op, int axis)
737 {
738     /* retain legacy behaviour for casting */
739     NPY_CASTING casting;
740     if (axis >= NPY_MAXDIMS) {
741         casting = NPY_UNSAFE_CASTING;
742     }
743     else {
744         casting = NPY_SAME_KIND_CASTING;
745     }
746     return PyArray_ConcatenateInto(
747             op, axis, NULL, NULL, casting, 0);
748 }
749 
750 static int
_signbit_set(PyArrayObject * arr)751 _signbit_set(PyArrayObject *arr)
752 {
753     static char bitmask = (char) 0x80;
754     char *ptr;  /* points to the npy_byte to test */
755     char byteorder;
756     int elsize;
757 
758     elsize = PyArray_DESCR(arr)->elsize;
759     byteorder = PyArray_DESCR(arr)->byteorder;
760     ptr = PyArray_DATA(arr);
761     if (elsize > 1 &&
762         (byteorder == NPY_LITTLE ||
763          (byteorder == NPY_NATIVE &&
764           PyArray_ISNBO(NPY_LITTLE)))) {
765         ptr += elsize - 1;
766     }
767     return ((*ptr & bitmask) != 0);
768 }
769 
770 
771 /*NUMPY_API
772  * ScalarKind
773  *
774  * Returns the scalar kind of a type number, with an
775  * optional tweak based on the scalar value itself.
776  * If no scalar is provided, it returns INTPOS_SCALAR
777  * for both signed and unsigned integers, otherwise
778  * it checks the sign of any signed integer to choose
779  * INTNEG_SCALAR when appropriate.
780  */
781 NPY_NO_EXPORT NPY_SCALARKIND
PyArray_ScalarKind(int typenum,PyArrayObject ** arr)782 PyArray_ScalarKind(int typenum, PyArrayObject **arr)
783 {
784     NPY_SCALARKIND ret = NPY_NOSCALAR;
785 
786     if ((unsigned int)typenum < NPY_NTYPES) {
787         ret = _npy_scalar_kinds_table[typenum];
788         /* Signed integer types are INTNEG in the table */
789         if (ret == NPY_INTNEG_SCALAR) {
790             if (!arr || !_signbit_set(*arr)) {
791                 ret = NPY_INTPOS_SCALAR;
792             }
793         }
794     } else if (PyTypeNum_ISUSERDEF(typenum)) {
795         PyArray_Descr* descr = PyArray_DescrFromType(typenum);
796 
797         if (descr->f->scalarkind) {
798             ret = descr->f->scalarkind((arr ? *arr : NULL));
799         }
800         Py_DECREF(descr);
801     }
802 
803     return ret;
804 }
805 
806 /*NUMPY_API
807  *
808  * Determines whether the data type 'thistype', with
809  * scalar kind 'scalar', can be coerced into 'neededtype'.
810  */
811 NPY_NO_EXPORT int
PyArray_CanCoerceScalar(int thistype,int neededtype,NPY_SCALARKIND scalar)812 PyArray_CanCoerceScalar(int thistype, int neededtype,
813                         NPY_SCALARKIND scalar)
814 {
815     PyArray_Descr* from;
816     int *castlist;
817 
818     /* If 'thistype' is not a scalar, it must be safely castable */
819     if (scalar == NPY_NOSCALAR) {
820         return PyArray_CanCastSafely(thistype, neededtype);
821     }
822     if ((unsigned int)neededtype < NPY_NTYPES) {
823         NPY_SCALARKIND neededscalar;
824 
825         if (scalar == NPY_OBJECT_SCALAR) {
826             return PyArray_CanCastSafely(thistype, neededtype);
827         }
828 
829         /*
830          * The lookup table gives us exactly what we need for
831          * this comparison, which PyArray_ScalarKind would not.
832          *
833          * The rule is that positive scalars can be coerced
834          * to a signed ints, but negative scalars cannot be coerced
835          * to unsigned ints.
836          *   _npy_scalar_kinds_table[int]==NEGINT > POSINT,
837          *      so 1 is returned, but
838          *   _npy_scalar_kinds_table[uint]==POSINT < NEGINT,
839          *      so 0 is returned, as required.
840          *
841          */
842         neededscalar = _npy_scalar_kinds_table[neededtype];
843         if (neededscalar >= scalar) {
844             return 1;
845         }
846         if (!PyTypeNum_ISUSERDEF(thistype)) {
847             return 0;
848         }
849     }
850 
851     from = PyArray_DescrFromType(thistype);
852     if (from->f->cancastscalarkindto
853         && (castlist = from->f->cancastscalarkindto[scalar])) {
854         while (*castlist != NPY_NOTYPE) {
855             if (*castlist++ == neededtype) {
856                 Py_DECREF(from);
857                 return 1;
858             }
859         }
860     }
861     Py_DECREF(from);
862 
863     return 0;
864 }
865 
866 /* Could perhaps be redone to not make contiguous arrays */
867 
868 /*NUMPY_API
869  * Numeric.innerproduct(a,v)
870  */
871 NPY_NO_EXPORT PyObject *
PyArray_InnerProduct(PyObject * op1,PyObject * op2)872 PyArray_InnerProduct(PyObject *op1, PyObject *op2)
873 {
874     PyArrayObject *ap1 = NULL;
875     PyArrayObject *ap2 = NULL;
876     int typenum;
877     PyArray_Descr *typec = NULL;
878     PyObject* ap2t = NULL;
879     npy_intp dims[NPY_MAXDIMS];
880     PyArray_Dims newaxes = {dims, 0};
881     int i;
882     PyObject* ret = NULL;
883 
884     typenum = PyArray_ObjectType(op1, 0);
885     if (typenum == NPY_NOTYPE && PyErr_Occurred()) {
886         return NULL;
887     }
888     typenum = PyArray_ObjectType(op2, typenum);
889     typec = PyArray_DescrFromType(typenum);
890     if (typec == NULL) {
891         if (!PyErr_Occurred()) {
892             PyErr_SetString(PyExc_TypeError,
893                             "Cannot find a common data type.");
894         }
895         goto fail;
896     }
897 
898     Py_INCREF(typec);
899     ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 0, 0,
900                                            NPY_ARRAY_ALIGNED, NULL);
901     if (ap1 == NULL) {
902         Py_DECREF(typec);
903         goto fail;
904     }
905     ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 0, 0,
906                                            NPY_ARRAY_ALIGNED, NULL);
907     if (ap2 == NULL) {
908         goto fail;
909     }
910 
911     newaxes.len = PyArray_NDIM(ap2);
912     if ((PyArray_NDIM(ap1) >= 1) && (newaxes.len >= 2)) {
913         for (i = 0; i < newaxes.len - 2; i++) {
914             dims[i] = (npy_intp)i;
915         }
916         dims[newaxes.len - 2] = newaxes.len - 1;
917         dims[newaxes.len - 1] = newaxes.len - 2;
918 
919         ap2t = PyArray_Transpose(ap2, &newaxes);
920         if (ap2t == NULL) {
921             goto fail;
922         }
923     }
924     else {
925         ap2t = (PyObject *)ap2;
926         Py_INCREF(ap2);
927     }
928 
929     ret = PyArray_MatrixProduct2((PyObject *)ap1, ap2t, NULL);
930     if (ret == NULL) {
931         goto fail;
932     }
933 
934 
935     Py_DECREF(ap1);
936     Py_DECREF(ap2);
937     Py_DECREF(ap2t);
938     return ret;
939 
940 fail:
941     Py_XDECREF(ap1);
942     Py_XDECREF(ap2);
943     Py_XDECREF(ap2t);
944     Py_XDECREF(ret);
945     return NULL;
946 }
947 
948 /*NUMPY_API
949  * Numeric.matrixproduct(a,v)
950  * just like inner product but does the swapaxes stuff on the fly
951  */
952 NPY_NO_EXPORT PyObject *
PyArray_MatrixProduct(PyObject * op1,PyObject * op2)953 PyArray_MatrixProduct(PyObject *op1, PyObject *op2)
954 {
955     return PyArray_MatrixProduct2(op1, op2, NULL);
956 }
957 
958 /*NUMPY_API
959  * Numeric.matrixproduct2(a,v,out)
960  * just like inner product but does the swapaxes stuff on the fly
961  */
962 NPY_NO_EXPORT PyObject *
PyArray_MatrixProduct2(PyObject * op1,PyObject * op2,PyArrayObject * out)963 PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
964 {
965     PyArrayObject *ap1, *ap2, *out_buf = NULL, *result = NULL;
966     PyArrayIterObject *it1, *it2;
967     npy_intp i, j, l;
968     int typenum, nd, axis, matchDim;
969     npy_intp is1, is2, os;
970     char *op;
971     npy_intp dimensions[NPY_MAXDIMS];
972     PyArray_DotFunc *dot;
973     PyArray_Descr *typec = NULL;
974     NPY_BEGIN_THREADS_DEF;
975 
976     typenum = PyArray_ObjectType(op1, 0);
977     if (typenum == NPY_NOTYPE && PyErr_Occurred()) {
978         return NULL;
979     }
980     typenum = PyArray_ObjectType(op2, typenum);
981     typec = PyArray_DescrFromType(typenum);
982     if (typec == NULL) {
983         if (!PyErr_Occurred()) {
984             PyErr_SetString(PyExc_TypeError,
985                             "Cannot find a common data type.");
986         }
987         return NULL;
988     }
989 
990     Py_INCREF(typec);
991     ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 0, 0,
992                                         NPY_ARRAY_ALIGNED, NULL);
993     if (ap1 == NULL) {
994         Py_DECREF(typec);
995         return NULL;
996     }
997     ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 0, 0,
998                                         NPY_ARRAY_ALIGNED, NULL);
999     if (ap2 == NULL) {
1000         Py_DECREF(ap1);
1001         return NULL;
1002     }
1003 
1004 #if defined(HAVE_CBLAS)
1005     if (PyArray_NDIM(ap1) <= 2 && PyArray_NDIM(ap2) <= 2 &&
1006             (NPY_DOUBLE == typenum || NPY_CDOUBLE == typenum ||
1007              NPY_FLOAT == typenum || NPY_CFLOAT == typenum)) {
1008         return cblas_matrixproduct(typenum, ap1, ap2, out);
1009     }
1010 #endif
1011 
1012     if (PyArray_NDIM(ap1) == 0 || PyArray_NDIM(ap2) == 0) {
1013         result = (PyArray_NDIM(ap1) == 0 ? ap1 : ap2);
1014         result = (PyArrayObject *)Py_TYPE(result)->tp_as_number->nb_multiply(
1015                                         (PyObject *)ap1, (PyObject *)ap2);
1016         Py_DECREF(ap1);
1017         Py_DECREF(ap2);
1018         return (PyObject *)result;
1019     }
1020     l = PyArray_DIMS(ap1)[PyArray_NDIM(ap1) - 1];
1021     if (PyArray_NDIM(ap2) > 1) {
1022         matchDim = PyArray_NDIM(ap2) - 2;
1023     }
1024     else {
1025         matchDim = 0;
1026     }
1027     if (PyArray_DIMS(ap2)[matchDim] != l) {
1028         dot_alignment_error(ap1, PyArray_NDIM(ap1) - 1, ap2, matchDim);
1029         goto fail;
1030     }
1031     nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2;
1032     if (nd > NPY_MAXDIMS) {
1033         PyErr_SetString(PyExc_ValueError, "dot: too many dimensions in result");
1034         goto fail;
1035     }
1036     j = 0;
1037     for (i = 0; i < PyArray_NDIM(ap1) - 1; i++) {
1038         dimensions[j++] = PyArray_DIMS(ap1)[i];
1039     }
1040     for (i = 0; i < PyArray_NDIM(ap2) - 2; i++) {
1041         dimensions[j++] = PyArray_DIMS(ap2)[i];
1042     }
1043     if (PyArray_NDIM(ap2) > 1) {
1044         dimensions[j++] = PyArray_DIMS(ap2)[PyArray_NDIM(ap2)-1];
1045     }
1046 
1047     is1 = PyArray_STRIDES(ap1)[PyArray_NDIM(ap1)-1];
1048     is2 = PyArray_STRIDES(ap2)[matchDim];
1049     /* Choose which subtype to return */
1050     out_buf = new_array_for_sum(ap1, ap2, out, nd, dimensions, typenum, &result);
1051     if (out_buf == NULL) {
1052         goto fail;
1053     }
1054     /* Ensure that multiarray.dot(<Nx0>,<0xM>) -> zeros((N,M)) */
1055     if (PyArray_SIZE(ap1) == 0 && PyArray_SIZE(ap2) == 0) {
1056         memset(PyArray_DATA(out_buf), 0, PyArray_NBYTES(out_buf));
1057     }
1058 
1059     dot = PyArray_DESCR(out_buf)->f->dotfunc;
1060     if (dot == NULL) {
1061         PyErr_SetString(PyExc_ValueError,
1062                         "dot not available for this type");
1063         goto fail;
1064     }
1065 
1066     op = PyArray_DATA(out_buf);
1067     os = PyArray_DESCR(out_buf)->elsize;
1068     axis = PyArray_NDIM(ap1)-1;
1069     it1 = (PyArrayIterObject *)
1070         PyArray_IterAllButAxis((PyObject *)ap1, &axis);
1071     if (it1 == NULL) {
1072         goto fail;
1073     }
1074     it2 = (PyArrayIterObject *)
1075         PyArray_IterAllButAxis((PyObject *)ap2, &matchDim);
1076     if (it2 == NULL) {
1077         Py_DECREF(it1);
1078         goto fail;
1079     }
1080     NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ap2));
1081     while (it1->index < it1->size) {
1082         while (it2->index < it2->size) {
1083             dot(it1->dataptr, is1, it2->dataptr, is2, op, l, NULL);
1084             op += os;
1085             PyArray_ITER_NEXT(it2);
1086         }
1087         PyArray_ITER_NEXT(it1);
1088         PyArray_ITER_RESET(it2);
1089     }
1090     NPY_END_THREADS_DESCR(PyArray_DESCR(ap2));
1091     Py_DECREF(it1);
1092     Py_DECREF(it2);
1093     if (PyErr_Occurred()) {
1094         /* only for OBJECT arrays */
1095         goto fail;
1096     }
1097     Py_DECREF(ap1);
1098     Py_DECREF(ap2);
1099 
1100     /* Trigger possible copy-back into `result` */
1101     PyArray_ResolveWritebackIfCopy(out_buf);
1102     Py_DECREF(out_buf);
1103 
1104     return (PyObject *)result;
1105 
1106 fail:
1107     Py_XDECREF(ap1);
1108     Py_XDECREF(ap2);
1109     Py_XDECREF(out_buf);
1110     Py_XDECREF(result);
1111     return NULL;
1112 }
1113 
1114 
1115 /*NUMPY_API
1116  * Copy and Transpose
1117  *
1118  * Could deprecate this function, as there isn't a speed benefit over
1119  * calling Transpose and then Copy.
1120  */
1121 NPY_NO_EXPORT PyObject *
PyArray_CopyAndTranspose(PyObject * op)1122 PyArray_CopyAndTranspose(PyObject *op)
1123 {
1124     PyArrayObject *arr, *tmp, *ret;
1125     int i;
1126     npy_intp new_axes_values[NPY_MAXDIMS];
1127     PyArray_Dims new_axes;
1128 
1129     /* Make sure we have an array */
1130     arr = (PyArrayObject *)PyArray_FROM_O(op);
1131     if (arr == NULL) {
1132         return NULL;
1133     }
1134 
1135     if (PyArray_NDIM(arr) > 1) {
1136         /* Set up the transpose operation */
1137         new_axes.len = PyArray_NDIM(arr);
1138         for (i = 0; i < new_axes.len; ++i) {
1139             new_axes_values[i] = new_axes.len - i - 1;
1140         }
1141         new_axes.ptr = new_axes_values;
1142 
1143         /* Do the transpose (always returns a view) */
1144         tmp = (PyArrayObject *)PyArray_Transpose(arr, &new_axes);
1145         if (tmp == NULL) {
1146             Py_DECREF(arr);
1147             return NULL;
1148         }
1149     }
1150     else {
1151         tmp = arr;
1152         arr = NULL;
1153     }
1154 
1155     /* TODO: Change this to NPY_KEEPORDER for NumPy 2.0 */
1156     ret = (PyArrayObject *)PyArray_NewCopy(tmp, NPY_CORDER);
1157 
1158     Py_XDECREF(arr);
1159     Py_DECREF(tmp);
1160     return (PyObject *)ret;
1161 }
1162 
1163 /*
1164  * Implementation which is common between PyArray_Correlate
1165  * and PyArray_Correlate2.
1166  *
1167  * inverted is set to 1 if computed correlate(ap2, ap1), 0 otherwise
1168  */
1169 static PyArrayObject*
_pyarray_correlate(PyArrayObject * ap1,PyArrayObject * ap2,int typenum,int mode,int * inverted)1170 _pyarray_correlate(PyArrayObject *ap1, PyArrayObject *ap2, int typenum,
1171                    int mode, int *inverted)
1172 {
1173     PyArrayObject *ret;
1174     npy_intp length;
1175     npy_intp i, n1, n2, n, n_left, n_right;
1176     npy_intp is1, is2, os;
1177     char *ip1, *ip2, *op;
1178     PyArray_DotFunc *dot;
1179 
1180     NPY_BEGIN_THREADS_DEF;
1181 
1182     n1 = PyArray_DIMS(ap1)[0];
1183     n2 = PyArray_DIMS(ap2)[0];
1184     if (n1 == 0) {
1185         PyErr_SetString(PyExc_ValueError, "first array argument cannot be empty");
1186         return NULL;
1187     }
1188     if (n2 == 0) {
1189         PyErr_SetString(PyExc_ValueError, "second array argument cannot be empty");
1190         return NULL;
1191     }
1192     if (n1 < n2) {
1193         ret = ap1;
1194         ap1 = ap2;
1195         ap2 = ret;
1196         ret = NULL;
1197         i = n1;
1198         n1 = n2;
1199         n2 = i;
1200         *inverted = 1;
1201     } else {
1202         *inverted = 0;
1203     }
1204 
1205     length = n1;
1206     n = n2;
1207     switch(mode) {
1208     case 0:
1209         length = length - n + 1;
1210         n_left = n_right = 0;
1211         break;
1212     case 1:
1213         n_left = (npy_intp)(n/2);
1214         n_right = n - n_left - 1;
1215         break;
1216     case 2:
1217         n_right = n - 1;
1218         n_left = n - 1;
1219         length = length + n - 1;
1220         break;
1221     default:
1222         PyErr_SetString(PyExc_ValueError, "mode must be 0, 1, or 2");
1223         return NULL;
1224     }
1225 
1226     /*
1227      * Need to choose an output array that can hold a sum
1228      * -- use priority to determine which subtype.
1229      */
1230     ret = new_array_for_sum(ap1, ap2, NULL, 1, &length, typenum, NULL);
1231     if (ret == NULL) {
1232         return NULL;
1233     }
1234     dot = PyArray_DESCR(ret)->f->dotfunc;
1235     if (dot == NULL) {
1236         PyErr_SetString(PyExc_ValueError,
1237                         "function not available for this data type");
1238         goto clean_ret;
1239     }
1240 
1241     NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ret));
1242     is1 = PyArray_STRIDES(ap1)[0];
1243     is2 = PyArray_STRIDES(ap2)[0];
1244     op = PyArray_DATA(ret);
1245     os = PyArray_DESCR(ret)->elsize;
1246     ip1 = PyArray_DATA(ap1);
1247     ip2 = PyArray_BYTES(ap2) + n_left*is2;
1248     n = n - n_left;
1249     for (i = 0; i < n_left; i++) {
1250         dot(ip1, is1, ip2, is2, op, n, ret);
1251         n++;
1252         ip2 -= is2;
1253         op += os;
1254     }
1255     if (small_correlate(ip1, is1, n1 - n2 + 1, PyArray_TYPE(ap1),
1256                         ip2, is2, n, PyArray_TYPE(ap2),
1257                         op, os)) {
1258         ip1 += is1 * (n1 - n2 + 1);
1259         op += os * (n1 - n2 + 1);
1260     }
1261     else {
1262         for (i = 0; i < (n1 - n2 + 1); i++) {
1263             dot(ip1, is1, ip2, is2, op, n, ret);
1264             ip1 += is1;
1265             op += os;
1266         }
1267     }
1268     for (i = 0; i < n_right; i++) {
1269         n--;
1270         dot(ip1, is1, ip2, is2, op, n, ret);
1271         ip1 += is1;
1272         op += os;
1273     }
1274 
1275     NPY_END_THREADS_DESCR(PyArray_DESCR(ret));
1276     if (PyErr_Occurred()) {
1277         goto clean_ret;
1278     }
1279 
1280     return ret;
1281 
1282 clean_ret:
1283     Py_DECREF(ret);
1284     return NULL;
1285 }
1286 
1287 /*
1288  * Revert a one dimensional array in-place
1289  *
1290  * Return 0 on success, other value on failure
1291  */
1292 static int
_pyarray_revert(PyArrayObject * ret)1293 _pyarray_revert(PyArrayObject *ret)
1294 {
1295     npy_intp length = PyArray_DIM(ret, 0);
1296     npy_intp os = PyArray_DESCR(ret)->elsize;
1297     char *op = PyArray_DATA(ret);
1298     char *sw1 = op;
1299     char *sw2;
1300 
1301     if (PyArray_ISNUMBER(ret) && !PyArray_ISCOMPLEX(ret)) {
1302         /* Optimization for unstructured dtypes */
1303         PyArray_CopySwapNFunc *copyswapn = PyArray_DESCR(ret)->f->copyswapn;
1304         sw2 = op + length * os - 1;
1305         /* First reverse the whole array byte by byte... */
1306         while(sw1 < sw2) {
1307             const char tmp = *sw1;
1308             *sw1++ = *sw2;
1309             *sw2-- = tmp;
1310         }
1311         /* ...then swap in place every item */
1312         copyswapn(op, os, NULL, 0, length, 1, NULL);
1313     }
1314     else {
1315         char *tmp = PyArray_malloc(PyArray_DESCR(ret)->elsize);
1316         if (tmp == NULL) {
1317             PyErr_NoMemory();
1318             return -1;
1319         }
1320         sw2 = op + (length - 1) * os;
1321         while (sw1 < sw2) {
1322             memcpy(tmp, sw1, os);
1323             memcpy(sw1, sw2, os);
1324             memcpy(sw2, tmp, os);
1325             sw1 += os;
1326             sw2 -= os;
1327         }
1328         PyArray_free(tmp);
1329     }
1330 
1331     return 0;
1332 }
1333 
1334 /*NUMPY_API
1335  * correlate(a1,a2,mode)
1336  *
1337  * This function computes the usual correlation (correlate(a1, a2) !=
1338  * correlate(a2, a1), and conjugate the second argument for complex inputs
1339  */
1340 NPY_NO_EXPORT PyObject *
PyArray_Correlate2(PyObject * op1,PyObject * op2,int mode)1341 PyArray_Correlate2(PyObject *op1, PyObject *op2, int mode)
1342 {
1343     PyArrayObject *ap1, *ap2, *ret = NULL;
1344     int typenum;
1345     PyArray_Descr *typec;
1346     int inverted;
1347     int st;
1348 
1349     typenum = PyArray_ObjectType(op1, 0);
1350     typenum = PyArray_ObjectType(op2, typenum);
1351 
1352     typec = PyArray_DescrFromType(typenum);
1353     Py_INCREF(typec);
1354     ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 1, 1,
1355                                         NPY_ARRAY_DEFAULT, NULL);
1356     if (ap1 == NULL) {
1357         Py_DECREF(typec);
1358         return NULL;
1359     }
1360     ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 1, 1,
1361                                         NPY_ARRAY_DEFAULT, NULL);
1362     if (ap2 == NULL) {
1363         goto clean_ap1;
1364     }
1365 
1366     if (PyArray_ISCOMPLEX(ap2)) {
1367         PyArrayObject *cap2;
1368         cap2 = (PyArrayObject *)PyArray_Conjugate(ap2, NULL);
1369         if (cap2 == NULL) {
1370             goto clean_ap2;
1371         }
1372         Py_DECREF(ap2);
1373         ap2 = cap2;
1374     }
1375 
1376     ret = _pyarray_correlate(ap1, ap2, typenum, mode, &inverted);
1377     if (ret == NULL) {
1378         goto clean_ap2;
1379     }
1380 
1381     /*
1382      * If we inverted input orders, we need to reverse the output array (i.e.
1383      * ret = ret[::-1])
1384      */
1385     if (inverted) {
1386         st = _pyarray_revert(ret);
1387         if (st) {
1388             goto clean_ret;
1389         }
1390     }
1391 
1392     Py_DECREF(ap1);
1393     Py_DECREF(ap2);
1394     return (PyObject *)ret;
1395 
1396 clean_ret:
1397     Py_DECREF(ret);
1398 clean_ap2:
1399     Py_DECREF(ap2);
1400 clean_ap1:
1401     Py_DECREF(ap1);
1402     return NULL;
1403 }
1404 
1405 /*NUMPY_API
1406  * Numeric.correlate(a1,a2,mode)
1407  */
1408 NPY_NO_EXPORT PyObject *
PyArray_Correlate(PyObject * op1,PyObject * op2,int mode)1409 PyArray_Correlate(PyObject *op1, PyObject *op2, int mode)
1410 {
1411     PyArrayObject *ap1, *ap2, *ret = NULL;
1412     int typenum;
1413     int unused;
1414     PyArray_Descr *typec;
1415 
1416     typenum = PyArray_ObjectType(op1, 0);
1417     typenum = PyArray_ObjectType(op2, typenum);
1418 
1419     typec = PyArray_DescrFromType(typenum);
1420     Py_INCREF(typec);
1421     ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 1, 1,
1422                                             NPY_ARRAY_DEFAULT, NULL);
1423     if (ap1 == NULL) {
1424         Py_DECREF(typec);
1425         return NULL;
1426     }
1427     ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 1, 1,
1428                                            NPY_ARRAY_DEFAULT, NULL);
1429     if (ap2 == NULL) {
1430         goto fail;
1431     }
1432 
1433     ret = _pyarray_correlate(ap1, ap2, typenum, mode, &unused);
1434     if (ret == NULL) {
1435         goto fail;
1436     }
1437     Py_DECREF(ap1);
1438     Py_DECREF(ap2);
1439     return (PyObject *)ret;
1440 
1441 fail:
1442     Py_XDECREF(ap1);
1443     Py_XDECREF(ap2);
1444     Py_XDECREF(ret);
1445     return NULL;
1446 }
1447 
1448 
1449 static PyObject *
array_putmask(PyObject * NPY_UNUSED (module),PyObject * args,PyObject * kwds)1450 array_putmask(PyObject *NPY_UNUSED(module), PyObject *args, PyObject *kwds)
1451 {
1452     PyObject *mask, *values;
1453     PyObject *array;
1454 
1455     static char *kwlist[] = {"arr", "mask", "values", NULL};
1456 
1457     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!OO:putmask", kwlist,
1458                 &PyArray_Type, &array, &mask, &values)) {
1459         return NULL;
1460     }
1461     return PyArray_PutMask((PyArrayObject *)array, values, mask);
1462 }
1463 
1464 
1465 /*NUMPY_API
1466  *
1467  * This function returns true if the two typecodes are
1468  * equivalent (same basic kind and same itemsize).
1469  */
1470 NPY_NO_EXPORT unsigned char
PyArray_EquivTypes(PyArray_Descr * type1,PyArray_Descr * type2)1471 PyArray_EquivTypes(PyArray_Descr *type1, PyArray_Descr *type2)
1472 {
1473 #if NPY_USE_NEW_CASTINGIMPL
1474     /*
1475      * Do not use PyArray_CanCastTypeTo because it supports legacy flexible
1476      * dtypes as input.
1477      */
1478     NPY_CASTING safety = PyArray_GetCastSafety(type1, type2, NULL);
1479     if (safety < 0) {
1480         PyErr_Clear();
1481         return 0;
1482     }
1483     /* If casting is "no casting" this dtypes are considered equivalent. */
1484     return PyArray_MinCastSafety(safety, NPY_NO_CASTING) == NPY_NO_CASTING;
1485 #else
1486     return PyArray_LegacyEquivTypes(type1, type2);
1487 #endif
1488 }
1489 
1490 
1491 /*NUMPY_API*/
1492 NPY_NO_EXPORT unsigned char
PyArray_EquivTypenums(int typenum1,int typenum2)1493 PyArray_EquivTypenums(int typenum1, int typenum2)
1494 {
1495     PyArray_Descr *d1, *d2;
1496     npy_bool ret;
1497 
1498     if (typenum1 == typenum2) {
1499         return NPY_SUCCEED;
1500     }
1501 
1502     d1 = PyArray_DescrFromType(typenum1);
1503     d2 = PyArray_DescrFromType(typenum2);
1504     ret = PyArray_EquivTypes(d1, d2);
1505     Py_DECREF(d1);
1506     Py_DECREF(d2);
1507     return ret;
1508 }
1509 
1510 /*** END C-API FUNCTIONS **/
1511 /*
1512  * NPY_RELAXED_STRIDES_CHECKING: If the strides logic is changed, the
1513  * order specific stride setting is not necessary.
1514  */
1515 static NPY_STEALS_REF_TO_ARG(1) PyObject *
_prepend_ones(PyArrayObject * arr,int nd,int ndmin,NPY_ORDER order)1516 _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order)
1517 {
1518     npy_intp newdims[NPY_MAXDIMS];
1519     npy_intp newstrides[NPY_MAXDIMS];
1520     npy_intp newstride;
1521     int i, k, num;
1522     PyObject *ret;
1523     PyArray_Descr *dtype;
1524 
1525     if (order == NPY_FORTRANORDER || PyArray_ISFORTRAN(arr) || PyArray_NDIM(arr) == 0) {
1526         newstride = PyArray_DESCR(arr)->elsize;
1527     }
1528     else {
1529         newstride = PyArray_STRIDES(arr)[0] * PyArray_DIMS(arr)[0];
1530     }
1531 
1532     num = ndmin - nd;
1533     for (i = 0; i < num; i++) {
1534         newdims[i] = 1;
1535         newstrides[i] = newstride;
1536     }
1537     for (i = num; i < ndmin; i++) {
1538         k = i - num;
1539         newdims[i] = PyArray_DIMS(arr)[k];
1540         newstrides[i] = PyArray_STRIDES(arr)[k];
1541     }
1542     dtype = PyArray_DESCR(arr);
1543     Py_INCREF(dtype);
1544     ret = PyArray_NewFromDescrAndBase(
1545             Py_TYPE(arr), dtype,
1546             ndmin, newdims, newstrides, PyArray_DATA(arr),
1547             PyArray_FLAGS(arr), (PyObject *)arr, (PyObject *)arr);
1548     Py_DECREF(arr);
1549 
1550     return ret;
1551 }
1552 
1553 #define STRIDING_OK(op, order) \
1554                 ((order) == NPY_ANYORDER || \
1555                  (order) == NPY_KEEPORDER || \
1556                  ((order) == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(op)) || \
1557                  ((order) == NPY_FORTRANORDER && PyArray_IS_F_CONTIGUOUS(op)))
1558 
1559 static PyObject *
_array_fromobject(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kws)1560 _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
1561 {
1562     PyObject *op;
1563     PyArrayObject *oparr = NULL, *ret = NULL;
1564     npy_bool subok = NPY_FALSE;
1565     npy_bool copy = NPY_TRUE;
1566     int ndmin = 0, nd;
1567     PyObject* like;
1568     PyArray_Descr *type = NULL;
1569     PyArray_Descr *oldtype = NULL;
1570     NPY_ORDER order = NPY_KEEPORDER;
1571     int flags = 0;
1572 
1573     PyObject* array_function_result = NULL;
1574 
1575     static char *kwd[] = {"object", "dtype", "copy", "order", "subok",
1576                           "ndmin", "like", NULL};
1577 
1578     if (PyTuple_GET_SIZE(args) > 2) {
1579         PyErr_Format(PyExc_TypeError,
1580                      "array() takes from 1 to 2 positional arguments but "
1581                      "%zd were given", PyTuple_GET_SIZE(args));
1582         return NULL;
1583     }
1584 
1585     array_function_result = array_implement_c_array_function_creation(
1586             "array", args, kws);
1587     if (array_function_result != Py_NotImplemented) {
1588         return array_function_result;
1589     }
1590 
1591     /* super-fast path for ndarray argument calls */
1592     if (PyTuple_GET_SIZE(args) == 0) {
1593         goto full_path;
1594     }
1595     op = PyTuple_GET_ITEM(args, 0);
1596     if (PyArray_CheckExact(op)) {
1597         PyObject * dtype_obj = Py_None;
1598         oparr = (PyArrayObject *)op;
1599         /* get dtype which can be positional */
1600         if (PyTuple_GET_SIZE(args) == 2) {
1601             dtype_obj = PyTuple_GET_ITEM(args, 1);
1602         }
1603         else if (kws) {
1604             dtype_obj = PyDict_GetItemWithError(kws, npy_ma_str_dtype);
1605             if (dtype_obj == NULL && PyErr_Occurred()) {
1606                 return NULL;
1607             }
1608             if (dtype_obj == NULL) {
1609                 dtype_obj = Py_None;
1610             }
1611         }
1612         if (dtype_obj != Py_None) {
1613             goto full_path;
1614         }
1615 
1616         /* array(ndarray) */
1617         if (kws == NULL) {
1618             ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1619             goto finish;
1620         }
1621         else {
1622             /* fast path for copy=False rest default (np.asarray) */
1623             PyObject * copy_obj, * order_obj, *ndmin_obj;
1624             copy_obj = PyDict_GetItemWithError(kws, npy_ma_str_copy);
1625             if (copy_obj == NULL && PyErr_Occurred()) {
1626                 return NULL;
1627             }
1628             if (copy_obj != Py_False) {
1629                 goto full_path;
1630             }
1631             copy = NPY_FALSE;
1632 
1633             /* order does not matter for contiguous 1d arrays */
1634             if (PyArray_NDIM((PyArrayObject*)op) > 1 ||
1635                 !PyArray_IS_C_CONTIGUOUS((PyArrayObject*)op)) {
1636                 order_obj = PyDict_GetItemWithError(kws, npy_ma_str_order);
1637                 if (order_obj == NULL && PyErr_Occurred()) {
1638                     return NULL;
1639                 }
1640                 else if (order_obj != Py_None && order_obj != NULL) {
1641                     goto full_path;
1642                 }
1643             }
1644 
1645             ndmin_obj = PyDict_GetItemWithError(kws, npy_ma_str_ndmin);
1646             if (ndmin_obj == NULL && PyErr_Occurred()) {
1647                 return NULL;
1648             }
1649             else if (ndmin_obj) {
1650                 long t = PyLong_AsLong(ndmin_obj);
1651                 if (error_converting(t)) {
1652                     goto clean_type;
1653                 }
1654                 else if (t > NPY_MAXDIMS) {
1655                     goto full_path;
1656                 }
1657                 ndmin = t;
1658             }
1659 
1660             /* copy=False with default dtype, order (any is OK) and ndim */
1661             ret = oparr;
1662             Py_INCREF(ret);
1663             goto finish;
1664         }
1665     }
1666 
1667 full_path:
1668     if (!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i$O:array", kwd,
1669                 &op,
1670                 PyArray_DescrConverter2, &type,
1671                 PyArray_BoolConverter, &copy,
1672                 PyArray_OrderConverter, &order,
1673                 PyArray_BoolConverter, &subok,
1674                 &ndmin,
1675                 &like)) {
1676         goto clean_type;
1677     }
1678 
1679     if (ndmin > NPY_MAXDIMS) {
1680         PyErr_Format(PyExc_ValueError,
1681                 "ndmin bigger than allowable number of dimensions "
1682                 "NPY_MAXDIMS (=%d)", NPY_MAXDIMS);
1683         goto clean_type;
1684     }
1685     /* fast exit if simple call */
1686     if ((subok && PyArray_Check(op)) ||
1687         (!subok && PyArray_CheckExact(op))) {
1688         oparr = (PyArrayObject *)op;
1689         if (type == NULL) {
1690             if (!copy && STRIDING_OK(oparr, order)) {
1691                 ret = oparr;
1692                 Py_INCREF(ret);
1693                 goto finish;
1694             }
1695             else {
1696                 ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1697                 goto finish;
1698             }
1699         }
1700         /* One more chance */
1701         oldtype = PyArray_DESCR(oparr);
1702         if (PyArray_EquivTypes(oldtype, type)) {
1703             if (!copy && STRIDING_OK(oparr, order)) {
1704                 Py_INCREF(op);
1705                 ret = oparr;
1706                 goto finish;
1707             }
1708             else {
1709                 ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1710                 if (oldtype == type || ret == NULL) {
1711                     goto finish;
1712                 }
1713                 Py_INCREF(oldtype);
1714                 Py_DECREF(PyArray_DESCR(ret));
1715                 ((PyArrayObject_fields *)ret)->descr = oldtype;
1716                 goto finish;
1717             }
1718         }
1719     }
1720 
1721     if (copy) {
1722         flags = NPY_ARRAY_ENSURECOPY;
1723     }
1724     if (order == NPY_CORDER) {
1725         flags |= NPY_ARRAY_C_CONTIGUOUS;
1726     }
1727     else if ((order == NPY_FORTRANORDER)
1728                  /* order == NPY_ANYORDER && */
1729                  || (PyArray_Check(op) &&
1730                      PyArray_ISFORTRAN((PyArrayObject *)op))) {
1731         flags |= NPY_ARRAY_F_CONTIGUOUS;
1732     }
1733     if (!subok) {
1734         flags |= NPY_ARRAY_ENSUREARRAY;
1735     }
1736 
1737     flags |= NPY_ARRAY_FORCECAST;
1738     Py_XINCREF(type);
1739     ret = (PyArrayObject *)PyArray_CheckFromAny(op, type,
1740                                                 0, 0, flags, NULL);
1741 
1742  finish:
1743     Py_XDECREF(type);
1744     if (ret == NULL) {
1745         return NULL;
1746     }
1747 
1748     nd = PyArray_NDIM(ret);
1749     if (nd >= ndmin) {
1750         return (PyObject *)ret;
1751     }
1752     /*
1753      * create a new array from the same data with ones in the shape
1754      * steals a reference to ret
1755      */
1756     return _prepend_ones(ret, nd, ndmin, order);
1757 
1758 clean_type:
1759     Py_XDECREF(type);
1760     return NULL;
1761 }
1762 
1763 static PyObject *
array_copyto(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)1764 array_copyto(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1765 {
1766 
1767     static char *kwlist[] = {"dst", "src", "casting", "where", NULL};
1768     PyObject *wheremask_in = NULL;
1769     PyArrayObject *dst = NULL, *src = NULL, *wheremask = NULL;
1770     NPY_CASTING casting = NPY_SAME_KIND_CASTING;
1771 
1772     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&|O&O:copyto", kwlist,
1773                 &PyArray_Type, &dst,
1774                 &PyArray_Converter, &src,
1775                 &PyArray_CastingConverter, &casting,
1776                 &wheremask_in)) {
1777         goto fail;
1778     }
1779 
1780     if (wheremask_in != NULL) {
1781         /* Get the boolean where mask */
1782         PyArray_Descr *dtype = PyArray_DescrFromType(NPY_BOOL);
1783         if (dtype == NULL) {
1784             goto fail;
1785         }
1786         wheremask = (PyArrayObject *)PyArray_FromAny(wheremask_in,
1787                                         dtype, 0, 0, 0, NULL);
1788         if (wheremask == NULL) {
1789             goto fail;
1790         }
1791     }
1792 
1793     if (PyArray_AssignArray(dst, src, wheremask, casting) < 0) {
1794         goto fail;
1795     }
1796 
1797     Py_XDECREF(src);
1798     Py_XDECREF(wheremask);
1799 
1800     Py_RETURN_NONE;
1801 
1802 fail:
1803     Py_XDECREF(src);
1804     Py_XDECREF(wheremask);
1805     return NULL;
1806 }
1807 
1808 static PyObject *
array_empty(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)1809 array_empty(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1810 {
1811 
1812     static char *kwlist[] = {"shape", "dtype", "order", "like", NULL};
1813     PyArray_Descr *typecode = NULL;
1814     PyArray_Dims shape = {NULL, 0};
1815     NPY_ORDER order = NPY_CORDER;
1816     PyObject *like = NULL;
1817     npy_bool is_f_order;
1818     PyObject *array_function_result = NULL;
1819     PyArrayObject *ret = NULL;
1820 
1821     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&$O:empty", kwlist,
1822                 PyArray_IntpConverter, &shape,
1823                 PyArray_DescrConverter, &typecode,
1824                 PyArray_OrderConverter, &order,
1825                 &like)) {
1826         goto fail;
1827     }
1828 
1829     array_function_result = array_implement_c_array_function_creation(
1830             "empty", args, kwds);
1831     if (array_function_result != Py_NotImplemented) {
1832         Py_XDECREF(typecode);
1833         npy_free_cache_dim_obj(shape);
1834         return array_function_result;
1835     }
1836 
1837     switch (order) {
1838         case NPY_CORDER:
1839             is_f_order = NPY_FALSE;
1840             break;
1841         case NPY_FORTRANORDER:
1842             is_f_order = NPY_TRUE;
1843             break;
1844         default:
1845             PyErr_SetString(PyExc_ValueError,
1846                             "only 'C' or 'F' order is permitted");
1847             goto fail;
1848     }
1849 
1850     ret = (PyArrayObject *)PyArray_Empty(shape.len, shape.ptr,
1851                                             typecode, is_f_order);
1852 
1853     npy_free_cache_dim_obj(shape);
1854     return (PyObject *)ret;
1855 
1856 fail:
1857     Py_XDECREF(typecode);
1858     npy_free_cache_dim_obj(shape);
1859     return NULL;
1860 }
1861 
1862 static PyObject *
array_empty_like(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)1863 array_empty_like(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1864 {
1865 
1866     static char *kwlist[] = {"prototype", "dtype", "order", "subok", "shape", NULL};
1867     PyArrayObject *prototype = NULL;
1868     PyArray_Descr *dtype = NULL;
1869     NPY_ORDER order = NPY_KEEPORDER;
1870     PyArrayObject *ret = NULL;
1871     int subok = 1;
1872     /* -1 is a special value meaning "not specified" */
1873     PyArray_Dims shape = {NULL, -1};
1874 
1875     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&iO&:empty_like", kwlist,
1876                 &PyArray_Converter, &prototype,
1877                 &PyArray_DescrConverter2, &dtype,
1878                 &PyArray_OrderConverter, &order,
1879                 &subok,
1880                 &PyArray_OptionalIntpConverter, &shape)) {
1881         goto fail;
1882     }
1883     /* steals the reference to dtype if it's not NULL */
1884     ret = (PyArrayObject *)PyArray_NewLikeArrayWithShape(prototype, order, dtype,
1885                                                          shape.len, shape.ptr, subok);
1886     npy_free_cache_dim_obj(shape);
1887     if (!ret) {
1888         goto fail;
1889     }
1890     Py_DECREF(prototype);
1891 
1892     return (PyObject *)ret;
1893 
1894 fail:
1895     Py_XDECREF(prototype);
1896     Py_XDECREF(dtype);
1897     return NULL;
1898 }
1899 
1900 /*
1901  * This function is needed for supporting Pickles of
1902  * numpy scalar objects.
1903  */
1904 static PyObject *
array_scalar(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)1905 array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1906 {
1907 
1908     static char *kwlist[] = {"dtype", "obj", NULL};
1909     PyArray_Descr *typecode;
1910     PyObject *obj = NULL, *tmpobj = NULL;
1911     int alloc = 0;
1912     void *dptr;
1913     PyObject *ret;
1914     PyObject *base = NULL;
1915 
1916     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O:scalar", kwlist,
1917                 &PyArrayDescr_Type, &typecode, &obj)) {
1918         return NULL;
1919     }
1920     if (PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
1921         if (typecode->type_num == NPY_OBJECT) {
1922             /* Deprecated 2020-11-24, NumPy 1.20 */
1923             if (DEPRECATE(
1924                     "Unpickling a scalar with object dtype is deprecated. "
1925                     "Object scalars should never be created. If this was a "
1926                     "properly created pickle, please open a NumPy issue. In "
1927                     "a best effort this returns the original object.") < 0) {
1928                 return NULL;
1929             }
1930             Py_INCREF(obj);
1931             return obj;
1932         }
1933         /* We store the full array to unpack it here: */
1934         if (!PyArray_CheckExact(obj)) {
1935             /* We pickle structured voids as arrays currently */
1936             PyErr_SetString(PyExc_RuntimeError,
1937                     "Unpickling NPY_LIST_PICKLE (structured void) scalar "
1938                     "requires an array.  The pickle file may be corrupted?");
1939             return NULL;
1940         }
1941         if (!PyArray_EquivTypes(PyArray_DESCR((PyArrayObject *)obj), typecode)) {
1942             PyErr_SetString(PyExc_RuntimeError,
1943                     "Pickled array is not compatible with requested scalar "
1944                     "dtype.  The pickle file may be corrupted?");
1945             return NULL;
1946         }
1947         base = obj;
1948         dptr = PyArray_BYTES((PyArrayObject *)obj);
1949     }
1950 
1951     else if (PyDataType_FLAGCHK(typecode, NPY_ITEM_IS_POINTER)) {
1952         if (obj == NULL) {
1953             obj = Py_None;
1954         }
1955         dptr = &obj;
1956     }
1957     else {
1958         if (obj == NULL) {
1959             if (typecode->elsize == 0) {
1960                 typecode->elsize = 1;
1961             }
1962             dptr = PyArray_malloc(typecode->elsize);
1963             if (dptr == NULL) {
1964                 return PyErr_NoMemory();
1965             }
1966             memset(dptr, '\0', typecode->elsize);
1967             alloc = 1;
1968         }
1969         else {
1970             /* Backward compatibility with Python 2 NumPy pickles */
1971             if (PyUnicode_Check(obj)) {
1972                 tmpobj = PyUnicode_AsLatin1String(obj);
1973                 obj = tmpobj;
1974                 if (tmpobj == NULL) {
1975                     /* More informative error message */
1976                     PyErr_SetString(PyExc_ValueError,
1977                             "Failed to encode Numpy scalar data string to "
1978                             "latin1,\npickle.load(a, encoding='latin1') is "
1979                             "assumed if unpickling.");
1980                     return NULL;
1981                 }
1982             }
1983             if (!PyBytes_Check(obj)) {
1984                 PyErr_SetString(PyExc_TypeError,
1985                         "initializing object must be a bytes object");
1986                 Py_XDECREF(tmpobj);
1987                 return NULL;
1988             }
1989             if (PyBytes_GET_SIZE(obj) < typecode->elsize) {
1990                 PyErr_SetString(PyExc_ValueError,
1991                         "initialization string is too small");
1992                 Py_XDECREF(tmpobj);
1993                 return NULL;
1994             }
1995             dptr = PyBytes_AS_STRING(obj);
1996         }
1997     }
1998     ret = PyArray_Scalar(dptr, typecode, base);
1999 
2000     /* free dptr which contains zeros */
2001     if (alloc) {
2002         PyArray_free(dptr);
2003     }
2004     Py_XDECREF(tmpobj);
2005     return ret;
2006 }
2007 
2008 static PyObject *
array_zeros(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)2009 array_zeros(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
2010 {
2011     static char *kwlist[] = {"shape", "dtype", "order", "like", NULL};
2012     PyArray_Descr *typecode = NULL;
2013     PyArray_Dims shape = {NULL, 0};
2014     NPY_ORDER order = NPY_CORDER;
2015     PyObject *like = NULL;
2016     npy_bool is_f_order = NPY_FALSE;
2017     PyObject *array_function_result = NULL;
2018     PyArrayObject *ret = NULL;
2019 
2020     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&$O:zeros", kwlist,
2021                 PyArray_IntpConverter, &shape,
2022                 PyArray_DescrConverter, &typecode,
2023                 PyArray_OrderConverter, &order,
2024                 &like)) {
2025         goto fail;
2026     }
2027 
2028     array_function_result = array_implement_c_array_function_creation(
2029             "zeros", args, kwds);
2030     if (array_function_result != Py_NotImplemented) {
2031         Py_XDECREF(typecode);
2032         npy_free_cache_dim_obj(shape);
2033         return array_function_result;
2034     }
2035 
2036     switch (order) {
2037         case NPY_CORDER:
2038             is_f_order = NPY_FALSE;
2039             break;
2040         case NPY_FORTRANORDER:
2041             is_f_order = NPY_TRUE;
2042             break;
2043         default:
2044             PyErr_SetString(PyExc_ValueError,
2045                             "only 'C' or 'F' order is permitted");
2046             goto fail;
2047     }
2048 
2049     ret = (PyArrayObject *)PyArray_Zeros(shape.len, shape.ptr,
2050                                         typecode, (int) is_f_order);
2051 
2052     npy_free_cache_dim_obj(shape);
2053     return (PyObject *)ret;
2054 
2055 fail:
2056     Py_XDECREF(typecode);
2057     npy_free_cache_dim_obj(shape);
2058     return (PyObject *)ret;
2059 }
2060 
2061 static PyObject *
array_count_nonzero(PyObject * NPY_UNUSED (self),PyObject * args,PyObject * kwds)2062 array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
2063 {
2064     PyArrayObject *array;
2065     npy_intp count;
2066 
2067     if (!PyArg_ParseTuple(args, "O&:count_nonzero", PyArray_Converter, &array)) {
2068         return NULL;
2069     }
2070 
2071     count =  PyArray_CountNonzero(array);
2072 
2073     Py_DECREF(array);
2074 
2075     if (count == -1) {
2076         return NULL;
2077     }
2078     return PyLong_FromSsize_t(count);
2079 }
2080 
2081 static PyObject *
array_fromstring(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * keywds)2082 array_fromstring(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2083 {
2084     char *data;
2085     Py_ssize_t nin = -1;
2086     char *sep = NULL;
2087     Py_ssize_t s;
2088     static char *kwlist[] = {"string", "dtype", "count", "sep", "like", NULL};
2089     PyObject *like = NULL;
2090     PyArray_Descr *descr = NULL;
2091     PyObject *array_function_result = NULL;
2092 
2093     if (!PyArg_ParseTupleAndKeywords(args, keywds,
2094                 "s#|O&" NPY_SSIZE_T_PYFMT "s$O:fromstring", kwlist,
2095                 &data, &s, PyArray_DescrConverter, &descr, &nin, &sep, &like)) {
2096         Py_XDECREF(descr);
2097         return NULL;
2098     }
2099 
2100     array_function_result = array_implement_c_array_function_creation(
2101             "fromstring", args, keywds);
2102     if (array_function_result != Py_NotImplemented) {
2103         Py_XDECREF(descr);
2104         return array_function_result;
2105     }
2106 
2107     /* binary mode, condition copied from PyArray_FromString */
2108     if (sep == NULL || strlen(sep) == 0) {
2109         /* Numpy 1.14, 2017-10-19 */
2110         if (DEPRECATE(
2111                 "The binary mode of fromstring is deprecated, as it behaves "
2112                 "surprisingly on unicode inputs. Use frombuffer instead") < 0) {
2113             Py_XDECREF(descr);
2114             return NULL;
2115         }
2116     }
2117     return PyArray_FromString(data, (npy_intp)s, descr, (npy_intp)nin, sep);
2118 }
2119 
2120 
2121 
2122 static PyObject *
array_fromfile(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * keywds)2123 array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2124 {
2125     PyObject *file = NULL, *ret = NULL;
2126     PyObject *err_type = NULL, *err_value = NULL, *err_traceback = NULL;
2127     char *sep = "";
2128     Py_ssize_t nin = -1;
2129     static char *kwlist[] = {"file", "dtype", "count", "sep", "offset", "like", NULL};
2130     PyObject *like = NULL;
2131     PyArray_Descr *type = NULL;
2132     PyObject *array_function_result = NULL;
2133     int own;
2134     npy_off_t orig_pos = 0, offset = 0;
2135     FILE *fp;
2136 
2137     if (!PyArg_ParseTupleAndKeywords(args, keywds,
2138                 "O|O&" NPY_SSIZE_T_PYFMT "s" NPY_OFF_T_PYFMT "$O:fromfile", kwlist,
2139                 &file, PyArray_DescrConverter, &type, &nin, &sep, &offset, &like)) {
2140         Py_XDECREF(type);
2141         return NULL;
2142     }
2143 
2144     array_function_result = array_implement_c_array_function_creation(
2145             "fromfile", args, keywds);
2146     if (array_function_result != Py_NotImplemented) {
2147         Py_XDECREF(type);
2148         return array_function_result;
2149     }
2150 
2151     file = NpyPath_PathlikeToFspath(file);
2152     if (file == NULL) {
2153         Py_XDECREF(type);
2154         return NULL;
2155     }
2156 
2157     if (offset != 0 && strcmp(sep, "") != 0) {
2158         PyErr_SetString(PyExc_TypeError, "'offset' argument only permitted for binary files");
2159         Py_XDECREF(type);
2160         Py_DECREF(file);
2161         return NULL;
2162     }
2163     if (PyBytes_Check(file) || PyUnicode_Check(file)) {
2164         Py_SETREF(file, npy_PyFile_OpenFile(file, "rb"));
2165         if (file == NULL) {
2166             Py_XDECREF(type);
2167             return NULL;
2168         }
2169         own = 1;
2170     }
2171     else {
2172         own = 0;
2173     }
2174     fp = npy_PyFile_Dup2(file, "rb", &orig_pos);
2175     if (fp == NULL) {
2176         Py_DECREF(file);
2177         Py_XDECREF(type);
2178         return NULL;
2179     }
2180     if (npy_fseek(fp, offset, SEEK_CUR) != 0) {
2181         PyErr_SetFromErrno(PyExc_IOError);
2182         goto cleanup;
2183     }
2184     if (type == NULL) {
2185         type = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
2186     }
2187     ret = PyArray_FromFile(fp, type, (npy_intp) nin, sep);
2188 
2189     /* If an exception is thrown in the call to PyArray_FromFile
2190      * we need to clear it, and restore it later to ensure that
2191      * we can cleanup the duplicated file descriptor properly.
2192      */
2193 cleanup:
2194     PyErr_Fetch(&err_type, &err_value, &err_traceback);
2195     if (npy_PyFile_DupClose2(file, fp, orig_pos) < 0) {
2196         npy_PyErr_ChainExceptions(err_type, err_value, err_traceback);
2197         goto fail;
2198     }
2199     if (own && npy_PyFile_CloseFile(file) < 0) {
2200         npy_PyErr_ChainExceptions(err_type, err_value, err_traceback);
2201         goto fail;
2202     }
2203     PyErr_Restore(err_type, err_value, err_traceback);
2204     Py_DECREF(file);
2205     return ret;
2206 
2207 fail:
2208     Py_DECREF(file);
2209     Py_XDECREF(ret);
2210     return NULL;
2211 }
2212 
2213 static PyObject *
array_fromiter(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * keywds)2214 array_fromiter(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2215 {
2216     PyObject *iter;
2217     Py_ssize_t nin = -1;
2218     static char *kwlist[] = {"iter", "dtype", "count", "like", NULL};
2219     PyObject *like = NULL;
2220     PyArray_Descr *descr = NULL;
2221     PyObject *array_function_result = NULL;
2222 
2223     if (!PyArg_ParseTupleAndKeywords(args, keywds,
2224                 "OO&|" NPY_SSIZE_T_PYFMT "$O:fromiter", kwlist,
2225                 &iter, PyArray_DescrConverter, &descr, &nin, &like)) {
2226         Py_XDECREF(descr);
2227         return NULL;
2228     }
2229 
2230     array_function_result = array_implement_c_array_function_creation(
2231             "fromiter", args, keywds);
2232     if (array_function_result != Py_NotImplemented) {
2233         Py_DECREF(descr);
2234         return array_function_result;
2235     }
2236 
2237     return PyArray_FromIter(iter, descr, (npy_intp)nin);
2238 }
2239 
2240 static PyObject *
array_frombuffer(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * keywds)2241 array_frombuffer(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2242 {
2243     PyObject *obj = NULL;
2244     Py_ssize_t nin = -1, offset = 0;
2245     static char *kwlist[] = {"buffer", "dtype", "count", "offset", "like", NULL};
2246     PyObject *like = NULL;
2247     PyArray_Descr *type = NULL;
2248     PyObject *array_function_result = NULL;
2249 
2250     if (!PyArg_ParseTupleAndKeywords(args, keywds,
2251                 "O|O&" NPY_SSIZE_T_PYFMT NPY_SSIZE_T_PYFMT "$O:frombuffer", kwlist,
2252                 &obj, PyArray_DescrConverter, &type, &nin, &offset, &like)) {
2253         Py_XDECREF(type);
2254         return NULL;
2255     }
2256 
2257     array_function_result = array_implement_c_array_function_creation(
2258             "frombuffer", args, keywds);
2259     if (array_function_result != Py_NotImplemented) {
2260         Py_XDECREF(type);
2261         return array_function_result;
2262     }
2263 
2264     if (type == NULL) {
2265         type = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
2266     }
2267     return PyArray_FromBuffer(obj, type, (npy_intp)nin, (npy_intp)offset);
2268 }
2269 
2270 static PyObject *
array_concatenate(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2271 array_concatenate(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2272 {
2273     PyObject *a0;
2274     PyObject *out = NULL;
2275     PyArray_Descr *dtype = NULL;
2276     NPY_CASTING casting = NPY_SAME_KIND_CASTING;
2277     PyObject *casting_obj = NULL;
2278     PyObject *res;
2279     int axis = 0;
2280     static char *kwlist[] = {"seq", "axis", "out", "dtype", "casting", NULL};
2281     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O&O$O&O:concatenate", kwlist,
2282                 &a0, PyArray_AxisConverter, &axis, &out,
2283                 PyArray_DescrConverter2, &dtype, &casting_obj)) {
2284         return NULL;
2285     }
2286     int casting_not_passed = 0;
2287     if (casting_obj == NULL) {
2288         /*
2289          * Casting was not passed in, needed for deprecation only.
2290          * This should be simplified once the deprecation is finished.
2291          */
2292         casting_not_passed = 1;
2293     }
2294     else if (!PyArray_CastingConverter(casting_obj, &casting)) {
2295         Py_XDECREF(dtype);
2296         return NULL;
2297     }
2298     if (out != NULL) {
2299         if (out == Py_None) {
2300             out = NULL;
2301         }
2302         else if (!PyArray_Check(out)) {
2303             PyErr_SetString(PyExc_TypeError, "'out' must be an array");
2304             Py_XDECREF(dtype);
2305             return NULL;
2306         }
2307     }
2308     res = PyArray_ConcatenateInto(a0, axis, (PyArrayObject *)out, dtype,
2309             casting, casting_not_passed);
2310     Py_XDECREF(dtype);
2311     return res;
2312 }
2313 
2314 static PyObject *
array_innerproduct(PyObject * NPY_UNUSED (dummy),PyObject * args)2315 array_innerproduct(PyObject *NPY_UNUSED(dummy), PyObject *args)
2316 {
2317     PyObject *b0, *a0;
2318 
2319     if (!PyArg_ParseTuple(args, "OO:innerproduct", &a0, &b0)) {
2320         return NULL;
2321     }
2322     return PyArray_Return((PyArrayObject *)PyArray_InnerProduct(a0, b0));
2323 }
2324 
2325 static PyObject *
array_matrixproduct(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2326 array_matrixproduct(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject* kwds)
2327 {
2328     PyObject *v, *a, *o = NULL;
2329     PyArrayObject *ret;
2330     char* kwlist[] = {"a", "b", "out", NULL };
2331 
2332     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:matrixproduct",
2333                                      kwlist, &a, &v, &o)) {
2334         return NULL;
2335     }
2336     if (o != NULL) {
2337         if (o == Py_None) {
2338             o = NULL;
2339         }
2340         else if (!PyArray_Check(o)) {
2341             PyErr_SetString(PyExc_TypeError, "'out' must be an array");
2342             return NULL;
2343         }
2344     }
2345     ret = (PyArrayObject *)PyArray_MatrixProduct2(a, v, (PyArrayObject *)o);
2346     return PyArray_Return(ret);
2347 }
2348 
2349 
2350 static PyObject *
array_vdot(PyObject * NPY_UNUSED (dummy),PyObject * args)2351 array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args)
2352 {
2353     int typenum;
2354     char *ip1, *ip2, *op;
2355     npy_intp n, stride1, stride2;
2356     PyObject *op1, *op2;
2357     npy_intp newdimptr[1] = {-1};
2358     PyArray_Dims newdims = {newdimptr, 1};
2359     PyArrayObject *ap1 = NULL, *ap2  = NULL, *ret = NULL;
2360     PyArray_Descr *type;
2361     PyArray_DotFunc *vdot;
2362     NPY_BEGIN_THREADS_DEF;
2363 
2364     if (!PyArg_ParseTuple(args, "OO:vdot", &op1, &op2)) {
2365         return NULL;
2366     }
2367 
2368     /*
2369      * Conjugating dot product using the BLAS for vectors.
2370      * Flattens both op1 and op2 before dotting.
2371      */
2372     typenum = PyArray_ObjectType(op1, 0);
2373     typenum = PyArray_ObjectType(op2, typenum);
2374 
2375     type = PyArray_DescrFromType(typenum);
2376     Py_INCREF(type);
2377     ap1 = (PyArrayObject *)PyArray_FromAny(op1, type, 0, 0, 0, NULL);
2378     if (ap1 == NULL) {
2379         Py_DECREF(type);
2380         goto fail;
2381     }
2382 
2383     op1 = PyArray_Newshape(ap1, &newdims, NPY_CORDER);
2384     if (op1 == NULL) {
2385         Py_DECREF(type);
2386         goto fail;
2387     }
2388     Py_DECREF(ap1);
2389     ap1 = (PyArrayObject *)op1;
2390 
2391     ap2 = (PyArrayObject *)PyArray_FromAny(op2, type, 0, 0, 0, NULL);
2392     if (ap2 == NULL) {
2393         goto fail;
2394     }
2395     op2 = PyArray_Newshape(ap2, &newdims, NPY_CORDER);
2396     if (op2 == NULL) {
2397         goto fail;
2398     }
2399     Py_DECREF(ap2);
2400     ap2 = (PyArrayObject *)op2;
2401 
2402     if (PyArray_DIM(ap2, 0) != PyArray_DIM(ap1, 0)) {
2403         PyErr_SetString(PyExc_ValueError,
2404                 "vectors have different lengths");
2405         goto fail;
2406     }
2407 
2408     /* array scalar output */
2409     ret = new_array_for_sum(ap1, ap2, NULL, 0, (npy_intp *)NULL, typenum, NULL);
2410     if (ret == NULL) {
2411         goto fail;
2412     }
2413 
2414     n = PyArray_DIM(ap1, 0);
2415     stride1 = PyArray_STRIDE(ap1, 0);
2416     stride2 = PyArray_STRIDE(ap2, 0);
2417     ip1 = PyArray_DATA(ap1);
2418     ip2 = PyArray_DATA(ap2);
2419     op = PyArray_DATA(ret);
2420 
2421     switch (typenum) {
2422         case NPY_CFLOAT:
2423             vdot = (PyArray_DotFunc *)CFLOAT_vdot;
2424             break;
2425         case NPY_CDOUBLE:
2426             vdot = (PyArray_DotFunc *)CDOUBLE_vdot;
2427             break;
2428         case NPY_CLONGDOUBLE:
2429             vdot = (PyArray_DotFunc *)CLONGDOUBLE_vdot;
2430             break;
2431         case NPY_OBJECT:
2432             vdot = (PyArray_DotFunc *)OBJECT_vdot;
2433             break;
2434         default:
2435             vdot = type->f->dotfunc;
2436             if (vdot == NULL) {
2437                 PyErr_SetString(PyExc_ValueError,
2438                         "function not available for this data type");
2439                 goto fail;
2440             }
2441     }
2442 
2443     if (n < 500) {
2444         vdot(ip1, stride1, ip2, stride2, op, n, NULL);
2445     }
2446     else {
2447         NPY_BEGIN_THREADS_DESCR(type);
2448         vdot(ip1, stride1, ip2, stride2, op, n, NULL);
2449         NPY_END_THREADS_DESCR(type);
2450     }
2451 
2452     Py_XDECREF(ap1);
2453     Py_XDECREF(ap2);
2454     return PyArray_Return(ret);
2455 fail:
2456     Py_XDECREF(ap1);
2457     Py_XDECREF(ap2);
2458     Py_XDECREF(ret);
2459     return NULL;
2460 }
2461 
2462 static int
einsum_sub_op_from_str(PyObject * args,PyObject ** str_obj,char ** subscripts,PyArrayObject ** op)2463 einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts,
2464                        PyArrayObject **op)
2465 {
2466     int i, nop;
2467     PyObject *subscripts_str;
2468 
2469     nop = PyTuple_GET_SIZE(args) - 1;
2470     if (nop <= 0) {
2471         PyErr_SetString(PyExc_ValueError,
2472                         "must specify the einstein sum subscripts string "
2473                         "and at least one operand");
2474         return -1;
2475     }
2476     else if (nop >= NPY_MAXARGS) {
2477         PyErr_SetString(PyExc_ValueError, "too many operands");
2478         return -1;
2479     }
2480 
2481     /* Get the subscripts string */
2482     subscripts_str = PyTuple_GET_ITEM(args, 0);
2483     if (PyUnicode_Check(subscripts_str)) {
2484         *str_obj = PyUnicode_AsASCIIString(subscripts_str);
2485         if (*str_obj == NULL) {
2486             return -1;
2487         }
2488         subscripts_str = *str_obj;
2489     }
2490 
2491     *subscripts = PyBytes_AsString(subscripts_str);
2492     if (*subscripts == NULL) {
2493         Py_XDECREF(*str_obj);
2494         *str_obj = NULL;
2495         return -1;
2496     }
2497 
2498     /* Set the operands to NULL */
2499     for (i = 0; i < nop; ++i) {
2500         op[i] = NULL;
2501     }
2502 
2503     /* Get the operands */
2504     for (i = 0; i < nop; ++i) {
2505         PyObject *obj = PyTuple_GET_ITEM(args, i+1);
2506 
2507         op[i] = (PyArrayObject *)PyArray_FROM_OF(obj, NPY_ARRAY_ENSUREARRAY);
2508         if (op[i] == NULL) {
2509             goto fail;
2510         }
2511     }
2512 
2513     return nop;
2514 
2515 fail:
2516     for (i = 0; i < nop; ++i) {
2517         Py_XDECREF(op[i]);
2518         op[i] = NULL;
2519     }
2520 
2521     return -1;
2522 }
2523 
2524 /*
2525  * Converts a list of subscripts to a string.
2526  *
2527  * Returns -1 on error, the number of characters placed in subscripts
2528  * otherwise.
2529  */
2530 static int
einsum_list_to_subscripts(PyObject * obj,char * subscripts,int subsize)2531 einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
2532 {
2533     int ellipsis = 0, subindex = 0;
2534     npy_intp i, size;
2535     PyObject *item;
2536 
2537     obj = PySequence_Fast(obj, "the subscripts for each operand must "
2538                                "be a list or a tuple");
2539     if (obj == NULL) {
2540         return -1;
2541     }
2542     size = PySequence_Size(obj);
2543 
2544     for (i = 0; i < size; ++i) {
2545         item = PySequence_Fast_GET_ITEM(obj, i);
2546         /* Ellipsis */
2547         if (item == Py_Ellipsis) {
2548             if (ellipsis) {
2549                 PyErr_SetString(PyExc_ValueError,
2550                         "each subscripts list may have only one ellipsis");
2551                 Py_DECREF(obj);
2552                 return -1;
2553             }
2554             if (subindex + 3 >= subsize) {
2555                 PyErr_SetString(PyExc_ValueError,
2556                         "subscripts list is too long");
2557                 Py_DECREF(obj);
2558                 return -1;
2559             }
2560             subscripts[subindex++] = '.';
2561             subscripts[subindex++] = '.';
2562             subscripts[subindex++] = '.';
2563             ellipsis = 1;
2564         }
2565         /* Subscript */
2566         else {
2567             npy_intp s = PyArray_PyIntAsIntp(item);
2568             /* Invalid */
2569             if (error_converting(s)) {
2570                 PyErr_SetString(PyExc_TypeError,
2571                         "each subscript must be either an integer "
2572                         "or an ellipsis");
2573                 Py_DECREF(obj);
2574                 return -1;
2575             }
2576             npy_bool bad_input = 0;
2577 
2578             if (subindex + 1 >= subsize) {
2579                 PyErr_SetString(PyExc_ValueError,
2580                         "subscripts list is too long");
2581                 Py_DECREF(obj);
2582                 return -1;
2583             }
2584 
2585             if (s < 0) {
2586                 bad_input = 1;
2587             }
2588             else if (s < 26) {
2589                 subscripts[subindex++] = 'A' + (char)s;
2590             }
2591             else if (s < 2*26) {
2592                 subscripts[subindex++] = 'a' + (char)s - 26;
2593             }
2594             else {
2595                 bad_input = 1;
2596             }
2597 
2598             if (bad_input) {
2599                 PyErr_SetString(PyExc_ValueError,
2600                         "subscript is not within the valid range [0, 52)");
2601                 Py_DECREF(obj);
2602                 return -1;
2603             }
2604         }
2605 
2606     }
2607 
2608     Py_DECREF(obj);
2609 
2610     return subindex;
2611 }
2612 
2613 /*
2614  * Fills in the subscripts, with maximum size subsize, and op,
2615  * with the values in the tuple 'args'.
2616  *
2617  * Returns -1 on error, number of operands placed in op otherwise.
2618  */
2619 static int
einsum_sub_op_from_lists(PyObject * args,char * subscripts,int subsize,PyArrayObject ** op)2620 einsum_sub_op_from_lists(PyObject *args,
2621                 char *subscripts, int subsize, PyArrayObject **op)
2622 {
2623     int subindex = 0;
2624     npy_intp i, nop;
2625 
2626     nop = PyTuple_Size(args)/2;
2627 
2628     if (nop == 0) {
2629         PyErr_SetString(PyExc_ValueError, "must provide at least an "
2630                         "operand and a subscripts list to einsum");
2631         return -1;
2632     }
2633     else if (nop >= NPY_MAXARGS) {
2634         PyErr_SetString(PyExc_ValueError, "too many operands");
2635         return -1;
2636     }
2637 
2638     /* Set the operands to NULL */
2639     for (i = 0; i < nop; ++i) {
2640         op[i] = NULL;
2641     }
2642 
2643     /* Get the operands and build the subscript string */
2644     for (i = 0; i < nop; ++i) {
2645         PyObject *obj = PyTuple_GET_ITEM(args, 2*i);
2646         int n;
2647 
2648         /* Comma between the subscripts for each operand */
2649         if (i != 0) {
2650             subscripts[subindex++] = ',';
2651             if (subindex >= subsize) {
2652                 PyErr_SetString(PyExc_ValueError,
2653                         "subscripts list is too long");
2654                 goto fail;
2655             }
2656         }
2657 
2658         op[i] = (PyArrayObject *)PyArray_FROM_OF(obj, NPY_ARRAY_ENSUREARRAY);
2659         if (op[i] == NULL) {
2660             goto fail;
2661         }
2662 
2663         obj = PyTuple_GET_ITEM(args, 2*i+1);
2664         n = einsum_list_to_subscripts(obj, subscripts+subindex,
2665                                       subsize-subindex);
2666         if (n < 0) {
2667             goto fail;
2668         }
2669         subindex += n;
2670     }
2671 
2672     /* Add the '->' to the string if provided */
2673     if (PyTuple_Size(args) == 2*nop+1) {
2674         PyObject *obj;
2675         int n;
2676 
2677         if (subindex + 2 >= subsize) {
2678             PyErr_SetString(PyExc_ValueError,
2679                     "subscripts list is too long");
2680             goto fail;
2681         }
2682         subscripts[subindex++] = '-';
2683         subscripts[subindex++] = '>';
2684 
2685         obj = PyTuple_GET_ITEM(args, 2*nop);
2686         n = einsum_list_to_subscripts(obj, subscripts+subindex,
2687                                       subsize-subindex);
2688         if (n < 0) {
2689             goto fail;
2690         }
2691         subindex += n;
2692     }
2693 
2694     /* NULL-terminate the subscripts string */
2695     subscripts[subindex] = '\0';
2696 
2697     return nop;
2698 
2699 fail:
2700     for (i = 0; i < nop; ++i) {
2701         Py_XDECREF(op[i]);
2702         op[i] = NULL;
2703     }
2704 
2705     return -1;
2706 }
2707 
2708 static PyObject *
array_einsum(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2709 array_einsum(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2710 {
2711     char *subscripts = NULL, subscripts_buffer[256];
2712     PyObject *str_obj = NULL, *str_key_obj = NULL;
2713     PyObject *arg0;
2714     int i, nop;
2715     PyArrayObject *op[NPY_MAXARGS];
2716     NPY_ORDER order = NPY_KEEPORDER;
2717     NPY_CASTING casting = NPY_SAFE_CASTING;
2718     PyArrayObject *out = NULL;
2719     PyArray_Descr *dtype = NULL;
2720     PyObject *ret = NULL;
2721 
2722     if (PyTuple_GET_SIZE(args) < 1) {
2723         PyErr_SetString(PyExc_ValueError,
2724                         "must specify the einstein sum subscripts string "
2725                         "and at least one operand, or at least one operand "
2726                         "and its corresponding subscripts list");
2727         return NULL;
2728     }
2729     arg0 = PyTuple_GET_ITEM(args, 0);
2730 
2731     /* einsum('i,j', a, b), einsum('i,j->ij', a, b) */
2732     if (PyBytes_Check(arg0) || PyUnicode_Check(arg0)) {
2733         nop = einsum_sub_op_from_str(args, &str_obj, &subscripts, op);
2734     }
2735     /* einsum(a, [0], b, [1]), einsum(a, [0], b, [1], [0,1]) */
2736     else {
2737         nop = einsum_sub_op_from_lists(args, subscripts_buffer,
2738                                     sizeof(subscripts_buffer), op);
2739         subscripts = subscripts_buffer;
2740     }
2741     if (nop <= 0) {
2742         goto finish;
2743     }
2744 
2745     /* Get the keyword arguments */
2746     if (kwds != NULL) {
2747         PyObject *key, *value;
2748         Py_ssize_t pos = 0;
2749         while (PyDict_Next(kwds, &pos, &key, &value)) {
2750             char *str = NULL;
2751 
2752             Py_XDECREF(str_key_obj);
2753             str_key_obj = PyUnicode_AsASCIIString(key);
2754             if (str_key_obj != NULL) {
2755                 key = str_key_obj;
2756             }
2757 
2758             str = PyBytes_AsString(key);
2759 
2760             if (str == NULL) {
2761                 PyErr_Clear();
2762                 PyErr_SetString(PyExc_TypeError, "invalid keyword");
2763                 goto finish;
2764             }
2765 
2766             if (strcmp(str,"out") == 0) {
2767                 if (PyArray_Check(value)) {
2768                     out = (PyArrayObject *)value;
2769                 }
2770                 else {
2771                     PyErr_SetString(PyExc_TypeError,
2772                                 "keyword parameter out must be an "
2773                                 "array for einsum");
2774                     goto finish;
2775                 }
2776             }
2777             else if (strcmp(str,"order") == 0) {
2778                 if (!PyArray_OrderConverter(value, &order)) {
2779                     goto finish;
2780                 }
2781             }
2782             else if (strcmp(str,"casting") == 0) {
2783                 if (!PyArray_CastingConverter(value, &casting)) {
2784                     goto finish;
2785                 }
2786             }
2787             else if (strcmp(str,"dtype") == 0) {
2788                 if (!PyArray_DescrConverter2(value, &dtype)) {
2789                     goto finish;
2790                 }
2791             }
2792             else {
2793                 PyErr_Format(PyExc_TypeError,
2794                             "'%s' is an invalid keyword for einsum",
2795                             str);
2796                 goto finish;
2797             }
2798         }
2799     }
2800 
2801     ret = (PyObject *)PyArray_EinsteinSum(subscripts, nop, op, dtype,
2802                                         order, casting, out);
2803 
2804     /* If no output was supplied, possibly convert to a scalar */
2805     if (ret != NULL && out == NULL) {
2806         ret = PyArray_Return((PyArrayObject *)ret);
2807     }
2808 
2809 finish:
2810     for (i = 0; i < nop; ++i) {
2811         Py_XDECREF(op[i]);
2812     }
2813     Py_XDECREF(dtype);
2814     Py_XDECREF(str_obj);
2815     Py_XDECREF(str_key_obj);
2816     /* out is a borrowed reference */
2817 
2818     return ret;
2819 }
2820 
2821 static PyObject *
array_fastCopyAndTranspose(PyObject * NPY_UNUSED (dummy),PyObject * args)2822 array_fastCopyAndTranspose(PyObject *NPY_UNUSED(dummy), PyObject *args)
2823 {
2824     PyObject *a0;
2825 
2826     if (!PyArg_ParseTuple(args, "O:_fastCopyAndTranspose", &a0)) {
2827         return NULL;
2828     }
2829     return PyArray_Return((PyArrayObject *)PyArray_CopyAndTranspose(a0));
2830 }
2831 
2832 static PyObject *
array_correlate(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2833 array_correlate(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2834 {
2835     PyObject *shape, *a0;
2836     int mode = 0;
2837     static char *kwlist[] = {"a", "v", "mode", NULL};
2838 
2839     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i:correlate", kwlist,
2840                 &a0, &shape, &mode)) {
2841         return NULL;
2842     }
2843     return PyArray_Correlate(a0, shape, mode);
2844 }
2845 
2846 static PyObject*
array_correlate2(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2847 array_correlate2(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2848 {
2849     PyObject *shape, *a0;
2850     int mode = 0;
2851     static char *kwlist[] = {"a", "v", "mode", NULL};
2852 
2853     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i:correlate2", kwlist,
2854                 &a0, &shape, &mode)) {
2855         return NULL;
2856     }
2857     return PyArray_Correlate2(a0, shape, mode);
2858 }
2859 
2860 static PyObject *
array_arange(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kws)2861 array_arange(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) {
2862     PyObject *o_start = NULL, *o_stop = NULL, *o_step = NULL, *range=NULL;
2863     PyObject *like = NULL;
2864     PyObject *array_function_result = NULL;
2865     static char *kwd[] = {"start", "stop", "step", "dtype", "like", NULL};
2866     PyArray_Descr *typecode = NULL;
2867 
2868     if (!PyArg_ParseTupleAndKeywords(args, kws, "O|OOO&$O:arange", kwd,
2869                 &o_start,
2870                 &o_stop,
2871                 &o_step,
2872                 PyArray_DescrConverter2, &typecode,
2873                 &like)) {
2874         Py_XDECREF(typecode);
2875         return NULL;
2876     }
2877 
2878     array_function_result = array_implement_c_array_function_creation(
2879             "arange", args, kws);
2880     if (array_function_result != Py_NotImplemented) {
2881         Py_XDECREF(typecode);
2882         return array_function_result;
2883     }
2884 
2885     range = PyArray_ArangeObj(o_start, o_stop, o_step, typecode);
2886     Py_XDECREF(typecode);
2887 
2888     return range;
2889 }
2890 
2891 /*NUMPY_API
2892  *
2893  * Included at the very first so not auto-grabbed and thus not labeled.
2894  */
2895 NPY_NO_EXPORT unsigned int
PyArray_GetNDArrayCVersion(void)2896 PyArray_GetNDArrayCVersion(void)
2897 {
2898     return (unsigned int)NPY_ABI_VERSION;
2899 }
2900 
2901 /*NUMPY_API
2902  * Returns the built-in (at compilation time) C API version
2903  */
2904 NPY_NO_EXPORT unsigned int
PyArray_GetNDArrayCFeatureVersion(void)2905 PyArray_GetNDArrayCFeatureVersion(void)
2906 {
2907     return (unsigned int)NPY_API_VERSION;
2908 }
2909 
2910 static PyObject *
array__get_ndarray_c_version(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)2911 array__get_ndarray_c_version(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2912 {
2913     static char *kwlist[] = {NULL};
2914 
2915     if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist )) {
2916         return NULL;
2917     }
2918     return PyLong_FromLong( (long) PyArray_GetNDArrayCVersion() );
2919 }
2920 
2921 /*NUMPY_API
2922 */
2923 NPY_NO_EXPORT int
PyArray_GetEndianness(void)2924 PyArray_GetEndianness(void)
2925 {
2926     const union {
2927         npy_uint32 i;
2928         char c[4];
2929     } bint = {0x01020304};
2930 
2931     if (bint.c[0] == 1) {
2932         return NPY_CPU_BIG;
2933     }
2934     else if (bint.c[0] == 4) {
2935         return NPY_CPU_LITTLE;
2936     }
2937     else {
2938         return NPY_CPU_UNKNOWN_ENDIAN;
2939     }
2940 }
2941 
2942 static PyObject *
array__reconstruct(PyObject * NPY_UNUSED (dummy),PyObject * args)2943 array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args)
2944 {
2945 
2946     PyObject *ret;
2947     PyTypeObject *subtype;
2948     PyArray_Dims shape = {NULL, 0};
2949     PyArray_Descr *dtype = NULL;
2950 
2951     evil_global_disable_warn_O4O8_flag = 1;
2952 
2953     if (!PyArg_ParseTuple(args, "O!O&O&:_reconstruct",
2954                 &PyType_Type, &subtype,
2955                 PyArray_IntpConverter, &shape,
2956                 PyArray_DescrConverter, &dtype)) {
2957         goto fail;
2958     }
2959     if (!PyType_IsSubtype(subtype, &PyArray_Type)) {
2960         PyErr_SetString(PyExc_TypeError,
2961                 "_reconstruct: First argument must be a sub-type of ndarray");
2962         goto fail;
2963     }
2964     ret = PyArray_NewFromDescr(subtype, dtype,
2965             (int)shape.len, shape.ptr, NULL, NULL, 0, NULL);
2966     npy_free_cache_dim_obj(shape);
2967 
2968     evil_global_disable_warn_O4O8_flag = 0;
2969 
2970     return ret;
2971 
2972 fail:
2973     evil_global_disable_warn_O4O8_flag = 0;
2974 
2975     Py_XDECREF(dtype);
2976     npy_free_cache_dim_obj(shape);
2977     return NULL;
2978 }
2979 
2980 static PyObject *
array_set_string_function(PyObject * NPY_UNUSED (self),PyObject * args,PyObject * kwds)2981 array_set_string_function(PyObject *NPY_UNUSED(self), PyObject *args,
2982         PyObject *kwds)
2983 {
2984     PyObject *op = NULL;
2985     int repr = 1;
2986     static char *kwlist[] = {"f", "repr", NULL};
2987 
2988     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:set_string_function", kwlist, &op, &repr)) {
2989         return NULL;
2990     }
2991     /* reset the array_repr function to built-in */
2992     if (op == Py_None) {
2993         op = NULL;
2994     }
2995     if (op != NULL && !PyCallable_Check(op)) {
2996         PyErr_SetString(PyExc_TypeError,
2997                 "Argument must be callable.");
2998         return NULL;
2999     }
3000     PyArray_SetStringFunction(op, repr);
3001     Py_RETURN_NONE;
3002 }
3003 
3004 static PyObject *
array_set_ops_function(PyObject * NPY_UNUSED (self),PyObject * NPY_UNUSED (args),PyObject * kwds)3005 array_set_ops_function(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args),
3006         PyObject *kwds)
3007 {
3008     PyObject *oldops = NULL;
3009 
3010     if ((oldops = _PyArray_GetNumericOps()) == NULL) {
3011         return NULL;
3012     }
3013     /*
3014      * Should probably ensure that objects are at least callable
3015      *  Leave this to the caller for now --- error will be raised
3016      *  later when use is attempted
3017      */
3018     if (kwds && PyArray_SetNumericOps(kwds) == -1) {
3019         Py_DECREF(oldops);
3020         if (PyErr_Occurred() == NULL) {
3021             PyErr_SetString(PyExc_ValueError,
3022                 "one or more objects not callable");
3023         }
3024         return NULL;
3025     }
3026     return oldops;
3027 }
3028 
3029 static PyObject *
array_set_datetimeparse_function(PyObject * NPY_UNUSED (self),PyObject * NPY_UNUSED (args),PyObject * NPY_UNUSED (kwds))3030 array_set_datetimeparse_function(PyObject *NPY_UNUSED(self),
3031         PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds))
3032 {
3033     PyErr_SetString(PyExc_RuntimeError, "This function has been removed");
3034     return NULL;
3035 }
3036 
3037 /*
3038  * inner loop with constant size memcpy arguments
3039  * this allows the compiler to replace function calls while still handling the
3040  * alignment requirements of the platform.
3041  */
3042 #define INNER_WHERE_LOOP(size) \
3043     do { \
3044         npy_intp i; \
3045         for (i = 0; i < n; i++) { \
3046             if (*csrc) { \
3047                 memcpy(dst, xsrc, size); \
3048             } \
3049             else { \
3050                 memcpy(dst, ysrc, size); \
3051             } \
3052             dst += size; \
3053             xsrc += xstride; \
3054             ysrc += ystride; \
3055             csrc += cstride; \
3056         } \
3057     } while(0)
3058 
3059 
3060 /*NUMPY_API
3061  * Where
3062  */
3063 NPY_NO_EXPORT PyObject *
PyArray_Where(PyObject * condition,PyObject * x,PyObject * y)3064 PyArray_Where(PyObject *condition, PyObject *x, PyObject *y)
3065 {
3066     PyArrayObject *arr, *ax, *ay;
3067     PyObject *ret = NULL;
3068 
3069     arr = (PyArrayObject *)PyArray_FROM_O(condition);
3070     if (arr == NULL) {
3071         return NULL;
3072     }
3073     if ((x == NULL) && (y == NULL)) {
3074         ret = PyArray_Nonzero(arr);
3075         Py_DECREF(arr);
3076         return ret;
3077     }
3078     if ((x == NULL) || (y == NULL)) {
3079         Py_DECREF(arr);
3080         PyErr_SetString(PyExc_ValueError,
3081                 "either both or neither of x and y should be given");
3082         return NULL;
3083     }
3084 
3085     ax = (PyArrayObject*)PyArray_FROM_O(x);
3086     ay = (PyArrayObject*)PyArray_FROM_O(y);
3087     if (ax == NULL || ay == NULL) {
3088         goto fail;
3089     }
3090     else {
3091         npy_uint32 flags = NPY_ITER_EXTERNAL_LOOP | NPY_ITER_BUFFERED |
3092                            NPY_ITER_REFS_OK | NPY_ITER_ZEROSIZE_OK;
3093         PyArrayObject * op_in[4] = {
3094             NULL, arr, ax, ay
3095         };
3096         npy_uint32 op_flags[4] = {
3097             NPY_ITER_WRITEONLY | NPY_ITER_ALLOCATE | NPY_ITER_NO_SUBTYPE,
3098             NPY_ITER_READONLY, NPY_ITER_READONLY, NPY_ITER_READONLY
3099         };
3100         PyArray_Descr * common_dt = PyArray_ResultType(2, &op_in[0] + 2,
3101                                                        0, NULL);
3102         PyArray_Descr * op_dt[4] = {common_dt, PyArray_DescrFromType(NPY_BOOL),
3103                                     common_dt, common_dt};
3104         NpyIter * iter;
3105         int needs_api;
3106         NPY_BEGIN_THREADS_DEF;
3107 
3108         if (common_dt == NULL || op_dt[1] == NULL) {
3109             Py_XDECREF(op_dt[1]);
3110             Py_XDECREF(common_dt);
3111             goto fail;
3112         }
3113         iter =  NpyIter_MultiNew(4, op_in, flags,
3114                                  NPY_KEEPORDER, NPY_UNSAFE_CASTING,
3115                                  op_flags, op_dt);
3116         Py_DECREF(op_dt[1]);
3117         Py_DECREF(common_dt);
3118         if (iter == NULL) {
3119             goto fail;
3120         }
3121 
3122         needs_api = NpyIter_IterationNeedsAPI(iter);
3123 
3124         /* Get the result from the iterator object array */
3125         ret = (PyObject*)NpyIter_GetOperandArray(iter)[0];
3126 
3127         NPY_BEGIN_THREADS_NDITER(iter);
3128 
3129         if (NpyIter_GetIterSize(iter) != 0) {
3130             NpyIter_IterNextFunc *iternext = NpyIter_GetIterNext(iter, NULL);
3131             npy_intp * innersizeptr = NpyIter_GetInnerLoopSizePtr(iter);
3132             char **dataptrarray = NpyIter_GetDataPtrArray(iter);
3133 
3134             do {
3135                 PyArray_Descr * dtx = NpyIter_GetDescrArray(iter)[2];
3136                 PyArray_Descr * dty = NpyIter_GetDescrArray(iter)[3];
3137                 int axswap = PyDataType_ISBYTESWAPPED(dtx);
3138                 int ayswap = PyDataType_ISBYTESWAPPED(dty);
3139                 PyArray_CopySwapFunc *copyswapx = dtx->f->copyswap;
3140                 PyArray_CopySwapFunc *copyswapy = dty->f->copyswap;
3141                 int native = (axswap == ayswap) && (axswap == 0) && !needs_api;
3142                 npy_intp n = (*innersizeptr);
3143                 npy_intp itemsize = NpyIter_GetDescrArray(iter)[0]->elsize;
3144                 npy_intp cstride = NpyIter_GetInnerStrideArray(iter)[1];
3145                 npy_intp xstride = NpyIter_GetInnerStrideArray(iter)[2];
3146                 npy_intp ystride = NpyIter_GetInnerStrideArray(iter)[3];
3147                 char * dst = dataptrarray[0];
3148                 char * csrc = dataptrarray[1];
3149                 char * xsrc = dataptrarray[2];
3150                 char * ysrc = dataptrarray[3];
3151 
3152                 /* constant sizes so compiler replaces memcpy */
3153                 if (native && itemsize == 16) {
3154                     INNER_WHERE_LOOP(16);
3155                 }
3156                 else if (native && itemsize == 8) {
3157                     INNER_WHERE_LOOP(8);
3158                 }
3159                 else if (native && itemsize == 4) {
3160                     INNER_WHERE_LOOP(4);
3161                 }
3162                 else if (native && itemsize == 2) {
3163                     INNER_WHERE_LOOP(2);
3164                 }
3165                 else if (native && itemsize == 1) {
3166                     INNER_WHERE_LOOP(1);
3167                 }
3168                 else {
3169                     /* copyswap is faster than memcpy even if we are native */
3170                     npy_intp i;
3171                     for (i = 0; i < n; i++) {
3172                         if (*csrc) {
3173                             copyswapx(dst, xsrc, axswap, ret);
3174                         }
3175                         else {
3176                             copyswapy(dst, ysrc, ayswap, ret);
3177                         }
3178                         dst += itemsize;
3179                         xsrc += xstride;
3180                         ysrc += ystride;
3181                         csrc += cstride;
3182                     }
3183                 }
3184             } while (iternext(iter));
3185         }
3186 
3187         NPY_END_THREADS;
3188 
3189         Py_INCREF(ret);
3190         Py_DECREF(arr);
3191         Py_DECREF(ax);
3192         Py_DECREF(ay);
3193 
3194         if (NpyIter_Deallocate(iter) != NPY_SUCCEED) {
3195             Py_DECREF(ret);
3196             return NULL;
3197         }
3198 
3199         return ret;
3200     }
3201 
3202 fail:
3203     Py_DECREF(arr);
3204     Py_XDECREF(ax);
3205     Py_XDECREF(ay);
3206     return NULL;
3207 }
3208 
3209 #undef INNER_WHERE_LOOP
3210 
3211 static PyObject *
array_where(PyObject * NPY_UNUSED (ignored),PyObject * args)3212 array_where(PyObject *NPY_UNUSED(ignored), PyObject *args)
3213 {
3214     PyObject *obj = NULL, *x = NULL, *y = NULL;
3215 
3216     if (!PyArg_ParseTuple(args, "O|OO:where", &obj, &x, &y)) {
3217         return NULL;
3218     }
3219     return PyArray_Where(obj, x, y);
3220 }
3221 
3222 static PyObject *
array_lexsort(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)3223 array_lexsort(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
3224 {
3225     int axis = -1;
3226     PyObject *obj;
3227     static char *kwlist[] = {"keys", "axis", NULL};
3228 
3229     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:lexsort", kwlist, &obj, &axis)) {
3230         return NULL;
3231     }
3232     return PyArray_Return((PyArrayObject *)PyArray_LexSort(obj, axis));
3233 }
3234 
3235 static PyObject *
array_can_cast_safely(PyObject * NPY_UNUSED (self),PyObject * args,PyObject * kwds)3236 array_can_cast_safely(PyObject *NPY_UNUSED(self), PyObject *args,
3237         PyObject *kwds)
3238 {
3239     PyObject *from_obj = NULL;
3240     PyArray_Descr *d1 = NULL;
3241     PyArray_Descr *d2 = NULL;
3242     npy_bool ret;
3243     PyObject *retobj = NULL;
3244     NPY_CASTING casting = NPY_SAFE_CASTING;
3245     static char *kwlist[] = {"from_", "to", "casting", NULL};
3246 
3247     if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO&|O&:can_cast", kwlist,
3248                 &from_obj,
3249                 PyArray_DescrConverter2, &d2,
3250                 PyArray_CastingConverter, &casting)) {
3251         goto finish;
3252     }
3253     if (d2 == NULL) {
3254         PyErr_SetString(PyExc_TypeError,
3255                 "did not understand one of the types; 'None' not accepted");
3256         goto finish;
3257     }
3258 
3259     /* If the first parameter is an object or scalar, use CanCastArrayTo */
3260     if (PyArray_Check(from_obj)) {
3261         ret = PyArray_CanCastArrayTo((PyArrayObject *)from_obj, d2, casting);
3262     }
3263     else if (PyArray_IsScalar(from_obj, Generic) ||
3264                                 PyArray_IsPythonNumber(from_obj)) {
3265         PyArrayObject *arr;
3266         arr = (PyArrayObject *)PyArray_FROM_O(from_obj);
3267         if (arr == NULL) {
3268             goto finish;
3269         }
3270         ret = PyArray_CanCastArrayTo(arr, d2, casting);
3271         Py_DECREF(arr);
3272     }
3273     /* Otherwise use CanCastTypeTo */
3274     else {
3275         if (!PyArray_DescrConverter2(from_obj, &d1) || d1 == NULL) {
3276             PyErr_SetString(PyExc_TypeError,
3277                     "did not understand one of the types; 'None' not accepted");
3278             goto finish;
3279         }
3280         ret = PyArray_CanCastTypeTo(d1, d2, casting);
3281     }
3282 
3283     retobj = ret ? Py_True : Py_False;
3284     Py_INCREF(retobj);
3285 
3286  finish:
3287     Py_XDECREF(d1);
3288     Py_XDECREF(d2);
3289     return retobj;
3290 }
3291 
3292 static PyObject *
array_promote_types(PyObject * NPY_UNUSED (dummy),PyObject * args)3293 array_promote_types(PyObject *NPY_UNUSED(dummy), PyObject *args)
3294 {
3295     PyArray_Descr *d1 = NULL;
3296     PyArray_Descr *d2 = NULL;
3297     PyObject *ret = NULL;
3298     if (!PyArg_ParseTuple(args, "O&O&:promote_types",
3299                 PyArray_DescrConverter2, &d1, PyArray_DescrConverter2, &d2)) {
3300         goto finish;
3301     }
3302 
3303     if (d1 == NULL || d2 == NULL) {
3304         PyErr_SetString(PyExc_TypeError,
3305                 "did not understand one of the types");
3306         goto finish;
3307     }
3308 
3309     ret = (PyObject *)PyArray_PromoteTypes(d1, d2);
3310 
3311  finish:
3312     Py_XDECREF(d1);
3313     Py_XDECREF(d2);
3314     return ret;
3315 }
3316 
3317 static PyObject *
array_min_scalar_type(PyObject * NPY_UNUSED (dummy),PyObject * args)3318 array_min_scalar_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
3319 {
3320     PyObject *array_in = NULL;
3321     PyArrayObject *array;
3322     PyObject *ret = NULL;
3323 
3324     if (!PyArg_ParseTuple(args, "O:min_scalar_type", &array_in)) {
3325         return NULL;
3326     }
3327 
3328     array = (PyArrayObject *)PyArray_FROM_O(array_in);
3329     if (array == NULL) {
3330         return NULL;
3331     }
3332 
3333     ret = (PyObject *)PyArray_MinScalarType(array);
3334     Py_DECREF(array);
3335     return ret;
3336 }
3337 
3338 static PyObject *
array_result_type(PyObject * NPY_UNUSED (dummy),PyObject * args)3339 array_result_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
3340 {
3341     npy_intp i, len, narr = 0, ndtypes = 0;
3342     PyArrayObject **arr = NULL;
3343     PyArray_Descr **dtypes = NULL;
3344     PyObject *ret = NULL;
3345 
3346     len = PyTuple_GET_SIZE(args);
3347     if (len == 0) {
3348         PyErr_SetString(PyExc_ValueError,
3349                         "at least one array or dtype is required");
3350         goto finish;
3351     }
3352 
3353     arr = PyArray_malloc(2 * len * sizeof(void *));
3354     if (arr == NULL) {
3355         return PyErr_NoMemory();
3356     }
3357     dtypes = (PyArray_Descr**)&arr[len];
3358 
3359     for (i = 0; i < len; ++i) {
3360         PyObject *obj = PyTuple_GET_ITEM(args, i);
3361         if (PyArray_Check(obj)) {
3362             Py_INCREF(obj);
3363             arr[narr] = (PyArrayObject *)obj;
3364             ++narr;
3365         }
3366         else if (PyArray_IsScalar(obj, Generic) ||
3367                                     PyArray_IsPythonNumber(obj)) {
3368             arr[narr] = (PyArrayObject *)PyArray_FROM_O(obj);
3369             if (arr[narr] == NULL) {
3370                 goto finish;
3371             }
3372             ++narr;
3373         }
3374         else {
3375             if (!PyArray_DescrConverter(obj, &dtypes[ndtypes])) {
3376                 goto finish;
3377             }
3378             ++ndtypes;
3379         }
3380     }
3381 
3382     ret = (PyObject *)PyArray_ResultType(narr, arr, ndtypes, dtypes);
3383 
3384 finish:
3385     for (i = 0; i < narr; ++i) {
3386         Py_DECREF(arr[i]);
3387     }
3388     for (i = 0; i < ndtypes; ++i) {
3389         Py_DECREF(dtypes[i]);
3390     }
3391     PyArray_free(arr);
3392     return ret;
3393 }
3394 
3395 static PyObject *
array_datetime_data(PyObject * NPY_UNUSED (dummy),PyObject * args)3396 array_datetime_data(PyObject *NPY_UNUSED(dummy), PyObject *args)
3397 {
3398     PyArray_Descr *dtype;
3399     PyArray_DatetimeMetaData *meta;
3400 
3401     if (!PyArg_ParseTuple(args, "O&:datetime_data",
3402                 PyArray_DescrConverter, &dtype)) {
3403         return NULL;
3404     }
3405 
3406     meta = get_datetime_metadata_from_dtype(dtype);
3407     if (meta == NULL) {
3408         Py_DECREF(dtype);
3409         return NULL;
3410     }
3411 
3412     PyObject *res = convert_datetime_metadata_to_tuple(meta);
3413     Py_DECREF(dtype);
3414     return res;
3415 }
3416 
3417 /*
3418  * Prints floating-point scalars using the Dragon4 algorithm, scientific mode.
3419  * See docstring of `np.format_float_scientific` for description of arguments.
3420  * The differences is that a value of -1 is valid for pad_left, exp_digits,
3421  * precision, which is equivalent to `None`.
3422  */
3423 static PyObject *
dragon4_scientific(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)3424 dragon4_scientific(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
3425 {
3426     PyObject *obj;
3427     static char *kwlist[] = {"x", "precision", "unique", "sign", "trim",
3428                              "pad_left", "exp_digits", NULL};
3429     int precision=-1, pad_left=-1, exp_digits=-1;
3430     char *trimstr=NULL;
3431     DigitMode digit_mode;
3432     TrimMode trim = TrimMode_None;
3433     int sign=0, unique=1;
3434 
3435     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iiisii:dragon4_scientific",
3436                 kwlist, &obj, &precision, &unique, &sign, &trimstr, &pad_left,
3437                 &exp_digits)) {
3438         return NULL;
3439     }
3440 
3441     if (trimstr != NULL) {
3442         if (strcmp(trimstr, "k") == 0) {
3443             trim = TrimMode_None;
3444         }
3445         else if (strcmp(trimstr, ".") == 0) {
3446             trim = TrimMode_Zeros;
3447         }
3448         else if (strcmp(trimstr, "0") == 0) {
3449             trim = TrimMode_LeaveOneZero;
3450         }
3451         else if (strcmp(trimstr, "-") == 0) {
3452             trim = TrimMode_DptZeros;
3453         }
3454         else {
3455             PyErr_SetString(PyExc_TypeError,
3456                 "if supplied, trim must be 'k', '.', '0' or '-'");
3457             return NULL;
3458         }
3459     }
3460 
3461     digit_mode = unique ? DigitMode_Unique : DigitMode_Exact;
3462 
3463     if (unique == 0 && precision < 0) {
3464         PyErr_SetString(PyExc_TypeError,
3465             "in non-unique mode `precision` must be supplied");
3466         return NULL;
3467     }
3468 
3469     return Dragon4_Scientific(obj, digit_mode, precision, sign, trim,
3470                               pad_left, exp_digits);
3471 }
3472 
3473 /*
3474  * Prints floating-point scalars using the Dragon4 algorithm, positional mode.
3475  * See docstring of `np.format_float_positional` for description of arguments.
3476  * The differences is that a value of -1 is valid for pad_left, pad_right,
3477  * precision, which is equivalent to `None`.
3478  */
3479 static PyObject *
dragon4_positional(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)3480 dragon4_positional(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
3481 {
3482     PyObject *obj;
3483     static char *kwlist[] = {"x", "precision", "unique", "fractional",
3484                              "sign", "trim", "pad_left", "pad_right", NULL};
3485     int precision=-1, pad_left=-1, pad_right=-1;
3486     char *trimstr=NULL;
3487     CutoffMode cutoff_mode;
3488     DigitMode digit_mode;
3489     TrimMode trim = TrimMode_None;
3490     int sign=0, unique=1, fractional=0;
3491 
3492     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iiiisii:dragon4_positional",
3493                 kwlist, &obj, &precision, &unique, &fractional, &sign, &trimstr,
3494                 &pad_left, &pad_right)) {
3495         return NULL;
3496     }
3497 
3498     if (trimstr != NULL) {
3499         if (strcmp(trimstr, "k") == 0) {
3500             trim = TrimMode_None;
3501         }
3502         else if (strcmp(trimstr, ".") == 0) {
3503             trim = TrimMode_Zeros;
3504         }
3505         else if (strcmp(trimstr, "0") == 0) {
3506             trim = TrimMode_LeaveOneZero;
3507         }
3508         else if (strcmp(trimstr, "-") == 0) {
3509             trim = TrimMode_DptZeros;
3510         }
3511         else {
3512             PyErr_SetString(PyExc_TypeError,
3513                 "if supplied, trim must be 'k', '.', '0' or '-'");
3514             return NULL;
3515         }
3516     }
3517 
3518     digit_mode = unique ? DigitMode_Unique : DigitMode_Exact;
3519     cutoff_mode = fractional ? CutoffMode_FractionLength :
3520                                CutoffMode_TotalLength;
3521 
3522     if (unique == 0 && precision < 0) {
3523         PyErr_SetString(PyExc_TypeError,
3524             "in non-unique mode `precision` must be supplied");
3525         return NULL;
3526     }
3527 
3528     return Dragon4_Positional(obj, digit_mode, cutoff_mode, precision, sign,
3529                               trim, pad_left, pad_right);
3530 }
3531 
3532 static PyObject *
format_longfloat(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)3533 format_longfloat(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
3534 {
3535     PyObject *obj;
3536     unsigned int precision;
3537     static char *kwlist[] = {"x", "precision", NULL};
3538 
3539     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OI:format_longfloat", kwlist,
3540                 &obj, &precision)) {
3541         return NULL;
3542     }
3543     if (!PyArray_IsScalar(obj, LongDouble)) {
3544         PyErr_SetString(PyExc_TypeError,
3545                 "not a longfloat");
3546         return NULL;
3547     }
3548     return Dragon4_Scientific(obj, DigitMode_Unique, precision, 0,
3549                               TrimMode_LeaveOneZero, -1, -1);
3550 }
3551 
3552 static PyObject *
compare_chararrays(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * kwds)3553 compare_chararrays(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
3554 {
3555     PyObject *array;
3556     PyObject *other;
3557     PyArrayObject *newarr, *newoth;
3558     int cmp_op;
3559     npy_bool rstrip;
3560     char *cmp_str;
3561     Py_ssize_t strlength;
3562     PyObject *res = NULL;
3563     static char msg[] = "comparison must be '==', '!=', '<', '>', '<=', '>='";
3564     static char *kwlist[] = {"a1", "a2", "cmp", "rstrip", NULL};
3565 
3566     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOs#O&:compare_chararrays",
3567                 kwlist,
3568                 &array, &other, &cmp_str, &strlength,
3569                 PyArray_BoolConverter, &rstrip)) {
3570         return NULL;
3571     }
3572     if (strlength < 1 || strlength > 2) {
3573         goto err;
3574     }
3575     if (strlength > 1) {
3576         if (cmp_str[1] != '=') {
3577             goto err;
3578         }
3579         if (cmp_str[0] == '=') {
3580             cmp_op = Py_EQ;
3581         }
3582         else if (cmp_str[0] == '!') {
3583             cmp_op = Py_NE;
3584         }
3585         else if (cmp_str[0] == '<') {
3586             cmp_op = Py_LE;
3587         }
3588         else if (cmp_str[0] == '>') {
3589             cmp_op = Py_GE;
3590         }
3591         else {
3592             goto err;
3593         }
3594     }
3595     else {
3596         if (cmp_str[0] == '<') {
3597             cmp_op = Py_LT;
3598         }
3599         else if (cmp_str[0] == '>') {
3600             cmp_op = Py_GT;
3601         }
3602         else {
3603             goto err;
3604         }
3605     }
3606 
3607     newarr = (PyArrayObject *)PyArray_FROM_O(array);
3608     if (newarr == NULL) {
3609         return NULL;
3610     }
3611     newoth = (PyArrayObject *)PyArray_FROM_O(other);
3612     if (newoth == NULL) {
3613         Py_DECREF(newarr);
3614         return NULL;
3615     }
3616     if (PyArray_ISSTRING(newarr) && PyArray_ISSTRING(newoth)) {
3617         res = _strings_richcompare(newarr, newoth, cmp_op, rstrip != 0);
3618     }
3619     else {
3620         PyErr_SetString(PyExc_TypeError,
3621                 "comparison of non-string arrays");
3622     }
3623     Py_DECREF(newarr);
3624     Py_DECREF(newoth);
3625     return res;
3626 
3627  err:
3628     PyErr_SetString(PyExc_ValueError, msg);
3629     return NULL;
3630 }
3631 
3632 static PyObject *
_vec_string_with_args(PyArrayObject * char_array,PyArray_Descr * type,PyObject * method,PyObject * args)3633 _vec_string_with_args(PyArrayObject* char_array, PyArray_Descr* type,
3634                       PyObject* method, PyObject* args)
3635 {
3636     PyObject* broadcast_args[NPY_MAXARGS];
3637     PyArrayMultiIterObject* in_iter = NULL;
3638     PyArrayObject* result = NULL;
3639     PyArrayIterObject* out_iter = NULL;
3640     Py_ssize_t i, n, nargs;
3641 
3642     nargs = PySequence_Size(args) + 1;
3643     if (nargs == -1 || nargs > NPY_MAXARGS) {
3644         PyErr_Format(PyExc_ValueError,
3645                 "len(args) must be < %d", NPY_MAXARGS - 1);
3646         Py_DECREF(type);
3647         goto err;
3648     }
3649 
3650     broadcast_args[0] = (PyObject*)char_array;
3651     for (i = 1; i < nargs; i++) {
3652         PyObject* item = PySequence_GetItem(args, i-1);
3653         if (item == NULL) {
3654             Py_DECREF(type);
3655             goto err;
3656         }
3657         broadcast_args[i] = item;
3658         Py_DECREF(item);
3659     }
3660     in_iter = (PyArrayMultiIterObject*)PyArray_MultiIterFromObjects
3661         (broadcast_args, nargs, 0);
3662     if (in_iter == NULL) {
3663         Py_DECREF(type);
3664         goto err;
3665     }
3666     n = in_iter->numiter;
3667 
3668     result = (PyArrayObject*)PyArray_SimpleNewFromDescr(in_iter->nd,
3669             in_iter->dimensions, type);
3670     if (result == NULL) {
3671         goto err;
3672     }
3673 
3674     out_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)result);
3675     if (out_iter == NULL) {
3676         goto err;
3677     }
3678 
3679     while (PyArray_MultiIter_NOTDONE(in_iter)) {
3680         PyObject* item_result;
3681         PyObject* args_tuple = PyTuple_New(n);
3682         if (args_tuple == NULL) {
3683             goto err;
3684         }
3685 
3686         for (i = 0; i < n; i++) {
3687             PyArrayIterObject* it = in_iter->iters[i];
3688             PyObject* arg = PyArray_ToScalar(PyArray_ITER_DATA(it), it->ao);
3689             if (arg == NULL) {
3690                 Py_DECREF(args_tuple);
3691                 goto err;
3692             }
3693             /* Steals ref to arg */
3694             PyTuple_SetItem(args_tuple, i, arg);
3695         }
3696 
3697         item_result = PyObject_CallObject(method, args_tuple);
3698         Py_DECREF(args_tuple);
3699         if (item_result == NULL) {
3700             goto err;
3701         }
3702 
3703         if (PyArray_SETITEM(result, PyArray_ITER_DATA(out_iter), item_result)) {
3704             Py_DECREF(item_result);
3705             PyErr_SetString( PyExc_TypeError,
3706                     "result array type does not match underlying function");
3707             goto err;
3708         }
3709         Py_DECREF(item_result);
3710 
3711         PyArray_MultiIter_NEXT(in_iter);
3712         PyArray_ITER_NEXT(out_iter);
3713     }
3714 
3715     Py_DECREF(in_iter);
3716     Py_DECREF(out_iter);
3717 
3718     return (PyObject*)result;
3719 
3720  err:
3721     Py_XDECREF(in_iter);
3722     Py_XDECREF(out_iter);
3723     Py_XDECREF(result);
3724 
3725     return 0;
3726 }
3727 
3728 static PyObject *
_vec_string_no_args(PyArrayObject * char_array,PyArray_Descr * type,PyObject * method)3729 _vec_string_no_args(PyArrayObject* char_array,
3730                                    PyArray_Descr* type, PyObject* method)
3731 {
3732     /*
3733      * This is a faster version of _vec_string_args to use when there
3734      * are no additional arguments to the string method.  This doesn't
3735      * require a broadcast iterator (and broadcast iterators don't work
3736      * with 1 argument anyway).
3737      */
3738     PyArrayIterObject* in_iter = NULL;
3739     PyArrayObject* result = NULL;
3740     PyArrayIterObject* out_iter = NULL;
3741 
3742     in_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)char_array);
3743     if (in_iter == NULL) {
3744         Py_DECREF(type);
3745         goto err;
3746     }
3747 
3748     result = (PyArrayObject*)PyArray_SimpleNewFromDescr(
3749             PyArray_NDIM(char_array), PyArray_DIMS(char_array), type);
3750     if (result == NULL) {
3751         goto err;
3752     }
3753 
3754     out_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)result);
3755     if (out_iter == NULL) {
3756         goto err;
3757     }
3758 
3759     while (PyArray_ITER_NOTDONE(in_iter)) {
3760         PyObject* item_result;
3761         PyObject* item = PyArray_ToScalar(in_iter->dataptr, in_iter->ao);
3762         if (item == NULL) {
3763             goto err;
3764         }
3765 
3766         item_result = PyObject_CallFunctionObjArgs(method, item, NULL);
3767         Py_DECREF(item);
3768         if (item_result == NULL) {
3769             goto err;
3770         }
3771 
3772         if (PyArray_SETITEM(result, PyArray_ITER_DATA(out_iter), item_result)) {
3773             Py_DECREF(item_result);
3774             PyErr_SetString( PyExc_TypeError,
3775                 "result array type does not match underlying function");
3776             goto err;
3777         }
3778         Py_DECREF(item_result);
3779 
3780         PyArray_ITER_NEXT(in_iter);
3781         PyArray_ITER_NEXT(out_iter);
3782     }
3783 
3784     Py_DECREF(in_iter);
3785     Py_DECREF(out_iter);
3786 
3787     return (PyObject*)result;
3788 
3789  err:
3790     Py_XDECREF(in_iter);
3791     Py_XDECREF(out_iter);
3792     Py_XDECREF(result);
3793 
3794     return 0;
3795 }
3796 
3797 static PyObject *
_vec_string(PyObject * NPY_UNUSED (dummy),PyObject * args,PyObject * NPY_UNUSED (kwds))3798 _vec_string(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUSED(kwds))
3799 {
3800     PyArrayObject* char_array = NULL;
3801     PyArray_Descr *type;
3802     PyObject* method_name;
3803     PyObject* args_seq = NULL;
3804 
3805     PyObject* method = NULL;
3806     PyObject* result = NULL;
3807 
3808     if (!PyArg_ParseTuple(args, "O&O&O|O",
3809                 PyArray_Converter, &char_array,
3810                 PyArray_DescrConverter, &type,
3811                 &method_name, &args_seq)) {
3812         goto err;
3813     }
3814 
3815     if (PyArray_TYPE(char_array) == NPY_STRING) {
3816         method = PyObject_GetAttr((PyObject *)&PyBytes_Type, method_name);
3817     }
3818     else if (PyArray_TYPE(char_array) == NPY_UNICODE) {
3819         method = PyObject_GetAttr((PyObject *)&PyUnicode_Type, method_name);
3820     }
3821     else {
3822         PyErr_SetString(PyExc_TypeError,
3823                 "string operation on non-string array");
3824         Py_DECREF(type);
3825         goto err;
3826     }
3827     if (method == NULL) {
3828         Py_DECREF(type);
3829         goto err;
3830     }
3831 
3832     if (args_seq == NULL
3833             || (PySequence_Check(args_seq) && PySequence_Size(args_seq) == 0)) {
3834         result = _vec_string_no_args(char_array, type, method);
3835     }
3836     else if (PySequence_Check(args_seq)) {
3837         result = _vec_string_with_args(char_array, type, method, args_seq);
3838     }
3839     else {
3840         Py_DECREF(type);
3841         PyErr_SetString(PyExc_TypeError,
3842                 "'args' must be a sequence of arguments");
3843         goto err;
3844     }
3845     if (result == NULL) {
3846         goto err;
3847     }
3848 
3849     Py_DECREF(char_array);
3850     Py_DECREF(method);
3851 
3852     return (PyObject*)result;
3853 
3854  err:
3855     Py_XDECREF(char_array);
3856     Py_XDECREF(method);
3857 
3858     return 0;
3859 }
3860 
3861 #ifndef __NPY_PRIVATE_NO_SIGNAL
3862 
3863 static NPY_TLS int sigint_buf_init = 0;
3864 static NPY_TLS NPY_SIGJMP_BUF _NPY_SIGINT_BUF;
3865 
3866 /*NUMPY_API
3867  */
3868 NPY_NO_EXPORT void
_PyArray_SigintHandler(int signum)3869 _PyArray_SigintHandler(int signum)
3870 {
3871     PyOS_setsig(signum, SIG_IGN);
3872     /*
3873      * jump buffer may be uninitialized as SIGINT allowing functions are usually
3874      * run in other threads than the master thread that receives the signal
3875      */
3876     if (sigint_buf_init > 0) {
3877         NPY_SIGLONGJMP(_NPY_SIGINT_BUF, signum);
3878     }
3879     /*
3880      * sending SIGINT to the worker threads to cancel them is job of the
3881      * application
3882      */
3883 }
3884 
3885 /*NUMPY_API
3886  */
3887 NPY_NO_EXPORT void*
_PyArray_GetSigintBuf(void)3888 _PyArray_GetSigintBuf(void)
3889 {
3890     sigint_buf_init = 1;
3891     return (void *)&_NPY_SIGINT_BUF;
3892 }
3893 
3894 #else
3895 
3896 NPY_NO_EXPORT void
_PyArray_SigintHandler(int signum)3897 _PyArray_SigintHandler(int signum)
3898 {
3899     return;
3900 }
3901 
3902 NPY_NO_EXPORT void*
_PyArray_GetSigintBuf(void)3903 _PyArray_GetSigintBuf(void)
3904 {
3905     return NULL;
3906 }
3907 
3908 #endif
3909 
3910 
3911 static PyObject *
array_shares_memory_impl(PyObject * args,PyObject * kwds,Py_ssize_t default_max_work,int raise_exceptions)3912 array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_work,
3913                          int raise_exceptions)
3914 {
3915     PyObject * self_obj = NULL;
3916     PyObject * other_obj = NULL;
3917     PyArrayObject * self = NULL;
3918     PyArrayObject * other = NULL;
3919     PyObject *max_work_obj = NULL;
3920     static char *kwlist[] = {"self", "other", "max_work", NULL};
3921 
3922     mem_overlap_t result;
3923     static PyObject *too_hard_cls = NULL;
3924     Py_ssize_t max_work;
3925     NPY_BEGIN_THREADS_DEF;
3926 
3927     max_work = default_max_work;
3928 
3929     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:shares_memory_impl", kwlist,
3930                                      &self_obj, &other_obj, &max_work_obj)) {
3931         return NULL;
3932     }
3933 
3934     if (PyArray_Check(self_obj)) {
3935         self = (PyArrayObject*)self_obj;
3936         Py_INCREF(self);
3937     }
3938     else {
3939         /* Use FromAny to enable checking overlap for objects exposing array
3940            interfaces etc. */
3941         self = (PyArrayObject*)PyArray_FROM_O(self_obj);
3942         if (self == NULL) {
3943             goto fail;
3944         }
3945     }
3946 
3947     if (PyArray_Check(other_obj)) {
3948         other = (PyArrayObject*)other_obj;
3949         Py_INCREF(other);
3950     }
3951     else {
3952         other = (PyArrayObject*)PyArray_FROM_O(other_obj);
3953         if (other == NULL) {
3954             goto fail;
3955         }
3956     }
3957 
3958     if (max_work_obj == NULL || max_work_obj == Py_None) {
3959         /* noop */
3960     }
3961     else if (PyLong_Check(max_work_obj)) {
3962         max_work = PyLong_AsSsize_t(max_work_obj);
3963         if (PyErr_Occurred()) {
3964             goto fail;
3965         }
3966     }
3967     else {
3968         PyErr_SetString(PyExc_ValueError, "max_work must be an integer");
3969         goto fail;
3970     }
3971 
3972     if (max_work < -2) {
3973         PyErr_SetString(PyExc_ValueError, "Invalid value for max_work");
3974         goto fail;
3975     }
3976 
3977     NPY_BEGIN_THREADS;
3978     result = solve_may_share_memory(self, other, max_work);
3979     NPY_END_THREADS;
3980 
3981     Py_XDECREF(self);
3982     Py_XDECREF(other);
3983 
3984     if (result == MEM_OVERLAP_NO) {
3985         Py_RETURN_FALSE;
3986     }
3987     else if (result == MEM_OVERLAP_YES) {
3988         Py_RETURN_TRUE;
3989     }
3990     else if (result == MEM_OVERLAP_OVERFLOW) {
3991         if (raise_exceptions) {
3992             PyErr_SetString(PyExc_OverflowError,
3993                             "Integer overflow in computing overlap");
3994             return NULL;
3995         }
3996         else {
3997             /* Don't know, so say yes */
3998             Py_RETURN_TRUE;
3999         }
4000     }
4001     else if (result == MEM_OVERLAP_TOO_HARD) {
4002         if (raise_exceptions) {
4003             npy_cache_import("numpy.core._exceptions", "TooHardError",
4004                              &too_hard_cls);
4005             if (too_hard_cls) {
4006                 PyErr_SetString(too_hard_cls, "Exceeded max_work");
4007             }
4008             return NULL;
4009         }
4010         else {
4011             /* Don't know, so say yes */
4012             Py_RETURN_TRUE;
4013         }
4014     }
4015     else {
4016         /* Doesn't happen usually */
4017         PyErr_SetString(PyExc_RuntimeError,
4018                         "Error in computing overlap");
4019         return NULL;
4020     }
4021 
4022 fail:
4023     Py_XDECREF(self);
4024     Py_XDECREF(other);
4025     return NULL;
4026 }
4027 
4028 
4029 static PyObject *
array_shares_memory(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)4030 array_shares_memory(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
4031 {
4032     return array_shares_memory_impl(args, kwds, NPY_MAY_SHARE_EXACT, 1);
4033 }
4034 
4035 
4036 static PyObject *
array_may_share_memory(PyObject * NPY_UNUSED (ignored),PyObject * args,PyObject * kwds)4037 array_may_share_memory(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
4038 {
4039     return array_shares_memory_impl(args, kwds, NPY_MAY_SHARE_BOUNDS, 0);
4040 }
4041 
4042 static PyObject *
normalize_axis_index(PyObject * NPY_UNUSED (self),PyObject * args,PyObject * kwds)4043 normalize_axis_index(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
4044 {
4045     static char *kwlist[] = {"axis", "ndim", "msg_prefix", NULL};
4046     int axis;
4047     int ndim;
4048     PyObject *msg_prefix = Py_None;
4049 
4050     if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii|O:normalize_axis_index",
4051                                      kwlist, &axis, &ndim, &msg_prefix)) {
4052         return NULL;
4053     }
4054     if (check_and_adjust_axis_msg(&axis, ndim, msg_prefix) < 0) {
4055         return NULL;
4056     }
4057 
4058     return PyLong_FromLong(axis);
4059 }
4060 
4061 
4062 static struct PyMethodDef array_module_methods[] = {
4063     {"_get_implementing_args",
4064         (PyCFunction)array__get_implementing_args,
4065         METH_VARARGS, NULL},
4066     {"_get_ndarray_c_version",
4067         (PyCFunction)array__get_ndarray_c_version,
4068         METH_VARARGS|METH_KEYWORDS, NULL},
4069     {"_reconstruct",
4070         (PyCFunction)array__reconstruct,
4071         METH_VARARGS, NULL},
4072     {"set_string_function",
4073         (PyCFunction)array_set_string_function,
4074         METH_VARARGS|METH_KEYWORDS, NULL},
4075     {"set_numeric_ops",
4076         (PyCFunction)array_set_ops_function,
4077         METH_VARARGS|METH_KEYWORDS, NULL},
4078     {"set_datetimeparse_function",
4079         (PyCFunction)array_set_datetimeparse_function,
4080         METH_VARARGS|METH_KEYWORDS, NULL},
4081     {"set_typeDict",
4082         (PyCFunction)array_set_typeDict,
4083         METH_VARARGS, NULL},
4084     {"array",
4085         (PyCFunction)_array_fromobject,
4086         METH_VARARGS|METH_KEYWORDS, NULL},
4087     {"copyto",
4088         (PyCFunction)array_copyto,
4089         METH_VARARGS|METH_KEYWORDS, NULL},
4090     {"nested_iters",
4091         (PyCFunction)NpyIter_NestedIters,
4092         METH_VARARGS|METH_KEYWORDS, NULL},
4093     {"arange",
4094         (PyCFunction)array_arange,
4095         METH_VARARGS|METH_KEYWORDS, NULL},
4096     {"zeros",
4097         (PyCFunction)array_zeros,
4098         METH_VARARGS|METH_KEYWORDS, NULL},
4099     {"count_nonzero",
4100         (PyCFunction)array_count_nonzero,
4101         METH_VARARGS|METH_KEYWORDS, NULL},
4102     {"empty",
4103         (PyCFunction)array_empty,
4104         METH_VARARGS|METH_KEYWORDS, NULL},
4105     {"empty_like",
4106         (PyCFunction)array_empty_like,
4107         METH_VARARGS|METH_KEYWORDS, NULL},
4108     {"scalar",
4109         (PyCFunction)array_scalar,
4110         METH_VARARGS|METH_KEYWORDS, NULL},
4111     {"where",
4112         (PyCFunction)array_where,
4113         METH_VARARGS, NULL},
4114     {"lexsort",
4115         (PyCFunction)array_lexsort,
4116         METH_VARARGS | METH_KEYWORDS, NULL},
4117     {"putmask",
4118         (PyCFunction)array_putmask,
4119         METH_VARARGS | METH_KEYWORDS, NULL},
4120     {"fromstring",
4121         (PyCFunction)array_fromstring,
4122         METH_VARARGS|METH_KEYWORDS, NULL},
4123     {"fromiter",
4124         (PyCFunction)array_fromiter,
4125         METH_VARARGS|METH_KEYWORDS, NULL},
4126     {"concatenate",
4127         (PyCFunction)array_concatenate,
4128         METH_VARARGS|METH_KEYWORDS, NULL},
4129     {"inner",
4130         (PyCFunction)array_innerproduct,
4131         METH_VARARGS, NULL},
4132     {"dot",
4133         (PyCFunction)array_matrixproduct,
4134         METH_VARARGS | METH_KEYWORDS, NULL},
4135     {"vdot",
4136         (PyCFunction)array_vdot,
4137         METH_VARARGS | METH_KEYWORDS, NULL},
4138     {"c_einsum",
4139         (PyCFunction)array_einsum,
4140         METH_VARARGS|METH_KEYWORDS, NULL},
4141     {"_fastCopyAndTranspose",
4142         (PyCFunction)array_fastCopyAndTranspose,
4143         METH_VARARGS, NULL},
4144     {"correlate",
4145         (PyCFunction)array_correlate,
4146         METH_VARARGS | METH_KEYWORDS, NULL},
4147     {"correlate2",
4148         (PyCFunction)array_correlate2,
4149         METH_VARARGS | METH_KEYWORDS, NULL},
4150     {"frombuffer",
4151         (PyCFunction)array_frombuffer,
4152         METH_VARARGS | METH_KEYWORDS, NULL},
4153     {"fromfile",
4154         (PyCFunction)array_fromfile,
4155         METH_VARARGS | METH_KEYWORDS, NULL},
4156     {"can_cast",
4157         (PyCFunction)array_can_cast_safely,
4158         METH_VARARGS | METH_KEYWORDS, NULL},
4159     {"promote_types",
4160         (PyCFunction)array_promote_types,
4161         METH_VARARGS, NULL},
4162     {"min_scalar_type",
4163         (PyCFunction)array_min_scalar_type,
4164         METH_VARARGS, NULL},
4165     {"result_type",
4166         (PyCFunction)array_result_type,
4167         METH_VARARGS, NULL},
4168     {"shares_memory",
4169         (PyCFunction)array_shares_memory,
4170         METH_VARARGS | METH_KEYWORDS, NULL},
4171     {"may_share_memory",
4172         (PyCFunction)array_may_share_memory,
4173         METH_VARARGS | METH_KEYWORDS, NULL},
4174     /* Datetime-related functions */
4175     {"datetime_data",
4176         (PyCFunction)array_datetime_data,
4177         METH_VARARGS, NULL},
4178     {"datetime_as_string",
4179         (PyCFunction)array_datetime_as_string,
4180         METH_VARARGS | METH_KEYWORDS, NULL},
4181     /* Datetime business-day API */
4182     {"busday_offset",
4183         (PyCFunction)array_busday_offset,
4184         METH_VARARGS | METH_KEYWORDS, NULL},
4185     {"busday_count",
4186         (PyCFunction)array_busday_count,
4187         METH_VARARGS | METH_KEYWORDS, NULL},
4188     {"is_busday",
4189         (PyCFunction)array_is_busday,
4190         METH_VARARGS | METH_KEYWORDS, NULL},
4191     {"format_longfloat",
4192         (PyCFunction)format_longfloat,
4193         METH_VARARGS | METH_KEYWORDS, NULL},
4194     {"dragon4_positional",
4195         (PyCFunction)dragon4_positional,
4196         METH_VARARGS | METH_KEYWORDS, NULL},
4197     {"dragon4_scientific",
4198         (PyCFunction)dragon4_scientific,
4199         METH_VARARGS | METH_KEYWORDS, NULL},
4200     {"compare_chararrays",
4201         (PyCFunction)compare_chararrays,
4202         METH_VARARGS | METH_KEYWORDS, NULL},
4203     {"_vec_string",
4204         (PyCFunction)_vec_string,
4205         METH_VARARGS | METH_KEYWORDS, NULL},
4206     {"_insert", (PyCFunction)arr_insert,
4207         METH_VARARGS | METH_KEYWORDS,
4208         "Insert vals sequentially into equivalent 1-d positions "
4209         "indicated by mask."},
4210     {"bincount", (PyCFunction)arr_bincount,
4211         METH_VARARGS | METH_KEYWORDS, NULL},
4212     {"_monotonicity", (PyCFunction)arr__monotonicity,
4213         METH_VARARGS | METH_KEYWORDS, NULL},
4214     {"implement_array_function",
4215         (PyCFunction)array_implement_array_function,
4216         METH_VARARGS, NULL},
4217     {"interp", (PyCFunction)arr_interp,
4218         METH_VARARGS | METH_KEYWORDS, NULL},
4219     {"interp_complex", (PyCFunction)arr_interp_complex,
4220         METH_VARARGS | METH_KEYWORDS, NULL},
4221     {"ravel_multi_index", (PyCFunction)arr_ravel_multi_index,
4222         METH_VARARGS | METH_KEYWORDS, NULL},
4223     {"unravel_index", (PyCFunction)arr_unravel_index,
4224         METH_VARARGS | METH_KEYWORDS, NULL},
4225     {"add_docstring", (PyCFunction)arr_add_docstring,
4226         METH_VARARGS, NULL},
4227     {"packbits", (PyCFunction)io_pack,
4228         METH_VARARGS | METH_KEYWORDS, NULL},
4229     {"unpackbits", (PyCFunction)io_unpack,
4230         METH_VARARGS | METH_KEYWORDS, NULL},
4231     {"normalize_axis_index", (PyCFunction)normalize_axis_index,
4232         METH_VARARGS | METH_KEYWORDS, NULL},
4233     {"set_legacy_print_mode", (PyCFunction)set_legacy_print_mode,
4234         METH_VARARGS, NULL},
4235     {"_discover_array_parameters", (PyCFunction)_discover_array_parameters,
4236         METH_VARARGS | METH_KEYWORDS, NULL},
4237     {"_get_castingimpl",  (PyCFunction)_get_castingimpl,
4238      METH_VARARGS | METH_KEYWORDS, NULL},
4239     /* from umath */
4240     {"frompyfunc",
4241         (PyCFunction) ufunc_frompyfunc,
4242         METH_VARARGS | METH_KEYWORDS, NULL},
4243     {"seterrobj",
4244         (PyCFunction) ufunc_seterr,
4245         METH_VARARGS, NULL},
4246     {"geterrobj",
4247         (PyCFunction) ufunc_geterr,
4248         METH_VARARGS, NULL},
4249     {"_add_newdoc_ufunc", (PyCFunction)add_newdoc_ufunc,
4250         METH_VARARGS, NULL},
4251     {"_set_madvise_hugepage", (PyCFunction)_set_madvise_hugepage,
4252         METH_O, NULL},
4253     {NULL, NULL, 0, NULL}                /* sentinel */
4254 };
4255 
4256 #include "__multiarray_api.c"
4257 #include "array_method.h"
4258 
4259 /* Establish scalar-type hierarchy
4260  *
4261  *  For dual inheritance we need to make sure that the objects being
4262  *  inherited from have the tp->mro object initialized.  This is
4263  *  not necessarily true for the basic type objects of Python (it is
4264  *  checked for single inheritance but not dual in PyType_Ready).
4265  *
4266  *  Thus, we call PyType_Ready on the standard Python Types, here.
4267  */
4268 static int
setup_scalartypes(PyObject * NPY_UNUSED (dict))4269 setup_scalartypes(PyObject *NPY_UNUSED(dict))
4270 {
4271     if (PyType_Ready(&PyBool_Type) < 0) {
4272         return -1;
4273     }
4274     if (PyType_Ready(&PyFloat_Type) < 0) {
4275         return -1;
4276     }
4277     if (PyType_Ready(&PyComplex_Type) < 0) {
4278         return -1;
4279     }
4280     if (PyType_Ready(&PyBytes_Type) < 0) {
4281         return -1;
4282     }
4283     if (PyType_Ready(&PyUnicode_Type) < 0) {
4284         return -1;
4285     }
4286 
4287 #define SINGLE_INHERIT(child, parent)                                   \
4288     Py##child##ArrType_Type.tp_base = &Py##parent##ArrType_Type;        \
4289     if (PyType_Ready(&Py##child##ArrType_Type) < 0) {                   \
4290         PyErr_Print();                                                  \
4291         PyErr_Format(PyExc_SystemError,                                 \
4292                      "could not initialize Py%sArrType_Type",           \
4293                      #child);                                           \
4294         return -1;                                                      \
4295     }
4296 
4297     if (PyType_Ready(&PyGenericArrType_Type) < 0) {
4298         return -1;
4299     }
4300     SINGLE_INHERIT(Number, Generic);
4301     SINGLE_INHERIT(Integer, Number);
4302     SINGLE_INHERIT(Inexact, Number);
4303     SINGLE_INHERIT(SignedInteger, Integer);
4304     SINGLE_INHERIT(UnsignedInteger, Integer);
4305     SINGLE_INHERIT(Floating, Inexact);
4306     SINGLE_INHERIT(ComplexFloating, Inexact);
4307     SINGLE_INHERIT(Flexible, Generic);
4308     SINGLE_INHERIT(Character, Flexible);
4309 
4310 #define DUAL_INHERIT(child, parent1, parent2)                           \
4311     Py##child##ArrType_Type.tp_base = &Py##parent2##ArrType_Type;       \
4312     Py##child##ArrType_Type.tp_bases =                                  \
4313         Py_BuildValue("(OO)", &Py##parent2##ArrType_Type,               \
4314                       &Py##parent1##_Type);                             \
4315     Py##child##ArrType_Type.tp_hash = Py##parent1##_Type.tp_hash;       \
4316     if (PyType_Ready(&Py##child##ArrType_Type) < 0) {                   \
4317         PyErr_Print();                                                  \
4318         PyErr_Format(PyExc_SystemError,                                 \
4319                      "could not initialize Py%sArrType_Type",           \
4320                      #child);                                           \
4321         return -1;                                                      \
4322     }
4323 
4324 #define DUAL_INHERIT2(child, parent1, parent2)                          \
4325     Py##child##ArrType_Type.tp_base = &Py##parent1##_Type;              \
4326     Py##child##ArrType_Type.tp_bases =                                  \
4327         Py_BuildValue("(OO)", &Py##parent1##_Type,                      \
4328                       &Py##parent2##ArrType_Type);                      \
4329     Py##child##ArrType_Type.tp_richcompare =                            \
4330         Py##parent1##_Type.tp_richcompare;                              \
4331     Py##child##ArrType_Type.tp_hash = Py##parent1##_Type.tp_hash;       \
4332     if (PyType_Ready(&Py##child##ArrType_Type) < 0) {                   \
4333         PyErr_Print();                                                  \
4334         PyErr_Format(PyExc_SystemError,                                 \
4335                      "could not initialize Py%sArrType_Type",           \
4336                      #child);                                           \
4337         return -1;                                                      \
4338     }
4339 
4340     SINGLE_INHERIT(Bool, Generic);
4341     SINGLE_INHERIT(Byte, SignedInteger);
4342     SINGLE_INHERIT(Short, SignedInteger);
4343     SINGLE_INHERIT(Int, SignedInteger);
4344     SINGLE_INHERIT(Long, SignedInteger);
4345     SINGLE_INHERIT(LongLong, SignedInteger);
4346 
4347     /* Datetime doesn't fit in any category */
4348     SINGLE_INHERIT(Datetime, Generic);
4349     /* Timedelta is an integer with an associated unit */
4350     SINGLE_INHERIT(Timedelta, SignedInteger);
4351 
4352     SINGLE_INHERIT(UByte, UnsignedInteger);
4353     SINGLE_INHERIT(UShort, UnsignedInteger);
4354     SINGLE_INHERIT(UInt, UnsignedInteger);
4355     SINGLE_INHERIT(ULong, UnsignedInteger);
4356     SINGLE_INHERIT(ULongLong, UnsignedInteger);
4357 
4358     SINGLE_INHERIT(Half, Floating);
4359     SINGLE_INHERIT(Float, Floating);
4360     DUAL_INHERIT(Double, Float, Floating);
4361     SINGLE_INHERIT(LongDouble, Floating);
4362 
4363     SINGLE_INHERIT(CFloat, ComplexFloating);
4364     DUAL_INHERIT(CDouble, Complex, ComplexFloating);
4365     SINGLE_INHERIT(CLongDouble, ComplexFloating);
4366 
4367     DUAL_INHERIT2(String, String, Character);
4368     DUAL_INHERIT2(Unicode, Unicode, Character);
4369 
4370     SINGLE_INHERIT(Void, Flexible);
4371 
4372     SINGLE_INHERIT(Object, Generic);
4373 
4374     return 0;
4375 
4376 #undef SINGLE_INHERIT
4377 #undef DUAL_INHERIT
4378 #undef DUAL_INHERIT2
4379 
4380     /*
4381      * Clean up string and unicode array types so they act more like
4382      * strings -- get their tables from the standard types.
4383      */
4384 }
4385 
4386 /* place a flag dictionary in d */
4387 
4388 static void
set_flaginfo(PyObject * d)4389 set_flaginfo(PyObject *d)
4390 {
4391     PyObject *s;
4392     PyObject *newd;
4393 
4394     newd = PyDict_New();
4395 
4396 #define _addnew(key, val, one)                                       \
4397     PyDict_SetItemString(newd, #key, s=PyLong_FromLong(val));    \
4398     Py_DECREF(s);                                               \
4399     PyDict_SetItemString(newd, #one, s=PyLong_FromLong(val));    \
4400     Py_DECREF(s)
4401 
4402 #define _addone(key, val)                                            \
4403     PyDict_SetItemString(newd, #key, s=PyLong_FromLong(val));    \
4404     Py_DECREF(s)
4405 
4406     _addnew(OWNDATA, NPY_ARRAY_OWNDATA, O);
4407     _addnew(FORTRAN, NPY_ARRAY_F_CONTIGUOUS, F);
4408     _addnew(CONTIGUOUS, NPY_ARRAY_C_CONTIGUOUS, C);
4409     _addnew(ALIGNED, NPY_ARRAY_ALIGNED, A);
4410     _addnew(UPDATEIFCOPY, NPY_ARRAY_UPDATEIFCOPY, U);
4411     _addnew(WRITEBACKIFCOPY, NPY_ARRAY_WRITEBACKIFCOPY, X);
4412     _addnew(WRITEABLE, NPY_ARRAY_WRITEABLE, W);
4413     _addone(C_CONTIGUOUS, NPY_ARRAY_C_CONTIGUOUS);
4414     _addone(F_CONTIGUOUS, NPY_ARRAY_F_CONTIGUOUS);
4415 
4416 #undef _addone
4417 #undef _addnew
4418 
4419     PyDict_SetItemString(d, "_flagdict", newd);
4420     Py_DECREF(newd);
4421     return;
4422 }
4423 
4424 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array = NULL;
4425 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_prepare = NULL;
4426 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_wrap = NULL;
4427 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_array_finalize = NULL;
4428 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ufunc = NULL;
4429 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_implementation = NULL;
4430 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_order = NULL;
4431 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_copy = NULL;
4432 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_dtype = NULL;
4433 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_ndmin = NULL;
4434 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_axis1 = NULL;
4435 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_axis2 = NULL;
4436 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_like = NULL;
4437 NPY_VISIBILITY_HIDDEN PyObject * npy_ma_str_numpy = NULL;
4438 
4439 static int
intern_strings(void)4440 intern_strings(void)
4441 {
4442     npy_ma_str_array = PyUnicode_InternFromString("__array__");
4443     npy_ma_str_array_prepare = PyUnicode_InternFromString("__array_prepare__");
4444     npy_ma_str_array_wrap = PyUnicode_InternFromString("__array_wrap__");
4445     npy_ma_str_array_finalize = PyUnicode_InternFromString("__array_finalize__");
4446     npy_ma_str_ufunc = PyUnicode_InternFromString("__array_ufunc__");
4447     npy_ma_str_implementation = PyUnicode_InternFromString("_implementation");
4448     npy_ma_str_order = PyUnicode_InternFromString("order");
4449     npy_ma_str_copy = PyUnicode_InternFromString("copy");
4450     npy_ma_str_dtype = PyUnicode_InternFromString("dtype");
4451     npy_ma_str_ndmin = PyUnicode_InternFromString("ndmin");
4452     npy_ma_str_axis1 = PyUnicode_InternFromString("axis1");
4453     npy_ma_str_axis2 = PyUnicode_InternFromString("axis2");
4454     npy_ma_str_like = PyUnicode_InternFromString("like");
4455     npy_ma_str_numpy = PyUnicode_InternFromString("numpy");
4456 
4457     return npy_ma_str_array && npy_ma_str_array_prepare &&
4458            npy_ma_str_array_wrap && npy_ma_str_array_finalize &&
4459            npy_ma_str_ufunc && npy_ma_str_implementation &&
4460            npy_ma_str_order && npy_ma_str_copy && npy_ma_str_dtype &&
4461            npy_ma_str_ndmin && npy_ma_str_axis1 && npy_ma_str_axis2 &&
4462            npy_ma_str_like && npy_ma_str_numpy;
4463 }
4464 
4465 static struct PyModuleDef moduledef = {
4466         PyModuleDef_HEAD_INIT,
4467         "_multiarray_umath",
4468         NULL,
4469         -1,
4470         array_module_methods,
4471         NULL,
4472         NULL,
4473         NULL,
4474         NULL
4475 };
4476 
4477 /* Initialization function for the module */
PyInit__multiarray_umath(void)4478 PyMODINIT_FUNC PyInit__multiarray_umath(void) {
4479     PyObject *m, *d, *s;
4480     PyObject *c_api;
4481 
4482     /* Initialize CPU features */
4483     if (npy_cpu_init() < 0) {
4484         goto err;
4485     }
4486 
4487     /* Create the module and add the functions */
4488     m = PyModule_Create(&moduledef);
4489     if (!m) {
4490         goto err;
4491     }
4492 
4493 #if defined(MS_WIN64) && defined(__GNUC__)
4494   PyErr_WarnEx(PyExc_Warning,
4495         "Numpy built with MINGW-W64 on Windows 64 bits is experimental, " \
4496         "and only available for \n" \
4497         "testing. You are advised not to use it for production. \n\n" \
4498         "CRASHES ARE TO BE EXPECTED - PLEASE REPORT THEM TO NUMPY DEVELOPERS",
4499         1);
4500 #endif
4501 
4502     /* Initialize access to the PyDateTime API */
4503     numpy_pydatetime_import();
4504 
4505     if (PyErr_Occurred()) {
4506         goto err;
4507     }
4508 
4509     /* Add some symbolic constants to the module */
4510     d = PyModule_GetDict(m);
4511     if (!d) {
4512         goto err;
4513     }
4514 
4515     /*
4516      * Before calling PyType_Ready, initialize the tp_hash slot in
4517      * PyArray_Type to work around mingw32 not being able initialize
4518      * static structure slots with functions from the Python C_API.
4519      */
4520     PyArray_Type.tp_hash = PyObject_HashNotImplemented;
4521 
4522     if (PyType_Ready(&PyUFunc_Type) < 0) {
4523         goto err;
4524     }
4525 
4526     /* Load the ufunc operators into the array module's namespace */
4527     if (InitOperators(d) < 0) {
4528         goto err;
4529     }
4530 
4531     if (set_matmul_flags(d) < 0) {
4532         goto err;
4533     }
4534 
4535     PyArrayDTypeMeta_Type.tp_base = &PyType_Type;
4536     if (PyType_Ready(&PyArrayDTypeMeta_Type) < 0) {
4537         goto err;
4538     }
4539 
4540     PyArrayDescr_Type.tp_hash = PyArray_DescrHash;
4541     Py_SET_TYPE(&PyArrayDescr_Type, &PyArrayDTypeMeta_Type);
4542     if (PyType_Ready(&PyArrayDescr_Type) < 0) {
4543         goto err;
4544     }
4545 
4546     initialize_casting_tables();
4547     initialize_numeric_types();
4548     if (initscalarmath(m) < 0) {
4549         goto err;
4550     }
4551 
4552     if (PyType_Ready(&PyArray_Type) < 0) {
4553         goto err;
4554     }
4555     if (setup_scalartypes(d) < 0) {
4556         goto err;
4557     }
4558     PyArrayIter_Type.tp_iter = PyObject_SelfIter;
4559     NpyIter_Type.tp_iter = PyObject_SelfIter;
4560     PyArrayMultiIter_Type.tp_iter = PyObject_SelfIter;
4561     PyArrayMultiIter_Type.tp_free = PyArray_free;
4562     if (PyType_Ready(&PyArrayIter_Type) < 0) {
4563         goto err;
4564     }
4565     if (PyType_Ready(&PyArrayMapIter_Type) < 0) {
4566         goto err;
4567     }
4568     if (PyType_Ready(&PyArrayMultiIter_Type) < 0) {
4569         goto err;
4570     }
4571     PyArrayNeighborhoodIter_Type.tp_new = PyType_GenericNew;
4572     if (PyType_Ready(&PyArrayNeighborhoodIter_Type) < 0) {
4573         goto err;
4574     }
4575     if (PyType_Ready(&NpyIter_Type) < 0) {
4576         goto err;
4577     }
4578 
4579     if (PyType_Ready(&PyArrayFlags_Type) < 0) {
4580         goto err;
4581     }
4582     NpyBusDayCalendar_Type.tp_new = PyType_GenericNew;
4583     if (PyType_Ready(&NpyBusDayCalendar_Type) < 0) {
4584         goto err;
4585     }
4586 
4587     c_api = PyCapsule_New((void *)PyArray_API, NULL, NULL);
4588     if (c_api == NULL) {
4589         goto err;
4590     }
4591     PyDict_SetItemString(d, "_ARRAY_API", c_api);
4592     Py_DECREF(c_api);
4593 
4594     c_api = PyCapsule_New((void *)PyUFunc_API, NULL, NULL);
4595     if (c_api == NULL) {
4596         goto err;
4597     }
4598     PyDict_SetItemString(d, "_UFUNC_API", c_api);
4599     Py_DECREF(c_api);
4600     if (PyErr_Occurred()) {
4601         goto err;
4602     }
4603 
4604     /*
4605      * PyExc_Exception should catch all the standard errors that are
4606      * now raised instead of the string exception "multiarray.error"
4607 
4608      * This is for backward compatibility with existing code.
4609      */
4610     PyDict_SetItemString (d, "error", PyExc_Exception);
4611 
4612     s = PyLong_FromLong(NPY_TRACE_DOMAIN);
4613     PyDict_SetItemString(d, "tracemalloc_domain", s);
4614     Py_DECREF(s);
4615 
4616     s = PyUnicode_FromString("3.1");
4617     PyDict_SetItemString(d, "__version__", s);
4618     Py_DECREF(s);
4619 
4620     s = npy_cpu_features_dict();
4621     if (s == NULL) {
4622         goto err;
4623     }
4624     if (PyDict_SetItemString(d, "__cpu_features__", s) < 0) {
4625         Py_DECREF(s);
4626         goto err;
4627     }
4628     Py_DECREF(s);
4629 
4630     s = npy_cpu_baseline_list();
4631     if (s == NULL) {
4632         goto err;
4633     }
4634     if (PyDict_SetItemString(d, "__cpu_baseline__", s) < 0) {
4635         Py_DECREF(s);
4636         goto err;
4637     }
4638     Py_DECREF(s);
4639 
4640     s = npy_cpu_dispatch_list();
4641     if (s == NULL) {
4642         goto err;
4643     }
4644     if (PyDict_SetItemString(d, "__cpu_dispatch__", s) < 0) {
4645         Py_DECREF(s);
4646         goto err;
4647     }
4648     Py_DECREF(s);
4649 
4650     s = PyCapsule_New((void *)_datetime_strings, NULL, NULL);
4651     if (s == NULL) {
4652         goto err;
4653     }
4654     PyDict_SetItemString(d, "DATETIMEUNITS", s);
4655     Py_DECREF(s);
4656 
4657 #define ADDCONST(NAME)                          \
4658     s = PyLong_FromLong(NPY_##NAME);             \
4659     PyDict_SetItemString(d, #NAME, s);          \
4660     Py_DECREF(s)
4661 
4662 
4663     ADDCONST(ALLOW_THREADS);
4664     ADDCONST(BUFSIZE);
4665     ADDCONST(CLIP);
4666 
4667     ADDCONST(ITEM_HASOBJECT);
4668     ADDCONST(LIST_PICKLE);
4669     ADDCONST(ITEM_IS_POINTER);
4670     ADDCONST(NEEDS_INIT);
4671     ADDCONST(NEEDS_PYAPI);
4672     ADDCONST(USE_GETITEM);
4673     ADDCONST(USE_SETITEM);
4674 
4675     ADDCONST(RAISE);
4676     ADDCONST(WRAP);
4677     ADDCONST(MAXDIMS);
4678 
4679     ADDCONST(MAY_SHARE_BOUNDS);
4680     ADDCONST(MAY_SHARE_EXACT);
4681 #undef ADDCONST
4682 
4683     PyDict_SetItemString(d, "ndarray", (PyObject *)&PyArray_Type);
4684     PyDict_SetItemString(d, "flatiter", (PyObject *)&PyArrayIter_Type);
4685     PyDict_SetItemString(d, "nditer", (PyObject *)&NpyIter_Type);
4686     PyDict_SetItemString(d, "broadcast",
4687                          (PyObject *)&PyArrayMultiIter_Type);
4688     PyDict_SetItemString(d, "dtype", (PyObject *)&PyArrayDescr_Type);
4689     PyDict_SetItemString(d, "flagsobj", (PyObject *)&PyArrayFlags_Type);
4690 
4691     /* Business day calendar object */
4692     PyDict_SetItemString(d, "busdaycalendar",
4693                             (PyObject *)&NpyBusDayCalendar_Type);
4694     set_flaginfo(d);
4695 
4696     /* Create the typeinfo types */
4697     if (typeinfo_init_structsequences(d) < 0) {
4698         goto err;
4699     }
4700 
4701     if (!intern_strings()) {
4702         goto err;
4703     }
4704 
4705     if (set_typeinfo(d) != 0) {
4706         goto err;
4707     }
4708     if (PyType_Ready(&PyArrayMethod_Type) < 0) {
4709         goto err;
4710     }
4711     if (PyType_Ready(&PyBoundArrayMethod_Type) < 0) {
4712         goto err;
4713     }
4714     if (initialize_and_map_pytypes_to_dtypes() < 0) {
4715         goto err;
4716     }
4717 
4718     if (PyArray_InitializeCasts() < 0) {
4719         goto err;
4720     }
4721 
4722     if (initumath(m) != 0) {
4723         goto err;
4724     }
4725     return m;
4726 
4727  err:
4728     if (!PyErr_Occurred()) {
4729         PyErr_SetString(PyExc_RuntimeError,
4730                         "cannot load multiarray module.");
4731     }
4732     return NULL;
4733 }
4734