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, ©,
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