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

34
NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
35

36
/* Internal APIs */
37
#include "alloc.h"
38
#include "abstractdtypes.h"
39
#include "array_coercion.h"
40
#include "arrayfunction_override.h"
41
#include "arraytypes.h"
42
#include "arrayobject.h"
43
#include "hashdescr.h"
44
#include "descriptor.h"
45
#include "dragon4.h"
46
#include "calculation.h"
47
#include "number.h"
48
#include "scalartypes.h"
49
#include "convert_datatype.h"
50
#include "conversion_utils.h"
51
#include "nditer_pywrap.h"
52
#include "methods.h"
53
#include "_datetime.h"
54
#include "datetime_strings.h"
55
#include "datetime_busday.h"
56
#include "datetime_busdaycal.h"
57
#include "item_selection.h"
58
#include "shape.h"
59
#include "ctors.h"
60
#include "array_assign.h"
61
#include "common.h"
62
#include "multiarraymodule.h"
63
#include "cblasfuncs.h"
64
#include "vdot.h"
65
#include "templ_common.h" /* for npy_mul_with_overflow_intp */
66
#include "compiled_base.h"
67
#include "mem_overlap.h"
68
#include "typeinfo.h"
69

70
#include "get_attr_string.h"
71

72
/*
73
 *****************************************************************************
74
 **                    INCLUDE GENERATED CODE                               **
75
 *****************************************************************************
76
 */
77
#include "funcs.inc"
78
#include "umathmodule.h"
79

80
NPY_NO_EXPORT int initscalarmath(PyObject *);
81
NPY_NO_EXPORT int set_matmul_flags(PyObject *d); /* in ufunc_object.c */
82

83
/*
84
 * global variable to determine if legacy printing is enabled, accessible from
85
 * C. For simplicity the mode is encoded as an integer where '0' means no
86
 * legacy mode, and '113' means 1.13 legacy mode. We can upgrade this if we
87
 * have more complex requirements in the future.
88
 */
89
int npy_legacy_print_mode = 0;
90

91
static PyObject *
92 1
set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args)
93
{
94 1
    if (!PyArg_ParseTuple(args, "i", &npy_legacy_print_mode)) {
95
        return NULL;
96
    }
97 1
    Py_RETURN_NONE;
98
}
99

100

101
/* Only here for API compatibility */
102
NPY_NO_EXPORT PyTypeObject PyBigArray_Type;
103

104

105
/*NUMPY_API
106
 * Get Priority from object
107
 */
108
NPY_NO_EXPORT double
109 1
PyArray_GetPriority(PyObject *obj, double default_)
110
{
111
    PyObject *ret;
112 1
    double priority = NPY_PRIORITY;
113

114 1
    if (PyArray_CheckExact(obj)) {
115
        return priority;
116
    }
117 1
    else if (PyArray_CheckAnyScalarExact(obj)) {
118
        return NPY_SCALAR_PRIORITY;
119
    }
120

121 1
    ret = PyArray_LookupSpecial_OnInstance(obj, "__array_priority__");
122 1
    if (ret == NULL) {
123 1
        if (PyErr_Occurred()) {
124 0
            PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
125
        }
126
        return default_;
127
    }
128

129 1
    priority = PyFloat_AsDouble(ret);
130 1
    Py_DECREF(ret);
131
    return priority;
132
}
133

134
/*NUMPY_API
135
 * Multiply a List of ints
136
 */
137
NPY_NO_EXPORT int
138 0
PyArray_MultiplyIntList(int const *l1, int n)
139
{
140 0
    int s = 1;
141

142 0
    while (n--) {
143 0
        s *= (*l1++);
144
    }
145 0
    return s;
146
}
147

148
/*NUMPY_API
149
 * Multiply a List
150
 */
151
NPY_NO_EXPORT npy_intp
152 1
PyArray_MultiplyList(npy_intp const *l1, int n)
153
{
154 1
    npy_intp s = 1;
155

156 1
    while (n--) {
157 1
        s *= (*l1++);
158
    }
159 1
    return s;
160
}
161

162
/*NUMPY_API
163
 * Multiply a List of Non-negative numbers with over-flow detection.
164
 */
165
NPY_NO_EXPORT npy_intp
166 1
PyArray_OverflowMultiplyList(npy_intp const *l1, int n)
167
{
168 1
    npy_intp prod = 1;
169
    int i;
170

171 1
    for (i = 0; i < n; i++) {
172 1
        npy_intp dim = l1[i];
173

174 1
        if (dim == 0) {
175
            return 0;
176
        }
177 1
        if (npy_mul_with_overflow_intp(&prod, prod, dim)) {
178
            return -1;
179
        }
180
    }
181
    return prod;
182
}
183

184
/*NUMPY_API
185
 * Produce a pointer into array
186
 */
187
NPY_NO_EXPORT void *
188 0
PyArray_GetPtr(PyArrayObject *obj, npy_intp const* ind)
189
{
190 0
    int n = PyArray_NDIM(obj);
191 0
    npy_intp *strides = PyArray_STRIDES(obj);
192 0
    char *dptr = PyArray_DATA(obj);
193

194 0
    while (n--) {
195 0
        dptr += (*strides++) * (*ind++);
196
    }
197 0
    return (void *)dptr;
198
}
199

200
/*NUMPY_API
201
 * Compare Lists
202
 */
203
NPY_NO_EXPORT int
204 1
PyArray_CompareLists(npy_intp const *l1, npy_intp const *l2, int n)
205
{
206
    int i;
207

208 1
    for (i = 0; i < n; i++) {
209 1
        if (l1[i] != l2[i]) {
210
            return 0;
211
        }
212
    }
213
    return 1;
214
}
215

216
/*
217
 * simulates a C-style 1-3 dimensional array which can be accessed using
218
 * ptr[i]  or ptr[i][j] or ptr[i][j][k] -- requires pointer allocation
219
 * for 2-d and 3-d.
220
 *
221
 * For 2-d and up, ptr is NOT equivalent to a statically defined
222
 * 2-d or 3-d array.  In particular, it cannot be passed into a
223
 * function that requires a true pointer to a fixed-size array.
224
 */
225

226
/*NUMPY_API
227
 * Simulate a C-array
228
 * steals a reference to typedescr -- can be NULL
229
 */
230
NPY_NO_EXPORT int
231 1
PyArray_AsCArray(PyObject **op, void *ptr, npy_intp *dims, int nd,
232
                 PyArray_Descr* typedescr)
233
{
234
    PyArrayObject *ap;
235
    npy_intp n, m, i, j;
236
    char **ptr2;
237
    char ***ptr3;
238

239 1
    if ((nd < 1) || (nd > 3)) {
240 0
        PyErr_SetString(PyExc_ValueError,
241
                        "C arrays of only 1-3 dimensions available");
242 0
        Py_XDECREF(typedescr);
243
        return -1;
244
    }
245 1
    if ((ap = (PyArrayObject*)PyArray_FromAny(*op, typedescr, nd, nd,
246
                                      NPY_ARRAY_CARRAY, NULL)) == NULL) {
247
        return -1;
248
    }
249 1
    switch(nd) {
250 1
    case 1:
251 1
        *((char **)ptr) = PyArray_DATA(ap);
252 1
        break;
253 1
    case 2:
254 1
        n = PyArray_DIMS(ap)[0];
255 1
        ptr2 = (char **)PyArray_malloc(n * sizeof(char *));
256 1
        if (!ptr2) {
257 0
            PyErr_NoMemory();
258 0
            return -1;
259
        }
260 1
        for (i = 0; i < n; i++) {
261 1
            ptr2[i] = PyArray_BYTES(ap) + i*PyArray_STRIDES(ap)[0];
262
        }
263 1
        *((char ***)ptr) = ptr2;
264 1
        break;
265 1
    case 3:
266 1
        n = PyArray_DIMS(ap)[0];
267 1
        m = PyArray_DIMS(ap)[1];
268 1
        ptr3 = (char ***)PyArray_malloc(n*(m+1) * sizeof(char *));
269 1
        if (!ptr3) {
270 0
            PyErr_NoMemory();
271 0
            return -1;
272
        }
273 1
        for (i = 0; i < n; i++) {
274 1
            ptr3[i] = (char **) &ptr3[n + m * i];
275 1
            for (j = 0; j < m; j++) {
276 1
                ptr3[i][j] = PyArray_BYTES(ap) + i*PyArray_STRIDES(ap)[0] + j*PyArray_STRIDES(ap)[1];
277
            }
278
        }
279 1
        *((char ****)ptr) = ptr3;
280
    }
281 1
    if (nd) {
282 1
        memcpy(dims, PyArray_DIMS(ap), nd*sizeof(npy_intp));
283
    }
284 1
    *op = (PyObject *)ap;
285 1
    return 0;
286
}
287

288
/* Deprecated --- Use PyArray_AsCArray instead */
289

290
/*NUMPY_API
291
 * Convert to a 1D C-array
292
 */
293
NPY_NO_EXPORT int
294 1
PyArray_As1D(PyObject **NPY_UNUSED(op), char **NPY_UNUSED(ptr),
295
             int *NPY_UNUSED(d1), int NPY_UNUSED(typecode))
296
{
297
    /* 2008-07-14, 1.5 */
298 1
    PyErr_SetString(PyExc_NotImplementedError,
299
                "PyArray_As1D: use PyArray_AsCArray.");
300 1
    return -1;
301
}
302

303
/*NUMPY_API
304
 * Convert to a 2D C-array
305
 */
306
NPY_NO_EXPORT int
307 1
PyArray_As2D(PyObject **NPY_UNUSED(op), char ***NPY_UNUSED(ptr),
308
             int *NPY_UNUSED(d1), int *NPY_UNUSED(d2), int NPY_UNUSED(typecode))
309
{
310
    /* 2008-07-14, 1.5 */
311 1
    PyErr_SetString(PyExc_NotImplementedError,
312
                "PyArray_As2D: use PyArray_AsCArray.");
313 1
    return -1;
314
}
315

316
/* End Deprecated */
317

318
/*NUMPY_API
319
 * Free pointers created if As2D is called
320
 */
321
NPY_NO_EXPORT int
322 1
PyArray_Free(PyObject *op, void *ptr)
323
{
324 1
    PyArrayObject *ap = (PyArrayObject *)op;
325

326 1
    if ((PyArray_NDIM(ap) < 1) || (PyArray_NDIM(ap) > 3)) {
327
        return -1;
328
    }
329 1
    if (PyArray_NDIM(ap) >= 2) {
330 1
        PyArray_free(ptr);
331
    }
332 1
    Py_DECREF(ap);
333
    return 0;
334
}
335

336
/*
337
 * Get the ndarray subclass with the highest priority
338
 */
339
NPY_NO_EXPORT PyTypeObject *
340 1
PyArray_GetSubType(int narrays, PyArrayObject **arrays) {
341 1
    PyTypeObject *subtype = &PyArray_Type;
342 1
    double priority = NPY_PRIORITY;
343
    int i;
344

345
    /* Get the priority subtype for the array */
346 1
    for (i = 0; i < narrays; ++i) {
347 1
        if (Py_TYPE(arrays[i]) != subtype) {
348 1
            double pr = PyArray_GetPriority((PyObject *)(arrays[i]), 0.0);
349 1
            if (pr > priority) {
350 1
                priority = pr;
351 1
                subtype = Py_TYPE(arrays[i]);
352
            }
353
        }
354
    }
355

356 1
    return subtype;
357
}
358

359

360
/*
361
 * Concatenates a list of ndarrays.
362
 */
363
NPY_NO_EXPORT PyArrayObject *
364 1
PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis,
365
                          PyArrayObject* ret, PyArray_Descr *dtype,
366
                          NPY_CASTING casting)
367
{
368
    int iarrays, idim, ndim;
369
    npy_intp shape[NPY_MAXDIMS];
370 1
    PyArrayObject_fields *sliding_view = NULL;
371

372 1
    if (narrays <= 0) {
373 1
        PyErr_SetString(PyExc_ValueError,
374
                        "need at least one array to concatenate");
375 1
        return NULL;
376
    }
377

378
    /* All the arrays must have the same 'ndim' */
379 1
    ndim = PyArray_NDIM(arrays[0]);
380

381 1
    if (ndim == 0) {
382 1
        PyErr_SetString(PyExc_ValueError,
383
                        "zero-dimensional arrays cannot be concatenated");
384 1
        return NULL;
385
    }
386

387
    /* Handle standard Python negative indexing */
388 1
    if (check_and_adjust_axis(&axis, ndim) < 0) {
389
        return NULL;
390
    }
391

392
    /*
393
     * Figure out the final concatenated shape starting from the first
394
     * array's shape.
395
     */
396 1
    memcpy(shape, PyArray_SHAPE(arrays[0]), ndim * sizeof(shape[0]));
397 1
    for (iarrays = 1; iarrays < narrays; ++iarrays) {
398
        npy_intp *arr_shape;
399

400 1
        if (PyArray_NDIM(arrays[iarrays]) != ndim) {
401 1
            PyErr_Format(PyExc_ValueError,
402
                         "all the input arrays must have same number of "
403
                         "dimensions, but the array at index %d has %d "
404
                         "dimension(s) and the array at index %d has %d "
405
                         "dimension(s)",
406
                         0, ndim, iarrays, PyArray_NDIM(arrays[iarrays]));
407 1
            return NULL;
408
        }
409 1
        arr_shape = PyArray_SHAPE(arrays[iarrays]);
410

411 1
        for (idim = 0; idim < ndim; ++idim) {
412
            /* Build up the size of the concatenation axis */
413 1
            if (idim == axis) {
414 1
                shape[idim] += arr_shape[idim];
415
            }
416
            /* Validate that the rest of the dimensions match */
417 1
            else if (shape[idim] != arr_shape[idim]) {
418 1
                PyErr_Format(PyExc_ValueError,
419
                             "all the input array dimensions for the "
420
                             "concatenation axis must match exactly, but "
421
                             "along dimension %d, the array at index %d has "
422
                             "size %d and the array at index %d has size %d",
423
                             idim, 0, shape[idim], iarrays, arr_shape[idim]);
424 1
                return NULL;
425
            }
426
        }
427
    }
428

429 1
    if (ret != NULL) {
430
        assert(dtype == NULL);
431 1
        if (PyArray_NDIM(ret) != ndim) {
432 1
            PyErr_SetString(PyExc_ValueError,
433
                            "Output array has wrong dimensionality");
434 1
            return NULL;
435
        }
436 1
        if (!PyArray_CompareLists(shape, PyArray_SHAPE(ret), ndim)) {
437 1
            PyErr_SetString(PyExc_ValueError,
438
                            "Output array is the wrong shape");
439 1
            return NULL;
440
        }
441 1
        Py_INCREF(ret);
442
    }
443
    else {
444
        npy_intp s, strides[NPY_MAXDIMS];
445
        int strideperm[NPY_MAXDIMS];
446

447
        /* Get the priority subtype for the array */
448 1
        PyTypeObject *subtype = PyArray_GetSubType(narrays, arrays);
449

450 1
        if (dtype == NULL) {
451
            /* Get the resulting dtype from combining all the arrays */
452 1
            dtype = (PyArray_Descr *)PyArray_ResultType(
453
                                                narrays, arrays, 0, NULL);
454 1
            if (dtype == NULL) {
455 1
                return NULL;
456
            }
457
        }
458
        else {
459 1
            Py_INCREF(dtype);
460
        }
461

462
        /*
463
         * Figure out the permutation to apply to the strides to match
464
         * the memory layout of the input arrays, using ambiguity
465
         * resolution rules matching that of the NpyIter.
466
         */
467 1
        PyArray_CreateMultiSortedStridePerm(narrays, arrays, ndim, strideperm);
468 1
        s = dtype->elsize;
469 1
        for (idim = ndim-1; idim >= 0; --idim) {
470 1
            int iperm = strideperm[idim];
471 1
            strides[iperm] = s;
472 1
            s *= shape[iperm];
473
        }
474

475
        /* Allocate the array for the result. This steals the 'dtype' reference. */
476 1
        ret = (PyArrayObject *)PyArray_NewFromDescr(subtype,
477
                                                        dtype,
478
                                                        ndim,
479
                                                        shape,
480
                                                        strides,
481
                                                        NULL,
482
                                                        0,
483
                                                        NULL);
484 1
        if (ret == NULL) {
485
            return NULL;
486
        }
487
    }
488

489
    /*
490
     * Create a view which slides through ret for assigning the
491
     * successive input arrays.
492
     */
493 1
    sliding_view = (PyArrayObject_fields *)PyArray_View(ret,
494
                                                        NULL, &PyArray_Type);
495 1
    if (sliding_view == NULL) {
496 0
        Py_DECREF(ret);
497
        return NULL;
498
    }
499 1
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
500
        /* Set the dimension to match the input array's */
501 1
        sliding_view->dimensions[axis] = PyArray_SHAPE(arrays[iarrays])[axis];
502

503
        /* Copy the data for this array */
504 1
        if (PyArray_AssignArray((PyArrayObject *)sliding_view, arrays[iarrays],
505
                            NULL, casting) < 0) {
506 1
            Py_DECREF(sliding_view);
507 1
            Py_DECREF(ret);
508
            return NULL;
509
        }
510

511
        /* Slide to the start of the next window */
512 1
        sliding_view->data += sliding_view->dimensions[axis] *
513 1
                                 sliding_view->strides[axis];
514
    }
515

516 1
    Py_DECREF(sliding_view);
517
    return ret;
518
}
519

520
/*
521
 * Concatenates a list of ndarrays, flattening each in the specified order.
522
 */
523
NPY_NO_EXPORT PyArrayObject *
524 1
PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays,
525
                                   NPY_ORDER order, PyArrayObject *ret,
526
                                   PyArray_Descr *dtype, NPY_CASTING casting,
527
                                   npy_bool casting_not_passed)
528
{
529
    int iarrays;
530 1
    npy_intp shape = 0;
531 1
    PyArrayObject_fields *sliding_view = NULL;
532

533 1
    if (narrays <= 0) {
534 0
        PyErr_SetString(PyExc_ValueError,
535
                        "need at least one array to concatenate");
536 0
        return NULL;
537
    }
538

539
    /*
540
     * Figure out the final concatenated shape starting from the first
541
     * array's shape.
542
     */
543 1
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
544 1
        shape += PyArray_SIZE(arrays[iarrays]);
545
        /* Check for overflow */
546 1
        if (shape < 0) {
547 0
            PyErr_SetString(PyExc_ValueError,
548
                            "total number of elements "
549
                            "too large to concatenate");
550 0
            return NULL;
551
        }
552
    }
553

554 1
    int out_passed = 0;
555 1
    if (ret != NULL) {
556
        assert(dtype == NULL);
557 1
        out_passed = 1;
558 1
        if (PyArray_NDIM(ret) != 1) {
559 0
            PyErr_SetString(PyExc_ValueError,
560
                            "Output array must be 1D");
561 0
            return NULL;
562
        }
563 1
        if (shape != PyArray_SIZE(ret)) {
564 0
            PyErr_SetString(PyExc_ValueError,
565
                            "Output array is the wrong size");
566 0
            return NULL;
567
        }
568 1
        Py_INCREF(ret);
569
    }
570
    else {
571
        npy_intp stride;
572

573
        /* Get the priority subtype for the array */
574 1
        PyTypeObject *subtype = PyArray_GetSubType(narrays, arrays);
575

576 1
        if (dtype == NULL) {
577
            /* Get the resulting dtype from combining all the arrays */
578 1
            dtype = (PyArray_Descr *)PyArray_ResultType(
579
                                            narrays, arrays, 0, NULL);
580 1
            if (dtype == NULL) {
581 0
                return NULL;
582
            }
583
        }
584
        else {
585 1
            Py_INCREF(dtype);
586
        }
587

588 1
        stride = dtype->elsize;
589

590
        /* Allocate the array for the result. This steals the 'dtype' reference. */
591 1
        ret = (PyArrayObject *)PyArray_NewFromDescr(subtype,
592
                                                        dtype,
593
                                                        1,
594
                                                        &shape,
595
                                                        &stride,
596
                                                        NULL,
597
                                                        0,
598
                                                        NULL);
599 1
        if (ret == NULL) {
600
            return NULL;
601
        }
602
    }
603

604
    /*
605
     * Create a view which slides through ret for assigning the
606
     * successive input arrays.
607
     */
608 1
    sliding_view = (PyArrayObject_fields *)PyArray_View(ret,
609
                                                        NULL, &PyArray_Type);
610 1
    if (sliding_view == NULL) {
611 0
        Py_DECREF(ret);
612
        return NULL;
613
    }
614

615
    int give_deprecation_warning = 1;  /* To give warning for just one input array. */
616 1
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
617
        /* Adjust the window dimensions for this array */
618 1
        sliding_view->dimensions[0] = PyArray_SIZE(arrays[iarrays]);
619

620 1
        if (!PyArray_CanCastArrayTo(
621
                arrays[iarrays], PyArray_DESCR(ret), casting)) {
622
            /* This should be an error, but was previously allowed here. */
623 1
            if (casting_not_passed && out_passed) {
624
                /* NumPy 1.20, 2020-09-03 */
625 0
                if (give_deprecation_warning && DEPRECATE(
626
                        "concatenate() with `axis=None` will use same-kind "
627
                        "casting by default in the future. Please use "
628
                        "`casting='unsafe'` to retain the old behaviour. "
629
                        "In the future this will be a TypeError.") < 0) {
630 0
                    Py_DECREF(sliding_view);
631 0
                    Py_DECREF(ret);
632
                    return NULL;
633
                }
634
                give_deprecation_warning = 0;
635
            }
636
            else {
637 1
                npy_set_invalid_cast_error(
638
                        PyArray_DESCR(arrays[iarrays]), PyArray_DESCR(ret),
639 1
                        casting, PyArray_NDIM(arrays[iarrays]) == 0);
640 1
                Py_DECREF(sliding_view);
641 1
                Py_DECREF(ret);
642
                return NULL;
643
            }
644
        }
645

646
        /* Copy the data for this array */
647 1
        if (PyArray_CopyAsFlat((PyArrayObject *)sliding_view, arrays[iarrays],
648
                            order) < 0) {
649 0
            Py_DECREF(sliding_view);
650 0
            Py_DECREF(ret);
651
            return NULL;
652
        }
653

654
        /* Slide to the start of the next window */
655 1
        sliding_view->data +=
656 1
            sliding_view->strides[0] * PyArray_SIZE(arrays[iarrays]);
657
    }
658

659 1
    Py_DECREF(sliding_view);
660
    return ret;
661
}
662

663

664
/**
665
 * Implementation for np.concatenate
666
 *
667
 * @param op Sequence of arrays to concatenate
668
 * @param axis Axis to concatenate along
669
 * @param ret output array to fill
670
 * @param dtype Forced output array dtype (cannot be combined with ret)
671
 * @param casting Casting mode used
672
 * @param casting_not_passed Deprecation helper
673
 */
674
NPY_NO_EXPORT PyObject *
675 1
PyArray_ConcatenateInto(PyObject *op,
676
        int axis, PyArrayObject *ret, PyArray_Descr *dtype,
677
        NPY_CASTING casting, npy_bool casting_not_passed)
678
{
679
    int iarrays, narrays;
680
    PyArrayObject **arrays;
681

682 1
    if (!PySequence_Check(op)) {
683 0
        PyErr_SetString(PyExc_TypeError,
684
                        "The first input argument needs to be a sequence");
685 0
        return NULL;
686
    }
687 1
    if (ret != NULL && dtype != NULL) {
688 1
        PyErr_SetString(PyExc_TypeError,
689
                "concatenate() only takes `out` or `dtype` as an "
690
                "argument, but both were provided.");
691 1
        return NULL;
692
    }
693

694
    /* Convert the input list into arrays */
695 1
    narrays = PySequence_Size(op);
696 1
    if (narrays < 0) {
697
        return NULL;
698
    }
699 1
    arrays = PyArray_malloc(narrays * sizeof(arrays[0]));
700 1
    if (arrays == NULL) {
701 0
        PyErr_NoMemory();
702 0
        return NULL;
703
    }
704 1
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
705 1
        PyObject *item = PySequence_GetItem(op, iarrays);
706 1
        if (item == NULL) {
707
            narrays = iarrays;
708
            goto fail;
709
        }
710 1
        arrays[iarrays] = (PyArrayObject *)PyArray_FROM_O(item);
711 1
        Py_DECREF(item);
712 1
        if (arrays[iarrays] == NULL) {
713
            narrays = iarrays;
714
            goto fail;
715
        }
716
    }
717

718 1
    if (axis >= NPY_MAXDIMS) {
719 1
        ret = PyArray_ConcatenateFlattenedArrays(
720
                narrays, arrays, NPY_CORDER, ret, dtype,
721
                casting, casting_not_passed);
722
    }
723
    else {
724 1
        ret = PyArray_ConcatenateArrays(
725
                narrays, arrays, axis, ret, dtype, casting);
726
    }
727

728 1
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
729 1
        Py_DECREF(arrays[iarrays]);
730
    }
731 1
    PyArray_free(arrays);
732

733 1
    return (PyObject *)ret;
734

735 0
fail:
736
    /* 'narrays' was set to how far we got in the conversion */
737 0
    for (iarrays = 0; iarrays < narrays; ++iarrays) {
738 0
        Py_DECREF(arrays[iarrays]);
739
    }
740 0
    PyArray_free(arrays);
741

742 0
    return NULL;
743
}
744

745
/*NUMPY_API
746
 * Concatenate
747
 *
748
 * Concatenate an arbitrary Python sequence into an array.
749
 * op is a python object supporting the sequence interface.
750
 * Its elements will be concatenated together to form a single
751
 * multidimensional array. If axis is NPY_MAXDIMS or bigger, then
752
 * each sequence object will be flattened before concatenation
753
*/
754
NPY_NO_EXPORT PyObject *
755 0
PyArray_Concatenate(PyObject *op, int axis)
756
{
757
    /* retain legacy behaviour for casting */
758
    NPY_CASTING casting;
759 0
    if (axis >= NPY_MAXDIMS) {
760
        casting = NPY_UNSAFE_CASTING;
761
    }
762
    else {
763 0
        casting = NPY_SAME_KIND_CASTING;
764
    }
765 0
    return PyArray_ConcatenateInto(
766
            op, axis, NULL, NULL, casting, 0);
767
}
768

769
static int
770
_signbit_set(PyArrayObject *arr)
771
{
772
    static char bitmask = (char) 0x80;
773
    char *ptr;  /* points to the npy_byte to test */
774
    char byteorder;
775
    int elsize;
776

777 0
    elsize = PyArray_DESCR(arr)->elsize;
778 0
    byteorder = PyArray_DESCR(arr)->byteorder;
779 0
    ptr = PyArray_DATA(arr);
780 0
    if (elsize > 1 &&
781 0
        (byteorder == NPY_LITTLE ||
782
         (byteorder == NPY_NATIVE &&
783
          PyArray_ISNBO(NPY_LITTLE)))) {
784 0
        ptr += elsize - 1;
785
    }
786 0
    return ((*ptr & bitmask) != 0);
787
}
788

789

790
/*NUMPY_API
791
 * ScalarKind
792
 *
793
 * Returns the scalar kind of a type number, with an
794
 * optional tweak based on the scalar value itself.
795
 * If no scalar is provided, it returns INTPOS_SCALAR
796
 * for both signed and unsigned integers, otherwise
797
 * it checks the sign of any signed integer to choose
798
 * INTNEG_SCALAR when appropriate.
799
 */
800
NPY_NO_EXPORT NPY_SCALARKIND
801 0
PyArray_ScalarKind(int typenum, PyArrayObject **arr)
802
{
803 0
    NPY_SCALARKIND ret = NPY_NOSCALAR;
804

805 0
    if ((unsigned int)typenum < NPY_NTYPES) {
806 0
        ret = _npy_scalar_kinds_table[typenum];
807
        /* Signed integer types are INTNEG in the table */
808 0
        if (ret == NPY_INTNEG_SCALAR) {
809 0
            if (!arr || !_signbit_set(*arr)) {
810
                ret = NPY_INTPOS_SCALAR;
811
            }
812
        }
813 0
    } else if (PyTypeNum_ISUSERDEF(typenum)) {
814 0
        PyArray_Descr* descr = PyArray_DescrFromType(typenum);
815

816 0
        if (descr->f->scalarkind) {
817 0
            ret = descr->f->scalarkind((arr ? *arr : NULL));
818
        }
819 0
        Py_DECREF(descr);
820
    }
821

822 0
    return ret;
823
}
824

825
/*NUMPY_API
826
 *
827
 * Determines whether the data type 'thistype', with
828
 * scalar kind 'scalar', can be coerced into 'neededtype'.
829
 */
830
NPY_NO_EXPORT int
831 0
PyArray_CanCoerceScalar(int thistype, int neededtype,
832
                        NPY_SCALARKIND scalar)
833
{
834
    PyArray_Descr* from;
835
    int *castlist;
836

837
    /* If 'thistype' is not a scalar, it must be safely castable */
838 0
    if (scalar == NPY_NOSCALAR) {
839 0
        return PyArray_CanCastSafely(thistype, neededtype);
840
    }
841 0
    if ((unsigned int)neededtype < NPY_NTYPES) {
842
        NPY_SCALARKIND neededscalar;
843

844 0
        if (scalar == NPY_OBJECT_SCALAR) {
845 0
            return PyArray_CanCastSafely(thistype, neededtype);
846
        }
847

848
        /*
849
         * The lookup table gives us exactly what we need for
850
         * this comparison, which PyArray_ScalarKind would not.
851
         *
852
         * The rule is that positive scalars can be coerced
853
         * to a signed ints, but negative scalars cannot be coerced
854
         * to unsigned ints.
855
         *   _npy_scalar_kinds_table[int]==NEGINT > POSINT,
856
         *      so 1 is returned, but
857
         *   _npy_scalar_kinds_table[uint]==POSINT < NEGINT,
858
         *      so 0 is returned, as required.
859
         *
860
         */
861 0
        neededscalar = _npy_scalar_kinds_table[neededtype];
862 0
        if (neededscalar >= scalar) {
863
            return 1;
864
        }
865 0
        if (!PyTypeNum_ISUSERDEF(thistype)) {
866
            return 0;
867
        }
868
    }
869

870 0
    from = PyArray_DescrFromType(thistype);
871 0
    if (from->f->cancastscalarkindto
872 0
        && (castlist = from->f->cancastscalarkindto[scalar])) {
873 0
        while (*castlist != NPY_NOTYPE) {
874 0
            if (*castlist++ == neededtype) {
875 0
                Py_DECREF(from);
876
                return 1;
877
            }
878
        }
879
    }
880 0
    Py_DECREF(from);
881

882
    return 0;
883
}
884

885
/* Could perhaps be redone to not make contiguous arrays */
886

887
/*NUMPY_API
888
 * Numeric.innerproduct(a,v)
889
 */
890
NPY_NO_EXPORT PyObject *
891 1
PyArray_InnerProduct(PyObject *op1, PyObject *op2)
892
{
893 1
    PyArrayObject *ap1 = NULL;
894 1
    PyArrayObject *ap2 = NULL;
895
    int typenum;
896 1
    PyArray_Descr *typec = NULL;
897 1
    PyObject* ap2t = NULL;
898
    npy_intp dims[NPY_MAXDIMS];
899 1
    PyArray_Dims newaxes = {dims, 0};
900
    int i;
901 1
    PyObject* ret = NULL;
902

903 1
    typenum = PyArray_ObjectType(op1, 0);
904 1
    if (typenum == NPY_NOTYPE && PyErr_Occurred()) {
905
        return NULL;
906
    }
907 1
    typenum = PyArray_ObjectType(op2, typenum);
908 1
    typec = PyArray_DescrFromType(typenum);
909 1
    if (typec == NULL) {
910 0
        if (!PyErr_Occurred()) {
911 0
            PyErr_SetString(PyExc_TypeError,
912
                            "Cannot find a common data type.");
913
        }
914
        goto fail;
915
    }
916

917 1
    Py_INCREF(typec);
918 1
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 0, 0,
919
                                           NPY_ARRAY_ALIGNED, NULL);
920 1
    if (ap1 == NULL) {
921 0
        Py_DECREF(typec);
922
        goto fail;
923
    }
924 1
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 0, 0,
925
                                           NPY_ARRAY_ALIGNED, NULL);
926 1
    if (ap2 == NULL) {
927
        goto fail;
928
    }
929

930 1
    newaxes.len = PyArray_NDIM(ap2);
931 1
    if ((PyArray_NDIM(ap1) >= 1) && (newaxes.len >= 2)) {
932 1
        for (i = 0; i < newaxes.len - 2; i++) {
933 1
            dims[i] = (npy_intp)i;
934
        }
935 1
        dims[newaxes.len - 2] = newaxes.len - 1;
936 1
        dims[newaxes.len - 1] = newaxes.len - 2;
937

938 1
        ap2t = PyArray_Transpose(ap2, &newaxes);
939 1
        if (ap2t == NULL) {
940
            goto fail;
941
        }
942
    }
943
    else {
944 1
        ap2t = (PyObject *)ap2;
945 1
        Py_INCREF(ap2);
946
    }
947

948 1
    ret = PyArray_MatrixProduct2((PyObject *)ap1, ap2t, NULL);
949 1
    if (ret == NULL) {
950
        goto fail;
951
    }
952

953

954 1
    Py_DECREF(ap1);
955 1
    Py_DECREF(ap2);
956 1
    Py_DECREF(ap2t);
957
    return ret;
958

959 1
fail:
960 1
    Py_XDECREF(ap1);
961 1
    Py_XDECREF(ap2);
962 1
    Py_XDECREF(ap2t);
963 1
    Py_XDECREF(ret);
964
    return NULL;
965
}
966

967
/*NUMPY_API
968
 * Numeric.matrixproduct(a,v)
969
 * just like inner product but does the swapaxes stuff on the fly
970
 */
971
NPY_NO_EXPORT PyObject *
972 0
PyArray_MatrixProduct(PyObject *op1, PyObject *op2)
973
{
974 0
    return PyArray_MatrixProduct2(op1, op2, NULL);
975
}
976

977
/*NUMPY_API
978
 * Numeric.matrixproduct2(a,v,out)
979
 * just like inner product but does the swapaxes stuff on the fly
980
 */
981
NPY_NO_EXPORT PyObject *
982 1
PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
983
{
984 1
    PyArrayObject *ap1, *ap2, *out_buf = NULL, *result = NULL;
985
    PyArrayIterObject *it1, *it2;
986
    npy_intp i, j, l;
987
    int typenum, nd, axis, matchDim;
988
    npy_intp is1, is2, os;
989
    char *op;
990
    npy_intp dimensions[NPY_MAXDIMS];
991
    PyArray_DotFunc *dot;
992 1
    PyArray_Descr *typec = NULL;
993 1
    NPY_BEGIN_THREADS_DEF;
994

995 1
    typenum = PyArray_ObjectType(op1, 0);
996 1
    if (typenum == NPY_NOTYPE && PyErr_Occurred()) {
997
        return NULL;
998
    }
999 1
    typenum = PyArray_ObjectType(op2, typenum);
1000 1
    typec = PyArray_DescrFromType(typenum);
1001 1
    if (typec == NULL) {
1002 0
        if (!PyErr_Occurred()) {
1003 0
            PyErr_SetString(PyExc_TypeError,
1004
                            "Cannot find a common data type.");
1005
        }
1006
        return NULL;
1007
    }
1008

1009 1
    Py_INCREF(typec);
1010 1
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 0, 0,
1011
                                        NPY_ARRAY_ALIGNED, NULL);
1012 1
    if (ap1 == NULL) {
1013 0
        Py_DECREF(typec);
1014
        return NULL;
1015
    }
1016 1
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 0, 0,
1017
                                        NPY_ARRAY_ALIGNED, NULL);
1018 1
    if (ap2 == NULL) {
1019 0
        Py_DECREF(ap1);
1020
        return NULL;
1021
    }
1022

1023
#if defined(HAVE_CBLAS)
1024 1
    if (PyArray_NDIM(ap1) <= 2 && PyArray_NDIM(ap2) <= 2 &&
1025 1
            (NPY_DOUBLE == typenum || NPY_CDOUBLE == typenum ||
1026 1
             NPY_FLOAT == typenum || NPY_CFLOAT == typenum)) {
1027 1
        return cblas_matrixproduct(typenum, ap1, ap2, out);
1028
    }
1029
#endif
1030

1031 1
    if (PyArray_NDIM(ap1) == 0 || PyArray_NDIM(ap2) == 0) {
1032 1
        result = (PyArray_NDIM(ap1) == 0 ? ap1 : ap2);
1033 1
        result = (PyArrayObject *)Py_TYPE(result)->tp_as_number->nb_multiply(
1034
                                        (PyObject *)ap1, (PyObject *)ap2);
1035 1
        Py_DECREF(ap1);
1036 1
        Py_DECREF(ap2);
1037 1
        return (PyObject *)result;
1038
    }
1039 1
    l = PyArray_DIMS(ap1)[PyArray_NDIM(ap1) - 1];
1040 1
    if (PyArray_NDIM(ap2) > 1) {
1041 1
        matchDim = PyArray_NDIM(ap2) - 2;
1042
    }
1043
    else {
1044 1
        matchDim = 0;
1045
    }
1046 1
    if (PyArray_DIMS(ap2)[matchDim] != l) {
1047 0
        dot_alignment_error(ap1, PyArray_NDIM(ap1) - 1, ap2, matchDim);
1048 0
        goto fail;
1049
    }
1050 1
    nd = PyArray_NDIM(ap1) + PyArray_NDIM(ap2) - 2;
1051 1
    if (nd > NPY_MAXDIMS) {
1052 0
        PyErr_SetString(PyExc_ValueError, "dot: too many dimensions in result");
1053 0
        goto fail;
1054
    }
1055
    j = 0;
1056 1
    for (i = 0; i < PyArray_NDIM(ap1) - 1; i++) {
1057 1
        dimensions[j++] = PyArray_DIMS(ap1)[i];
1058
    }
1059 1
    for (i = 0; i < PyArray_NDIM(ap2) - 2; i++) {
1060 1
        dimensions[j++] = PyArray_DIMS(ap2)[i];
1061
    }
1062 1
    if (PyArray_NDIM(ap2) > 1) {
1063 1
        dimensions[j++] = PyArray_DIMS(ap2)[PyArray_NDIM(ap2)-1];
1064
    }
1065

1066 1
    is1 = PyArray_STRIDES(ap1)[PyArray_NDIM(ap1)-1];
1067 1
    is2 = PyArray_STRIDES(ap2)[matchDim];
1068
    /* Choose which subtype to return */
1069 1
    out_buf = new_array_for_sum(ap1, ap2, out, nd, dimensions, typenum, &result);
1070 1
    if (out_buf == NULL) {
1071
        goto fail;
1072
    }
1073
    /* Ensure that multiarray.dot(<Nx0>,<0xM>) -> zeros((N,M)) */
1074 1
    if (PyArray_SIZE(ap1) == 0 && PyArray_SIZE(ap2) == 0) {
1075 1
        memset(PyArray_DATA(out_buf), 0, PyArray_NBYTES(out_buf));
1076
    }
1077

1078 1
    dot = PyArray_DESCR(out_buf)->f->dotfunc;
1079 1
    if (dot == NULL) {
1080 0
        PyErr_SetString(PyExc_ValueError,
1081
                        "dot not available for this type");
1082 0
        goto fail;
1083
    }
1084

1085 1
    op = PyArray_DATA(out_buf);
1086 1
    os = PyArray_DESCR(out_buf)->elsize;
1087 1
    axis = PyArray_NDIM(ap1)-1;
1088 1
    it1 = (PyArrayIterObject *)
1089
        PyArray_IterAllButAxis((PyObject *)ap1, &axis);
1090 1
    if (it1 == NULL) {
1091
        goto fail;
1092
    }
1093 1
    it2 = (PyArrayIterObject *)
1094
        PyArray_IterAllButAxis((PyObject *)ap2, &matchDim);
1095 1
    if (it2 == NULL) {
1096 0
        Py_DECREF(it1);
1097
        goto fail;
1098
    }
1099 1
    NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ap2));
1100 1
    while (it1->index < it1->size) {
1101 1
        while (it2->index < it2->size) {
1102 1
            dot(it1->dataptr, is1, it2->dataptr, is2, op, l, NULL);
1103 1
            op += os;
1104 1
            PyArray_ITER_NEXT(it2);
1105
        }
1106 1
        PyArray_ITER_NEXT(it1);
1107 1
        PyArray_ITER_RESET(it2);
1108
    }
1109 1
    NPY_END_THREADS_DESCR(PyArray_DESCR(ap2));
1110 1
    Py_DECREF(it1);
1111 1
    Py_DECREF(it2);
1112 1
    if (PyErr_Occurred()) {
1113
        /* only for OBJECT arrays */
1114
        goto fail;
1115
    }
1116 1
    Py_DECREF(ap1);
1117 1
    Py_DECREF(ap2);
1118

1119
    /* Trigger possible copy-back into `result` */
1120 1
    PyArray_ResolveWritebackIfCopy(out_buf);
1121 1
    Py_DECREF(out_buf);
1122

1123 1
    return (PyObject *)result;
1124

1125 1
fail:
1126 1
    Py_XDECREF(ap1);
1127 1
    Py_XDECREF(ap2);
1128 1
    Py_XDECREF(out_buf);
1129 1
    Py_XDECREF(result);
1130
    return NULL;
1131
}
1132

1133

1134
/*NUMPY_API
1135
 * Copy and Transpose
1136
 *
1137
 * Could deprecate this function, as there isn't a speed benefit over
1138
 * calling Transpose and then Copy.
1139
 */
1140
NPY_NO_EXPORT PyObject *
1141 1
PyArray_CopyAndTranspose(PyObject *op)
1142
{
1143
    PyArrayObject *arr, *tmp, *ret;
1144
    int i;
1145
    npy_intp new_axes_values[NPY_MAXDIMS];
1146
    PyArray_Dims new_axes;
1147

1148
    /* Make sure we have an array */
1149 1
    arr = (PyArrayObject *)PyArray_FROM_O(op);
1150 1
    if (arr == NULL) {
1151
        return NULL;
1152
    }
1153

1154 1
    if (PyArray_NDIM(arr) > 1) {
1155
        /* Set up the transpose operation */
1156 1
        new_axes.len = PyArray_NDIM(arr);
1157 1
        for (i = 0; i < new_axes.len; ++i) {
1158 1
            new_axes_values[i] = new_axes.len - i - 1;
1159
        }
1160 1
        new_axes.ptr = new_axes_values;
1161

1162
        /* Do the transpose (always returns a view) */
1163 1
        tmp = (PyArrayObject *)PyArray_Transpose(arr, &new_axes);
1164 1
        if (tmp == NULL) {
1165 0
            Py_DECREF(arr);
1166
            return NULL;
1167
        }
1168
    }
1169
    else {
1170
        tmp = arr;
1171
        arr = NULL;
1172
    }
1173

1174
    /* TODO: Change this to NPY_KEEPORDER for NumPy 2.0 */
1175 1
    ret = (PyArrayObject *)PyArray_NewCopy(tmp, NPY_CORDER);
1176

1177 1
    Py_XDECREF(arr);
1178 1
    Py_DECREF(tmp);
1179
    return (PyObject *)ret;
1180
}
1181

1182
/*
1183
 * Implementation which is common between PyArray_Correlate
1184
 * and PyArray_Correlate2.
1185
 *
1186
 * inverted is set to 1 if computed correlate(ap2, ap1), 0 otherwise
1187
 */
1188
static PyArrayObject*
1189 1
_pyarray_correlate(PyArrayObject *ap1, PyArrayObject *ap2, int typenum,
1190
                   int mode, int *inverted)
1191
{
1192
    PyArrayObject *ret;
1193
    npy_intp length;
1194
    npy_intp i, n1, n2, n, n_left, n_right;
1195
    npy_intp is1, is2, os;
1196
    char *ip1, *ip2, *op;
1197
    PyArray_DotFunc *dot;
1198

1199 1
    NPY_BEGIN_THREADS_DEF;
1200

1201 1
    n1 = PyArray_DIMS(ap1)[0];
1202 1
    n2 = PyArray_DIMS(ap2)[0];
1203 1
    if (n1 == 0) {
1204 1
        PyErr_SetString(PyExc_ValueError, "first array argument cannot be empty");
1205 1
        return NULL;
1206
    }
1207 1
    if (n2 == 0) {
1208 1
        PyErr_SetString(PyExc_ValueError, "second array argument cannot be empty");
1209 1
        return NULL;
1210
    }
1211 1
    if (n1 < n2) {
1212 1
        ret = ap1;
1213 1
        ap1 = ap2;
1214 1
        ap2 = ret;
1215 1
        ret = NULL;
1216 1
        i = n1;
1217 1
        n1 = n2;
1218 1
        n2 = i;
1219 1
        *inverted = 1;
1220
    } else {
1221 1
        *inverted = 0;
1222
    }
1223

1224 1
    length = n1;
1225 1
    n = n2;
1226 1
    switch(mode) {
1227 1
    case 0:
1228 1
        length = length - n + 1;
1229 1
        n_left = n_right = 0;
1230 1
        break;
1231 0
    case 1:
1232 0
        n_left = (npy_intp)(n/2);
1233 0
        n_right = n - n_left - 1;
1234 0
        break;
1235 1
    case 2:
1236 1
        n_right = n - 1;
1237 1
        n_left = n - 1;
1238 1
        length = length + n - 1;
1239 1
        break;
1240 0
    default:
1241 0
        PyErr_SetString(PyExc_ValueError, "mode must be 0, 1, or 2");
1242 0
        return NULL;
1243
    }
1244

1245
    /*
1246
     * Need to choose an output array that can hold a sum
1247
     * -- use priority to determine which subtype.
1248
     */
1249 1
    ret = new_array_for_sum(ap1, ap2, NULL, 1, &length, typenum, NULL);
1250 1
    if (ret == NULL) {
1251
        return NULL;
1252
    }
1253 1
    dot = PyArray_DESCR(ret)->f->dotfunc;
1254 1
    if (dot == NULL) {
1255 0
        PyErr_SetString(PyExc_ValueError,
1256
                        "function not available for this data type");
1257 0
        goto clean_ret;
1258
    }
1259

1260 1
    NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ret));
1261 1
    is1 = PyArray_STRIDES(ap1)[0];
1262 1
    is2 = PyArray_STRIDES(ap2)[0];
1263 1
    op = PyArray_DATA(ret);
1264 1
    os = PyArray_DESCR(ret)->elsize;
1265 1
    ip1 = PyArray_DATA(ap1);
1266 1
    ip2 = PyArray_BYTES(ap2) + n_left*is2;
1267 1
    n = n - n_left;
1268 1
    for (i = 0; i < n_left; i++) {
1269 1
        dot(ip1, is1, ip2, is2, op, n, ret);
1270 1
        n++;
1271 1
        ip2 -= is2;
1272 1
        op += os;
1273
    }
1274 1
    if (small_correlate(ip1, is1, n1 - n2 + 1, PyArray_TYPE(ap1),
1275 1
                        ip2, is2, n, PyArray_TYPE(ap2),
1276
                        op, os)) {
1277 1
        ip1 += is1 * (n1 - n2 + 1);
1278 1
        op += os * (n1 - n2 + 1);
1279
    }
1280
    else {
1281 1
        for (i = 0; i < (n1 - n2 + 1); i++) {
1282 1
            dot(ip1, is1, ip2, is2, op, n, ret);
1283 1
            ip1 += is1;
1284 1
            op += os;
1285
        }
1286
    }
1287 1
    for (i = 0; i < n_right; i++) {
1288 1
        n--;
1289 1
        dot(ip1, is1, ip2, is2, op, n, ret);
1290 1
        ip1 += is1;
1291 1
        op += os;
1292
    }
1293

1294 1
    NPY_END_THREADS_DESCR(PyArray_DESCR(ret));
1295 1
    if (PyErr_Occurred()) {
1296
        goto clean_ret;
1297
    }
1298

1299
    return ret;
1300

1301 0
clean_ret:
1302 0
    Py_DECREF(ret);
1303
    return NULL;
1304
}
1305

1306
/*
1307
 * Revert a one dimensional array in-place
1308
 *
1309
 * Return 0 on success, other value on failure
1310
 */
1311
static int
1312 1
_pyarray_revert(PyArrayObject *ret)
1313
{
1314 1
    npy_intp length = PyArray_DIM(ret, 0);
1315 1
    npy_intp os = PyArray_DESCR(ret)->elsize;
1316 1
    char *op = PyArray_DATA(ret);
1317 1
    char *sw1 = op;
1318
    char *sw2;
1319

1320 1
    if (PyArray_ISNUMBER(ret) && !PyArray_ISCOMPLEX(ret)) {
1321
        /* Optimization for unstructured dtypes */
1322 1
        PyArray_CopySwapNFunc *copyswapn = PyArray_DESCR(ret)->f->copyswapn;
1323 1
        sw2 = op + length * os - 1;
1324
        /* First reverse the whole array byte by byte... */
1325 1
        while(sw1 < sw2) {
1326 1
            const char tmp = *sw1;
1327 1
            *sw1++ = *sw2;
1328 1
            *sw2-- = tmp;
1329
        }
1330
        /* ...then swap in place every item */
1331 1
        copyswapn(op, os, NULL, 0, length, 1, NULL);
1332
    }
1333
    else {
1334 1
        char *tmp = PyArray_malloc(PyArray_DESCR(ret)->elsize);
1335 1
        if (tmp == NULL) {
1336 0
            PyErr_NoMemory();
1337 0
            return -1;
1338
        }
1339 1
        sw2 = op + (length - 1) * os;
1340 1
        while (sw1 < sw2) {
1341 1
            memcpy(tmp, sw1, os);
1342 1
            memcpy(sw1, sw2, os);
1343 1
            memcpy(sw2, tmp, os);
1344 1
            sw1 += os;
1345 1
            sw2 -= os;
1346
        }
1347 1
        PyArray_free(tmp);
1348
    }
1349

1350
    return 0;
1351
}
1352

1353
/*NUMPY_API
1354
 * correlate(a1,a2,mode)
1355
 *
1356
 * This function computes the usual correlation (correlate(a1, a2) !=
1357
 * correlate(a2, a1), and conjugate the second argument for complex inputs
1358
 */
1359
NPY_NO_EXPORT PyObject *
1360 1
PyArray_Correlate2(PyObject *op1, PyObject *op2, int mode)
1361
{
1362 1
    PyArrayObject *ap1, *ap2, *ret = NULL;
1363
    int typenum;
1364
    PyArray_Descr *typec;
1365
    int inverted;
1366
    int st;
1367

1368 1
    typenum = PyArray_ObjectType(op1, 0);
1369 1
    typenum = PyArray_ObjectType(op2, typenum);
1370

1371 1
    typec = PyArray_DescrFromType(typenum);
1372 1
    Py_INCREF(typec);
1373 1
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 1, 1,
1374
                                        NPY_ARRAY_DEFAULT, NULL);
1375 1
    if (ap1 == NULL) {
1376 0
        Py_DECREF(typec);
1377
        return NULL;
1378
    }
1379 1
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 1, 1,
1380
                                        NPY_ARRAY_DEFAULT, NULL);
1381 1
    if (ap2 == NULL) {
1382
        goto clean_ap1;
1383
    }
1384

1385 1
    if (PyArray_ISCOMPLEX(ap2)) {
1386
        PyArrayObject *cap2;
1387 1
        cap2 = (PyArrayObject *)PyArray_Conjugate(ap2, NULL);
1388 1
        if (cap2 == NULL) {
1389
            goto clean_ap2;
1390
        }
1391 1
        Py_DECREF(ap2);
1392
        ap2 = cap2;
1393
    }
1394

1395 1
    ret = _pyarray_correlate(ap1, ap2, typenum, mode, &inverted);
1396 1
    if (ret == NULL) {
1397
        goto clean_ap2;
1398
    }
1399

1400
    /*
1401
     * If we inverted input orders, we need to reverse the output array (i.e.
1402
     * ret = ret[::-1])
1403
     */
1404 1
    if (inverted) {
1405 1
        st = _pyarray_revert(ret);
1406 1
        if (st) {
1407
            goto clean_ret;
1408
        }
1409
    }
1410

1411 1
    Py_DECREF(ap1);
1412 1
    Py_DECREF(ap2);
1413
    return (PyObject *)ret;
1414

1415 0
clean_ret:
1416 0
    Py_DECREF(ret);
1417 1
clean_ap2:
1418 1
    Py_DECREF(ap2);
1419 1
clean_ap1:
1420 1
    Py_DECREF(ap1);
1421
    return NULL;
1422
}
1423

1424
/*NUMPY_API
1425
 * Numeric.correlate(a1,a2,mode)
1426
 */
1427
NPY_NO_EXPORT PyObject *
1428 1
PyArray_Correlate(PyObject *op1, PyObject *op2, int mode)
1429
{
1430 1
    PyArrayObject *ap1, *ap2, *ret = NULL;
1431
    int typenum;
1432
    int unused;
1433
    PyArray_Descr *typec;
1434

1435 1
    typenum = PyArray_ObjectType(op1, 0);
1436 1
    typenum = PyArray_ObjectType(op2, typenum);
1437

1438 1
    typec = PyArray_DescrFromType(typenum);
1439 1
    Py_INCREF(typec);
1440 1
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, typec, 1, 1,
1441
                                            NPY_ARRAY_DEFAULT, NULL);
1442 1
    if (ap1 == NULL) {
1443 0
        Py_DECREF(typec);
1444
        return NULL;
1445
    }
1446 1
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, typec, 1, 1,
1447
                                           NPY_ARRAY_DEFAULT, NULL);
1448 1
    if (ap2 == NULL) {
1449
        goto fail;
1450
    }
1451

1452 1
    ret = _pyarray_correlate(ap1, ap2, typenum, mode, &unused);
1453 1
    if (ret == NULL) {
1454
        goto fail;
1455
    }
1456 1
    Py_DECREF(ap1);
1457 1
    Py_DECREF(ap2);
1458
    return (PyObject *)ret;
1459

1460 0
fail:
1461 0
    Py_XDECREF(ap1);
1462 0
    Py_XDECREF(ap2);
1463 0
    Py_XDECREF(ret);
1464
    return NULL;
1465
}
1466

1467

1468
static PyObject *
1469 1
array_putmask(PyObject *NPY_UNUSED(module), PyObject *args, PyObject *kwds)
1470
{
1471
    PyObject *mask, *values;
1472
    PyObject *array;
1473

1474
    static char *kwlist[] = {"arr", "mask", "values", NULL};
1475

1476 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!OO:putmask", kwlist,
1477
                &PyArray_Type, &array, &mask, &values)) {
1478
        return NULL;
1479
    }
1480 1
    return PyArray_PutMask((PyArrayObject *)array, values, mask);
1481
}
1482

1483
/*
1484
 * Compare the field dictionaries for two types.
1485
 *
1486
 * Return 1 if the field types and field names of the two descrs are equal and
1487
 * in the same order, 0 if not.
1488
 */
1489
static int
1490 1
_equivalent_fields(PyArray_Descr *type1, PyArray_Descr *type2) {
1491

1492
    int val;
1493

1494 1
    if (type1->fields == type2->fields && type1->names == type2->names) {
1495
        return 1;
1496
    }
1497 1
    if (type1->fields == NULL || type2->fields == NULL) {
1498
        return 0;
1499
    }
1500

1501 1
    val = PyObject_RichCompareBool(type1->fields, type2->fields, Py_EQ);
1502 1
    if (val != 1 || PyErr_Occurred()) {
1503 1
        PyErr_Clear();
1504
        return 0;
1505
    }
1506

1507 1
    val = PyObject_RichCompareBool(type1->names, type2->names, Py_EQ);
1508 1
    if (val != 1 || PyErr_Occurred()) {
1509 1
        PyErr_Clear();
1510
        return 0;
1511
    }
1512

1513
    return 1;
1514
}
1515

1516
/*
1517
 * Compare the subarray data for two types.
1518
 * Return 1 if they are the same, 0 if not.
1519
 */
1520
static int
1521 1
_equivalent_subarrays(PyArray_ArrayDescr *sub1, PyArray_ArrayDescr *sub2)
1522
{
1523
    int val;
1524

1525 1
    if (sub1 == sub2) {
1526
        return 1;
1527

1528
    }
1529 1
    if (sub1 == NULL || sub2 == NULL) {
1530
        return 0;
1531
    }
1532

1533 1
    val = PyObject_RichCompareBool(sub1->shape, sub2->shape, Py_EQ);
1534 1
    if (val != 1 || PyErr_Occurred()) {
1535 1
        PyErr_Clear();
1536 1
        return 0;
1537
    }
1538

1539 1
    return PyArray_EquivTypes(sub1->base, sub2->base);
1540
}
1541

1542

1543
/*NUMPY_API
1544
 *
1545
 * This function returns true if the two typecodes are
1546
 * equivalent (same basic kind and same itemsize).
1547
 */
1548
NPY_NO_EXPORT unsigned char
1549 1
PyArray_EquivTypes(PyArray_Descr *type1, PyArray_Descr *type2)
1550
{
1551
    int type_num1, type_num2, size1, size2;
1552

1553 1
    if (type1 == type2) {
1554
        return NPY_TRUE;
1555
    }
1556

1557 1
    type_num1 = type1->type_num;
1558 1
    type_num2 = type2->type_num;
1559 1
    size1 = type1->elsize;
1560 1
    size2 = type2->elsize;
1561

1562 1
    if (size1 != size2) {
1563
        return NPY_FALSE;
1564
    }
1565 1
    if (PyArray_ISNBO(type1->byteorder) != PyArray_ISNBO(type2->byteorder)) {
1566
        return NPY_FALSE;
1567
    }
1568 1
    if (type1->subarray || type2->subarray) {
1569
        return ((type_num1 == type_num2)
1570 1
                && _equivalent_subarrays(type1->subarray, type2->subarray));
1571
    }
1572 1
    if (type_num1 == NPY_VOID || type_num2 == NPY_VOID) {
1573 1
        return ((type_num1 == type_num2) && _equivalent_fields(type1, type2));
1574
    }
1575 1
    if (type_num1 == NPY_DATETIME
1576 1
            || type_num1 == NPY_TIMEDELTA
1577
            || type_num2 == NPY_DATETIME
1578 1
            || type_num2 == NPY_TIMEDELTA) {
1579
        return ((type_num1 == type_num2)
1580 1
                && has_equivalent_datetime_metadata(type1, type2));
1581
    }
1582 1
    return type1->kind == type2->kind;
1583
}
1584

1585
/*NUMPY_API*/
1586
NPY_NO_EXPORT unsigned char
1587 1
PyArray_EquivTypenums(int typenum1, int typenum2)
1588
{
1589
    PyArray_Descr *d1, *d2;
1590
    npy_bool ret;
1591

1592 1
    if (typenum1 == typenum2) {
1593
        return NPY_SUCCEED;
1594
    }
1595

1596 1
    d1 = PyArray_DescrFromType(typenum1);
1597 1
    d2 = PyArray_DescrFromType(typenum2);
1598 1
    ret = PyArray_EquivTypes(d1, d2);
1599 1
    Py_DECREF(d1);
1600 1
    Py_DECREF(d2);
1601
    return ret;
1602
}
1603

1604
/*** END C-API FUNCTIONS **/
1605
/*
1606
 * NPY_RELAXED_STRIDES_CHECKING: If the strides logic is changed, the
1607
 * order specific stride setting is not necessary.
1608
 */
1609
static NPY_STEALS_REF_TO_ARG(1) PyObject *
1610 1
_prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order)
1611
{
1612
    npy_intp newdims[NPY_MAXDIMS];
1613
    npy_intp newstrides[NPY_MAXDIMS];
1614
    npy_intp newstride;
1615
    int i, k, num;
1616
    PyObject *ret;
1617
    PyArray_Descr *dtype;
1618

1619 1
    if (order == NPY_FORTRANORDER || PyArray_ISFORTRAN(arr) || PyArray_NDIM(arr) == 0) {
1620 1
        newstride = PyArray_DESCR(arr)->elsize;
1621
    }
1622
    else {
1623 1
        newstride = PyArray_STRIDES(arr)[0] * PyArray_DIMS(arr)[0];
1624
    }
1625

1626 1
    num = ndmin - nd;
1627 1
    for (i = 0; i < num; i++) {
1628 1
        newdims[i] = 1;
1629 1
        newstrides[i] = newstride;
1630
    }
1631 1
    for (i = num; i < ndmin; i++) {
1632 1
        k = i - num;
1633 1
        newdims[i] = PyArray_DIMS(arr)[k];
1634 1
        newstrides[i] = PyArray_STRIDES(arr)[k];
1635
    }
1636 1
    dtype = PyArray_DESCR(arr);
1637 1
    Py_INCREF(dtype);
1638 1
    ret = PyArray_NewFromDescrAndBase(
1639 1
            Py_TYPE(arr), dtype,
1640
            ndmin, newdims, newstrides, PyArray_DATA(arr),
1641
            PyArray_FLAGS(arr), (PyObject *)arr, (PyObject *)arr);
1642 1
    Py_DECREF(arr);
1643

1644 1
    return ret;
1645
}
1646

1647
#define STRIDING_OK(op, order) \
1648
                ((order) == NPY_ANYORDER || \
1649
                 (order) == NPY_KEEPORDER || \
1650
                 ((order) == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(op)) || \
1651
                 ((order) == NPY_FORTRANORDER && PyArray_IS_F_CONTIGUOUS(op)))
1652

1653
static PyObject *
1654 1
_array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
1655
{
1656
    PyObject *op;
1657 1
    PyArrayObject *oparr = NULL, *ret = NULL;
1658 1
    npy_bool subok = NPY_FALSE;
1659 1
    npy_bool copy = NPY_TRUE;
1660 1
    int ndmin = 0, nd;
1661
    PyObject* like;
1662 1
    PyArray_Descr *type = NULL;
1663 1
    PyArray_Descr *oldtype = NULL;
1664 1
    NPY_ORDER order = NPY_KEEPORDER;
1665 1
    int flags = 0;
1666

1667 1
    PyObject* array_function_result = NULL;
1668

1669
    static char *kwd[] = {"object", "dtype", "copy", "order", "subok",
1670
                          "ndmin", "like", NULL};
1671

1672 1
    if (PyTuple_GET_SIZE(args) > 2) {
1673 0
        PyErr_Format(PyExc_TypeError,
1674
                     "array() takes from 1 to 2 positional arguments but "
1675
                     "%zd were given", PyTuple_GET_SIZE(args));
1676 0
        return NULL;
1677
    }
1678

1679 1
    array_function_result = array_implement_c_array_function_creation(
1680
            "array", args, kws);
1681 1
    if (array_function_result != Py_NotImplemented) {
1682
        return array_function_result;
1683
    }
1684

1685
    /* super-fast path for ndarray argument calls */
1686 1
    if (PyTuple_GET_SIZE(args) == 0) {
1687
        goto full_path;
1688
    }
1689 1
    op = PyTuple_GET_ITEM(args, 0);
1690 1
    if (PyArray_CheckExact(op)) {
1691 1
        PyObject * dtype_obj = Py_None;
1692 1
        oparr = (PyArrayObject *)op;
1693
        /* get dtype which can be positional */
1694 1
        if (PyTuple_GET_SIZE(args) == 2) {
1695 1
            dtype_obj = PyTuple_GET_ITEM(args, 1);
1696
        }
1697 1
        else if (kws) {
1698 1
            dtype_obj = PyDict_GetItemWithError(kws, npy_ma_str_dtype);
1699 1
            if (dtype_obj == NULL && PyErr_Occurred()) {
1700
                return NULL;
1701
            }
1702 1
            if (dtype_obj == NULL) {
1703 1
                dtype_obj = Py_None;
1704
            }
1705
        }
1706 1
        if (dtype_obj != Py_None) {
1707
            goto full_path;
1708
        }
1709

1710
        /* array(ndarray) */
1711 1
        if (kws == NULL) {
1712 1
            ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1713 1
            goto finish;
1714
        }
1715
        else {
1716
            /* fast path for copy=False rest default (np.asarray) */
1717
            PyObject * copy_obj, * order_obj, *ndmin_obj;
1718 1
            copy_obj = PyDict_GetItemWithError(kws, npy_ma_str_copy);
1719 1
            if (copy_obj == NULL && PyErr_Occurred()) {
1720
                return NULL;
1721
            }
1722 1
            if (copy_obj != Py_False) {
1723
                goto full_path;
1724
            }
1725 1
            copy = NPY_FALSE;
1726

1727
            /* order does not matter for contiguous 1d arrays */
1728 1
            if (PyArray_NDIM((PyArrayObject*)op) > 1 ||
1729 1
                !PyArray_IS_C_CONTIGUOUS((PyArrayObject*)op)) {
1730 1
                order_obj = PyDict_GetItemWithError(kws, npy_ma_str_order);
1731 1
                if (order_obj == NULL && PyErr_Occurred()) {
1732
                    return NULL;
1733
                }
1734 1
                else if (order_obj != Py_None && order_obj != NULL) {
1735
                    goto full_path;
1736
                }
1737
            }
1738

1739 1
            ndmin_obj = PyDict_GetItemWithError(kws, npy_ma_str_ndmin);
1740 1
            if (ndmin_obj == NULL && PyErr_Occurred()) {
1741
                return NULL;
1742
            }
1743 1
            else if (ndmin_obj) {
1744 1
                long t = PyLong_AsLong(ndmin_obj);
1745 1
                if (error_converting(t)) {
1746
                    goto clean_type;
1747
                }
1748 1
                else if (t > NPY_MAXDIMS) {
1749
                    goto full_path;
1750
                }
1751 1
                ndmin = t;
1752
            }
1753

1754
            /* copy=False with default dtype, order (any is OK) and ndim */
1755 1
            ret = oparr;
1756 1
            Py_INCREF(ret);
1757 1
            goto finish;
1758
        }
1759
    }
1760

1761 1
full_path:
1762 1
    if (!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i$O:array", kwd,
1763
                &op,
1764
                PyArray_DescrConverter2, &type,
1765
                PyArray_BoolConverter, &copy,
1766
                PyArray_OrderConverter, &order,
1767
                PyArray_BoolConverter, &subok,
1768
                &ndmin,
1769
                &like)) {
1770
        goto clean_type;
1771
    }
1772

1773 1
    if (ndmin > NPY_MAXDIMS) {
1774 1
        PyErr_Format(PyExc_ValueError,
1775
                "ndmin bigger than allowable number of dimensions "
1776
                "NPY_MAXDIMS (=%d)", NPY_MAXDIMS);
1777 1
        goto clean_type;
1778
    }
1779
    /* fast exit if simple call */
1780 1
    if ((subok && PyArray_Check(op)) ||
1781 1
        (!subok && PyArray_CheckExact(op))) {
1782 1
        oparr = (PyArrayObject *)op;
1783 1
        if (type == NULL) {
1784 1
            if (!copy && STRIDING_OK(oparr, order)) {
1785 1
                ret = oparr;
1786 1
                Py_INCREF(ret);
1787 1
                goto finish;
1788
            }
1789
            else {
1790 1
                ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1791 1
                goto finish;
1792
            }
1793
        }
1794
        /* One more chance */
1795 1
        oldtype = PyArray_DESCR(oparr);
1796 1
        if (PyArray_EquivTypes(oldtype, type)) {
1797 1
            if (!copy && STRIDING_OK(oparr, order)) {
1798 1
                Py_INCREF(op);
1799 1
                ret = oparr;
1800 1
                goto finish;
1801
            }
1802
            else {
1803 1
                ret = (PyArrayObject *)PyArray_NewCopy(oparr, order);
1804 1
                if (oldtype == type || ret == NULL) {
1805
                    goto finish;
1806
                }
1807 1
                Py_INCREF(oldtype);
1808 1
                Py_DECREF(PyArray_DESCR(ret));
1809 1
                ((PyArrayObject_fields *)ret)->descr = oldtype;
1810 1
                goto finish;
1811
            }
1812
        }
1813
    }
1814

1815 1
    if (copy) {
1816 1
        flags = NPY_ARRAY_ENSURECOPY;
1817
    }
1818 1
    if (order == NPY_CORDER) {
1819 1
        flags |= NPY_ARRAY_C_CONTIGUOUS;
1820
    }
1821 1
    else if ((order == NPY_FORTRANORDER)
1822
                 /* order == NPY_ANYORDER && */
1823 1
                 || (PyArray_Check(op) &&
1824 1
                     PyArray_ISFORTRAN((PyArrayObject *)op))) {
1825 1
        flags |= NPY_ARRAY_F_CONTIGUOUS;
1826
    }
1827 1
    if (!subok) {
1828 1
        flags |= NPY_ARRAY_ENSUREARRAY;
1829
    }
1830

1831 1
    flags |= NPY_ARRAY_FORCECAST;
1832 1
    Py_XINCREF(type);
1833 1
    ret = (PyArrayObject *)PyArray_CheckFromAny(op, type,
1834
                                                0, 0, flags, NULL);
1835

1836 1
 finish:
1837 1
    Py_XDECREF(type);
1838 1
    if (ret == NULL) {
1839
        return NULL;
1840
    }
1841

1842 1
    nd = PyArray_NDIM(ret);
1843 1
    if (nd >= ndmin) {
1844
        return (PyObject *)ret;
1845
    }
1846
    /*
1847
     * create a new array from the same data with ones in the shape
1848
     * steals a reference to ret
1849
     */
1850 1
    return _prepend_ones(ret, nd, ndmin, order);
1851

1852 1
clean_type:
1853 1
    Py_XDECREF(type);
1854
    return NULL;
1855
}
1856

1857
static PyObject *
1858 1
array_copyto(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1859
{
1860

1861
    static char *kwlist[] = {"dst", "src", "casting", "where", NULL};
1862 1
    PyObject *wheremask_in = NULL;
1863 1
    PyArrayObject *dst = NULL, *src = NULL, *wheremask = NULL;
1864 1
    NPY_CASTING casting = NPY_SAME_KIND_CASTING;
1865

1866 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&|O&O:copyto", kwlist,
1867
                &PyArray_Type, &dst,
1868
                &PyArray_Converter, &src,
1869
                &PyArray_CastingConverter, &casting,
1870
                &wheremask_in)) {
1871
        goto fail;
1872
    }
1873

1874 1
    if (wheremask_in != NULL) {
1875
        /* Get the boolean where mask */
1876 1
        PyArray_Descr *dtype = PyArray_DescrFromType(NPY_BOOL);
1877 1
        if (dtype == NULL) {
1878
            goto fail;
1879
        }
1880 1
        wheremask = (PyArrayObject *)PyArray_FromAny(wheremask_in,
1881
                                        dtype, 0, 0, 0, NULL);
1882 1
        if (wheremask == NULL) {
1883
            goto fail;
1884
        }
1885
    }
1886

1887 1
    if (PyArray_AssignArray(dst, src, wheremask, casting) < 0) {
1888
        goto fail;
1889
    }
1890

1891 1
    Py_XDECREF(src);
1892 1
    Py_XDECREF(wheremask);
1893

1894 1
    Py_RETURN_NONE;
1895

1896 1
fail:
1897 1
    Py_XDECREF(src);
1898 1
    Py_XDECREF(wheremask);
1899
    return NULL;
1900
}
1901

1902
static PyObject *
1903 1
array_empty(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1904
{
1905

1906
    static char *kwlist[] = {"shape", "dtype", "order", "like", NULL};
1907 1
    PyArray_Descr *typecode = NULL;
1908 1
    PyArray_Dims shape = {NULL, 0};
1909 1
    NPY_ORDER order = NPY_CORDER;
1910 1
    PyObject *like = NULL;
1911
    npy_bool is_f_order;
1912 1
    PyObject *array_function_result = NULL;
1913 1
    PyArrayObject *ret = NULL;
1914

1915 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&$O:empty", kwlist,
1916
                PyArray_IntpConverter, &shape,
1917
                PyArray_DescrConverter, &typecode,
1918
                PyArray_OrderConverter, &order,
1919
                &like)) {
1920
        goto fail;
1921
    }
1922

1923 1
    array_function_result = array_implement_c_array_function_creation(
1924
            "empty", args, kwds);
1925 1
    if (array_function_result != Py_NotImplemented) {
1926
        return array_function_result;
1927
    }
1928

1929 1
    switch (order) {
1930
        case NPY_CORDER:
1931
            is_f_order = NPY_FALSE;
1932
            break;
1933 1
        case NPY_FORTRANORDER:
1934 1
            is_f_order = NPY_TRUE;
1935 1
            break;
1936 1
        default:
1937 1
            PyErr_SetString(PyExc_ValueError,
1938
                            "only 'C' or 'F' order is permitted");
1939 1
            goto fail;
1940
    }
1941

1942 1
    ret = (PyArrayObject *)PyArray_Empty(shape.len, shape.ptr,
1943
                                            typecode, is_f_order);
1944

1945 1
    npy_free_cache_dim_obj(shape);
1946 1
    return (PyObject *)ret;
1947

1948 1
fail:
1949 1
    Py_XDECREF(typecode);
1950 1
    npy_free_cache_dim_obj(shape);
1951 1
    return NULL;
1952
}
1953

1954
static PyObject *
1955 1
array_empty_like(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1956
{
1957

1958
    static char *kwlist[] = {"prototype", "dtype", "order", "subok", "shape", NULL};
1959 1
    PyArrayObject *prototype = NULL;
1960 1
    PyArray_Descr *dtype = NULL;
1961 1
    NPY_ORDER order = NPY_KEEPORDER;
1962 1
    PyArrayObject *ret = NULL;
1963 1
    int subok = 1;
1964
    /* -1 is a special value meaning "not specified" */
1965 1
    PyArray_Dims shape = {NULL, -1};
1966

1967 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&iO&:empty_like", kwlist,
1968
                &PyArray_Converter, &prototype,
1969
                &PyArray_DescrConverter2, &dtype,
1970
                &PyArray_OrderConverter, &order,
1971
                &subok,
1972
                &PyArray_OptionalIntpConverter, &shape)) {
1973
        goto fail;
1974
    }
1975
    /* steals the reference to dtype if it's not NULL */
1976 1
    ret = (PyArrayObject *)PyArray_NewLikeArrayWithShape(prototype, order, dtype,
1977 1
                                                         shape.len, shape.ptr, subok);
1978 1
    npy_free_cache_dim_obj(shape);
1979 1
    if (!ret) {
1980
        goto fail;
1981
    }
1982 1
    Py_DECREF(prototype);
1983

1984
    return (PyObject *)ret;
1985

1986 0
fail:
1987 0
    Py_XDECREF(prototype);
1988 0
    Py_XDECREF(dtype);
1989
    return NULL;
1990
}
1991

1992
/*
1993
 * This function is needed for supporting Pickles of
1994
 * numpy scalar objects.
1995
 */
1996
static PyObject *
1997 1
array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
1998
{
1999

2000
    static char *kwlist[] = {"dtype", "obj", NULL};
2001
    PyArray_Descr *typecode;
2002 1
    PyObject *obj = NULL, *tmpobj = NULL;
2003 1
    int alloc = 0;
2004
    void *dptr;
2005
    PyObject *ret;
2006

2007

2008 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O:scalar", kwlist,
2009
                &PyArrayDescr_Type, &typecode, &obj)) {
2010
        return NULL;
2011
    }
2012 1
    if (PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
2013 1
        if (!PySequence_Check(obj)) {
2014 1
            PyErr_SetString(PyExc_TypeError,
2015
                            "found non-sequence while unpickling scalar with "
2016
                            "NPY_LIST_PICKLE set");
2017 1
            return NULL;
2018
        }
2019
        dptr = &obj;
2020
    }
2021

2022 1
    else if (PyDataType_FLAGCHK(typecode, NPY_ITEM_IS_POINTER)) {
2023 0
        if (obj == NULL) {
2024 0
            obj = Py_None;
2025
        }
2026
        dptr = &obj;
2027
    }
2028
    else {
2029 1
        if (obj == NULL) {
2030 0
            if (typecode->elsize == 0) {
2031 0
                typecode->elsize = 1;
2032
            }
2033 0
            dptr = PyArray_malloc(typecode->elsize);
2034 0
            if (dptr == NULL) {
2035 0
                return PyErr_NoMemory();
2036
            }
2037 0
            memset(dptr, '\0', typecode->elsize);
2038 0
            alloc = 1;
2039
        }
2040
        else {
2041
            /* Backward compatibility with Python 2 NumPy pickles */
2042 1
            if (PyUnicode_Check(obj)) {
2043 1
                tmpobj = PyUnicode_AsLatin1String(obj);
2044 1
                obj = tmpobj;
2045 1
                if (tmpobj == NULL) {
2046
                    /* More informative error message */
2047 1
                    PyErr_SetString(PyExc_ValueError,
2048
                            "Failed to encode Numpy scalar data string to "
2049
                            "latin1,\npickle.load(a, encoding='latin1') is "
2050
                            "assumed if unpickling.");
2051 1
                    return NULL;
2052
                }
2053
            }
2054 1
            if (!PyBytes_Check(obj)) {
2055 0
                PyErr_SetString(PyExc_TypeError,
2056
                        "initializing object must be a bytes object");
2057 0
                Py_XDECREF(tmpobj);
2058
                return NULL;
2059
            }
2060 1
            if (PyBytes_GET_SIZE(obj) < typecode->elsize) {
2061 0
                PyErr_SetString(PyExc_ValueError,
2062
                        "initialization string is too small");
2063 0
                Py_XDECREF(tmpobj);
2064
                return NULL;
2065
            }
2066 1
            dptr = PyBytes_AS_STRING(obj);
2067
        }
2068
    }
2069 1
    ret = PyArray_Scalar(dptr, typecode, NULL);
2070

2071
    /* free dptr which contains zeros */
2072 1
    if (alloc) {
2073 0
        PyArray_free(dptr);
2074
    }
2075 1
    Py_XDECREF(tmpobj);
2076
    return ret;
2077
}
2078

2079
static PyObject *
2080 1
array_zeros(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
2081
{
2082
    static char *kwlist[] = {"shape", "dtype", "order", "like", NULL};
2083 1
    PyArray_Descr *typecode = NULL;
2084 1
    PyArray_Dims shape = {NULL, 0};
2085 1
    NPY_ORDER order = NPY_CORDER;
2086 1
    PyObject *like = NULL;
2087 1
    npy_bool is_f_order = NPY_FALSE;
2088 1
    PyObject *array_function_result = NULL;
2089 1
    PyArrayObject *ret = NULL;
2090

2091 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&$O:zeros", kwlist,
2092
                PyArray_IntpConverter, &shape,
2093
                PyArray_DescrConverter, &typecode,
2094
                PyArray_OrderConverter, &order,
2095
                &like)) {
2096
        goto fail;
2097
    }
2098

2099 1
    array_function_result = array_implement_c_array_function_creation(
2100
            "zeros", args, kwds);
2101 1
    if (array_function_result != Py_NotImplemented) {
2102
        return array_function_result;
2103
    }
2104

2105 1
    switch (order) {
2106
        case NPY_CORDER:
2107
            is_f_order = NPY_FALSE;
2108
            break;
2109 1
        case NPY_FORTRANORDER:
2110 1
            is_f_order = NPY_TRUE;
2111 1
            break;
2112 1
        default:
2113 1
            PyErr_SetString(PyExc_ValueError,
2114
                            "only 'C' or 'F' order is permitted");
2115 1
            goto fail;
2116
    }
2117

2118 1
    ret = (PyArrayObject *)PyArray_Zeros(shape.len, shape.ptr,
2119
                                        typecode, (int) is_f_order);
2120

2121 1
    npy_free_cache_dim_obj(shape);
2122 1
    return (PyObject *)ret;
2123

2124 0
fail:
2125 1
    Py_XDECREF(typecode);
2126 1
    npy_free_cache_dim_obj(shape);
2127 1
    return (PyObject *)ret;
2128
}
2129

2130
static PyObject *
2131 1
array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
2132
{
2133
    PyArrayObject *array;
2134
    npy_intp count;
2135

2136 1
    if (!PyArg_ParseTuple(args, "O&:count_nonzero", PyArray_Converter, &array)) {
2137
        return NULL;
2138
    }
2139

2140 1
    count =  PyArray_CountNonzero(array);
2141

2142 1
    Py_DECREF(array);
2143

2144 1
    if (count == -1) {
2145
        return NULL;
2146
    }
2147 1
    return PyLong_FromSsize_t(count);
2148
}
2149

2150
static PyObject *
2151 1
array_fromstring(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2152
{
2153
    char *data;
2154 1
    Py_ssize_t nin = -1;
2155 1
    char *sep = NULL;
2156
    Py_ssize_t s;
2157
    static char *kwlist[] = {"string", "dtype", "count", "sep", "like", NULL};
2158 1
    PyObject *like = NULL;
2159 1
    PyArray_Descr *descr = NULL;
2160 1
    PyObject *array_function_result = NULL;
2161

2162 1
    if (!PyArg_ParseTupleAndKeywords(args, keywds,
2163
                "s#|O&" NPY_SSIZE_T_PYFMT "s$O:fromstring", kwlist,
2164
                &data, &s, PyArray_DescrConverter, &descr, &nin, &sep, &like)) {
2165 0
        Py_XDECREF(descr);
2166
        return NULL;
2167
    }
2168

2169 1
    array_function_result = array_implement_c_array_function_creation(
2170
            "fromstring", args, keywds);
2171 1
    if (array_function_result != Py_NotImplemented) {
2172
        return array_function_result;
2173
    }
2174

2175
    /* binary mode, condition copied from PyArray_FromString */
2176 1
    if (sep == NULL || strlen(sep) == 0) {
2177
        /* Numpy 1.14, 2017-10-19 */
2178 1
        if (DEPRECATE(
2179
                "The binary mode of fromstring is deprecated, as it behaves "
2180
                "surprisingly on unicode inputs. Use frombuffer instead") < 0) {
2181 1
            Py_XDECREF(descr);
2182
            return NULL;
2183
        }
2184
    }
2185 1
    return PyArray_FromString(data, (npy_intp)s, descr, (npy_intp)nin, sep);
2186
}
2187

2188

2189

2190
static PyObject *
2191 1
array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2192
{
2193 1
    PyObject *file = NULL, *ret = NULL;
2194 1
    PyObject *err_type = NULL, *err_value = NULL, *err_traceback = NULL;
2195 1
    char *sep = "";
2196 1
    Py_ssize_t nin = -1;
2197
    static char *kwlist[] = {"file", "dtype", "count", "sep", "offset", "like", NULL};
2198 1
    PyObject *like = NULL;
2199 1
    PyArray_Descr *type = NULL;
2200 1
    PyObject *array_function_result = NULL;
2201
    int own;
2202 1
    npy_off_t orig_pos = 0, offset = 0;
2203
    FILE *fp;
2204

2205 1
    if (!PyArg_ParseTupleAndKeywords(args, keywds,
2206
                "O|O&" NPY_SSIZE_T_PYFMT "s" NPY_OFF_T_PYFMT "$O:fromfile", kwlist,
2207
                &file, PyArray_DescrConverter, &type, &nin, &sep, &offset, &like)) {
2208 0
        Py_XDECREF(type);
2209
        return NULL;
2210
    }
2211

2212 1
    array_function_result = array_implement_c_array_function_creation(
2213
            "fromfile", args, keywds);
2214 1
    if (array_function_result != Py_NotImplemented) {
2215
        return array_function_result;
2216
    }
2217

2218 1
    file = NpyPath_PathlikeToFspath(file);
2219 1
    if (file == NULL) {
2220
        return NULL;
2221
    }
2222

2223 1
    if (offset != 0 && strcmp(sep, "") != 0) {
2224 1
        PyErr_SetString(PyExc_TypeError, "'offset' argument only permitted for binary files");
2225 1
        Py_XDECREF(type);
2226 1
        Py_DECREF(file);
2227
        return NULL;
2228
    }
2229 1
    if (PyBytes_Check(file) || PyUnicode_Check(file)) {
2230 1
        Py_SETREF(file, npy_PyFile_OpenFile(file, "rb"));
2231 1
        if (file == NULL) {
2232 0
            Py_XDECREF(type);
2233
            return NULL;
2234
        }
2235
        own = 1;
2236
    }
2237
    else {
2238
        own = 0;
2239
    }
2240 1
    fp = npy_PyFile_Dup2(file, "rb", &orig_pos);
2241 1
    if (fp == NULL) {
2242 1
        Py_DECREF(file);
2243 1
        Py_XDECREF(type);
2244
        return NULL;
2245
    }
2246 1
    if (npy_fseek(fp, offset, SEEK_CUR) != 0) {
2247 0
        PyErr_SetFromErrno(PyExc_IOError);
2248 0
        goto cleanup;
2249
    }
2250 1
    if (type == NULL) {
2251 1
        type = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
2252
    }
2253 1
    ret = PyArray_FromFile(fp, type, (npy_intp) nin, sep);
2254

2255
    /* If an exception is thrown in the call to PyArray_FromFile
2256
     * we need to clear it, and restore it later to ensure that
2257
     * we can cleanup the duplicated file descriptor properly.
2258
     */
2259 1
cleanup:
2260 1
    PyErr_Fetch(&err_type, &err_value, &err_traceback);
2261 1
    if (npy_PyFile_DupClose2(file, fp, orig_pos) < 0) {
2262 0
        npy_PyErr_ChainExceptions(err_type, err_value, err_traceback);
2263 0
        goto fail;
2264
    }
2265 1
    if (own && npy_PyFile_CloseFile(file) < 0) {
2266 0
        npy_PyErr_ChainExceptions(err_type, err_value, err_traceback);
2267 0
        goto fail;
2268
    }
2269 1
    PyErr_Restore(err_type, err_value, err_traceback);
2270 1
    Py_DECREF(file);
2271
    return ret;
2272

2273 0
fail:
2274 0
    Py_DECREF(file);
2275 0
    Py_XDECREF(ret);
2276
    return NULL;
2277
}
2278

2279
static PyObject *
2280 1
array_fromiter(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2281
{
2282
    PyObject *iter;
2283 1
    Py_ssize_t nin = -1;
2284
    static char *kwlist[] = {"iter", "dtype", "count", "like", NULL};
2285 1
    PyObject *like = NULL;
2286 1
    PyArray_Descr *descr = NULL;
2287 1
    PyObject *array_function_result = NULL;
2288

2289 1
    if (!PyArg_ParseTupleAndKeywords(args, keywds,
2290
                "OO&|" NPY_SSIZE_T_PYFMT "$O:fromiter", kwlist,
2291
                &iter, PyArray_DescrConverter, &descr, &nin, &like)) {
2292 0
        Py_XDECREF(descr);
2293
        return NULL;
2294
    }
2295

2296 1
    array_function_result = array_implement_c_array_function_creation(
2297
            "fromiter", args, keywds);
2298 1
    if (array_function_result != Py_NotImplemented) {
2299
        return array_function_result;
2300
    }
2301

2302 1
    return PyArray_FromIter(iter, descr, (npy_intp)nin);
2303
}
2304

2305
static PyObject *
2306 1
array_frombuffer(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
2307
{
2308 1
    PyObject *obj = NULL;
2309 1
    Py_ssize_t nin = -1, offset = 0;
2310
    static char *kwlist[] = {"buffer", "dtype", "count", "offset", "like", NULL};
2311 1
    PyObject *like = NULL;
2312 1
    PyArray_Descr *type = NULL;
2313 1
    PyObject *array_function_result = NULL;
2314

2315 1
    if (!PyArg_ParseTupleAndKeywords(args, keywds,
2316
                "O|O&" NPY_SSIZE_T_PYFMT NPY_SSIZE_T_PYFMT "$O:frombuffer", kwlist,
2317
                &obj, PyArray_DescrConverter, &type, &nin, &offset, &like)) {
2318 0
        Py_XDECREF(type);
2319
        return NULL;
2320
    }
2321

2322 1
    array_function_result = array_implement_c_array_function_creation(
2323
            "frombuffer", args, keywds);
2324 1
    if (array_function_result != Py_NotImplemented) {
2325
        return array_function_result;
2326
    }
2327

2328 1
    if (type == NULL) {
2329 1
        type = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
2330
    }
2331 1
    return PyArray_FromBuffer(obj, type, (npy_intp)nin, (npy_intp)offset);
2332
}
2333

2334
static PyObject *
2335 1
array_concatenate(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2336
{
2337
    PyObject *a0;
2338 1
    PyObject *out = NULL;
2339 1
    PyArray_Descr *dtype = NULL;
2340 1
    NPY_CASTING casting = NPY_SAME_KIND_CASTING;
2341 1
    PyObject *casting_obj = NULL;
2342
    PyObject *res;
2343 1
    int axis = 0;
2344
    static char *kwlist[] = {"seq", "axis", "out", "dtype", "casting", NULL};
2345 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O&O$O&O:concatenate", kwlist,
2346
                &a0, PyArray_AxisConverter, &axis, &out,
2347
                PyArray_DescrConverter2, &dtype, &casting_obj)) {
2348
        return NULL;
2349
    }
2350 1
    int casting_not_passed = 0;
2351 1
    if (casting_obj == NULL) {
2352
        /*
2353
         * Casting was not passed in, needed for deprecation only.
2354
         * This should be simplified once the deprecation is finished.
2355
         */
2356
        casting_not_passed = 1;
2357
    }
2358 1
    else if (!PyArray_CastingConverter(casting_obj, &casting)) {
2359 0
        Py_XDECREF(dtype);
2360
        return NULL;
2361
    }
2362 1
    if (out != NULL) {
2363 1
        if (out == Py_None) {
2364 1
            out = NULL;
2365
        }
2366 1
        else if (!PyArray_Check(out)) {
2367 0
            PyErr_SetString(PyExc_TypeError, "'out' must be an array");
2368 0
            Py_XDECREF(dtype);
2369
            return NULL;
2370
        }
2371
    }
2372 1
    res = PyArray_ConcatenateInto(a0, axis, (PyArrayObject *)out, dtype,
2373
            casting, casting_not_passed);
2374 1
    Py_XDECREF(dtype);
2375
    return res;
2376
}
2377

2378
static PyObject *
2379 1
array_innerproduct(PyObject *NPY_UNUSED(dummy), PyObject *args)
2380
{
2381
    PyObject *b0, *a0;
2382

2383 1
    if (!PyArg_ParseTuple(args, "OO:innerproduct", &a0, &b0)) {
2384
        return NULL;
2385
    }
2386 1
    return PyArray_Return((PyArrayObject *)PyArray_InnerProduct(a0, b0));
2387
}
2388

2389
static PyObject *
2390 1
array_matrixproduct(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject* kwds)
2391
{
2392 1
    PyObject *v, *a, *o = NULL;
2393
    PyArrayObject *ret;
2394 1
    char* kwlist[] = {"a", "b", "out", NULL };
2395

2396 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:matrixproduct",
2397
                                     kwlist, &a, &v, &o)) {
2398
        return NULL;
2399
    }
2400 1
    if (o != NULL) {
2401 1
        if (o == Py_None) {
2402 1
            o = NULL;
2403
        }
2404 1
        else if (!PyArray_Check(o)) {
2405 0
            PyErr_SetString(PyExc_TypeError, "'out' must be an array");
2406 0
            return NULL;
2407
        }
2408
    }
2409 1
    ret = (PyArrayObject *)PyArray_MatrixProduct2(a, v, (PyArrayObject *)o);
2410 1
    return PyArray_Return(ret);
2411
}
2412

2413

2414
static PyObject *
2415 1
array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args)
2416
{
2417
    int typenum;
2418
    char *ip1, *ip2, *op;
2419
    npy_intp n, stride1, stride2;
2420
    PyObject *op1, *op2;
2421 1
    npy_intp newdimptr[1] = {-1};
2422 1
    PyArray_Dims newdims = {newdimptr, 1};
2423 1
    PyArrayObject *ap1 = NULL, *ap2  = NULL, *ret = NULL;
2424
    PyArray_Descr *type;
2425
    PyArray_DotFunc *vdot;
2426 1
    NPY_BEGIN_THREADS_DEF;
2427

2428 1
    if (!PyArg_ParseTuple(args, "OO:vdot", &op1, &op2)) {
2429
        return NULL;
2430
    }
2431

2432
    /*
2433
     * Conjugating dot product using the BLAS for vectors.
2434
     * Flattens both op1 and op2 before dotting.
2435
     */
2436 1
    typenum = PyArray_ObjectType(op1, 0);
2437 1
    typenum = PyArray_ObjectType(op2, typenum);
2438

2439 1
    type = PyArray_DescrFromType(typenum);
2440 1
    Py_INCREF(type);
2441 1
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, type, 0, 0, 0, NULL);
2442 1
    if (ap1 == NULL) {
2443 0
        Py_DECREF(type);
2444
        goto fail;
2445
    }
2446

2447 1
    op1 = PyArray_Newshape(ap1, &newdims, NPY_CORDER);
2448 1
    if (op1 == NULL) {
2449 0
        Py_DECREF(type);
2450
        goto fail;
2451
    }
2452 1
    Py_DECREF(ap1);
2453 1
    ap1 = (PyArrayObject *)op1;
2454

2455 1
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, type, 0, 0, 0, NULL);
2456 1
    if (ap2 == NULL) {
2457
        goto fail;
2458
    }
2459 1
    op2 = PyArray_Newshape(ap2, &newdims, NPY_CORDER);
2460 1
    if (op2 == NULL) {
2461
        goto fail;
2462
    }
2463 1
    Py_DECREF(ap2);
2464 1
    ap2 = (PyArrayObject *)op2;
2465

2466 1
    if (PyArray_DIM(ap2, 0) != PyArray_DIM(ap1, 0)) {
2467 0
        PyErr_SetString(PyExc_ValueError,
2468
                "vectors have different lengths");
2469 0
        goto fail;
2470
    }
2471

2472
    /* array scalar output */
2473 1
    ret = new_array_for_sum(ap1, ap2, NULL, 0, (npy_intp *)NULL, typenum, NULL);
2474 1
    if (ret == NULL) {
2475
        goto fail;
2476
    }
2477

2478 1
    n = PyArray_DIM(ap1, 0);
2479 1
    stride1 = PyArray_STRIDE(ap1, 0);
2480 1
    stride2 = PyArray_STRIDE(ap2, 0);
2481 1
    ip1 = PyArray_DATA(ap1);
2482 1
    ip2 = PyArray_DATA(ap2);
2483 1
    op = PyArray_DATA(ret);
2484

2485 1
    switch (typenum) {
2486
        case NPY_CFLOAT:
2487
            vdot = (PyArray_DotFunc *)CFLOAT_vdot;
2488
            break;
2489 1
        case NPY_CDOUBLE:
2490 1
            vdot = (PyArray_DotFunc *)CDOUBLE_vdot;
2491 1
            break;
2492 1
        case NPY_CLONGDOUBLE:
2493 1
            vdot = (PyArray_DotFunc *)CLONGDOUBLE_vdot;
2494 1
            break;
2495 1
        case NPY_OBJECT:
2496 1
            vdot = (PyArray_DotFunc *)OBJECT_vdot;
2497 1
            break;
2498 1
        default:
2499 1
            vdot = type->f->dotfunc;
2500 1
            if (vdot == NULL) {
2501 0
                PyErr_SetString(PyExc_ValueError,
2502
                        "function not available for this data type");
2503 0
                goto fail;
2504
            }
2505
    }
2506

2507 1
    if (n < 500) {
2508 1
        vdot(ip1, stride1, ip2, stride2, op, n, NULL);
2509
    }
2510
    else {
2511 1
        NPY_BEGIN_THREADS_DESCR(type);
2512 1
        vdot(ip1, stride1, ip2, stride2, op, n, NULL);
2513 1
        NPY_END_THREADS_DESCR(type);
2514
    }
2515

2516 1
    Py_XDECREF(ap1);
2517 1
    Py_XDECREF(ap2);
2518 1
    return PyArray_Return(ret);
2519 0
fail:
2520 0
    Py_XDECREF(ap1);
2521 0
    Py_XDECREF(ap2);
2522 0
    Py_XDECREF(ret);
2523
    return NULL;
2524
}
2525

2526
static int
2527 1
einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts,
2528
                       PyArrayObject **op)
2529
{
2530
    int i, nop;
2531
    PyObject *subscripts_str;
2532

2533 1
    nop = PyTuple_GET_SIZE(args) - 1;
2534 1
    if (nop <= 0) {
2535 1
        PyErr_SetString(PyExc_ValueError,
2536
                        "must specify the einstein sum subscripts string "
2537
                        "and at least one operand");
2538 1
        return -1;
2539
    }
2540 1
    else if (nop >= NPY_MAXARGS) {
2541 0
        PyErr_SetString(PyExc_ValueError, "too many operands");
2542 0
        return -1;
2543
    }
2544

2545
    /* Get the subscripts string */
2546 1
    subscripts_str = PyTuple_GET_ITEM(args, 0);
2547 1
    if (PyUnicode_Check(subscripts_str)) {
2548 1
        *str_obj = PyUnicode_AsASCIIString(subscripts_str);
2549 1
        if (*str_obj == NULL) {
2550
            return -1;
2551
        }
2552
        subscripts_str = *str_obj;
2553
    }
2554

2555 1
    *subscripts = PyBytes_AsString(subscripts_str);
2556 1
    if (*subscripts == NULL) {
2557 0
        Py_XDECREF(*str_obj);
2558 0
        *str_obj = NULL;
2559 0
        return -1;
2560
    }
2561

2562
    /* Set the operands to NULL */
2563 1
    for (i = 0; i < nop; ++i) {
2564 1
        op[i] = NULL;
2565
    }
2566

2567
    /* Get the operands */
2568 1
    for (i = 0; i < nop; ++i) {
2569 1
        PyObject *obj = PyTuple_GET_ITEM(args, i+1);
2570

2571 1
        op[i] = (PyArrayObject *)PyArray_FROM_OF(obj, NPY_ARRAY_ENSUREARRAY);
2572 1
        if (op[i] == NULL) {
2573
            goto fail;
2574
        }
2575
    }
2576

2577
    return nop;
2578

2579 0
fail:
2580 0
    for (i = 0; i < nop; ++i) {
2581 0
        Py_XDECREF(op[i]);
2582 0
        op[i] = NULL;
2583
    }
2584

2585
    return -1;
2586
}
2587

2588
/*
2589
 * Converts a list of subscripts to a string.
2590
 *
2591
 * Returns -1 on error, the number of characters placed in subscripts
2592
 * otherwise.
2593
 */
2594
static int
2595 1
einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
2596
{
2597 1
    int ellipsis = 0, subindex = 0;
2598
    npy_intp i, size;
2599
    PyObject *item;
2600

2601 1
    obj = PySequence_Fast(obj, "the subscripts for each operand must "
2602
                               "be a list or a tuple");
2603 1
    if (obj == NULL) {
2604
        return -1;
2605
    }
2606 1
    size = PySequence_Size(obj);
2607

2608 1
    for (i = 0; i < size; ++i) {
2609 1
        item = PySequence_Fast_GET_ITEM(obj, i);
2610
        /* Ellipsis */
2611 1
        if (item == Py_Ellipsis) {
2612 1
            if (ellipsis) {
2613 0
                PyErr_SetString(PyExc_ValueError,
2614
                        "each subscripts list may have only one ellipsis");
2615 0
                Py_DECREF(obj);
2616
                return -1;
2617
            }
2618 1
            if (subindex + 3 >= subsize) {
2619 0
                PyErr_SetString(PyExc_ValueError,
2620
                        "subscripts list is too long");
2621 0
                Py_DECREF(obj);
2622
                return -1;
2623
            }
2624 1
            subscripts[subindex++] = '.';
2625 1
            subscripts[subindex++] = '.';
2626 1
            subscripts[subindex++] = '.';
2627 1
            ellipsis = 1;
2628
        }
2629
        /* Subscript */
2630
        else {
2631 1
            npy_intp s = PyArray_PyIntAsIntp(item);
2632
            /* Invalid */
2633 1
            if (error_converting(s)) {
2634 0
                PyErr_SetString(PyExc_TypeError,
2635
                        "each subscript must be either an integer "
2636
                        "or an ellipsis");
2637 0
                Py_DECREF(obj);
2638
                return -1;
2639
            }
2640 1
            npy_bool bad_input = 0;
2641

2642 1
            if (subindex + 1 >= subsize) {
2643 0
                PyErr_SetString(PyExc_ValueError,
2644
                        "subscripts list is too long");
2645 0
                Py_DECREF(obj);
2646
                return -1;
2647
            }
2648

2649 1
            if (s < 0) {
2650
                bad_input = 1;
2651
            }
2652 1
            else if (s < 26) {
2653 1
                subscripts[subindex++] = 'A' + (char)s;
2654
            }
2655 1
            else if (s < 2*26) {
2656 1
                subscripts[subindex++] = 'a' + (char)s - 26;
2657
            }
2658
            else {
2659
                bad_input = 1;
2660
            }
2661

2662
            if (bad_input) {
2663 1
                PyErr_SetString(PyExc_ValueError,
2664
                        "subscript is not within the valid range [0, 52)");
2665 1
                Py_DECREF(obj);
2666
                return -1;
2667
            }
2668
        }
2669

2670
    }
2671

2672 1
    Py_DECREF(obj);
2673

2674
    return subindex;
2675
}
2676

2677
/*
2678
 * Fills in the subscripts, with maximum size subsize, and op,
2679
 * with the values in the tuple 'args'.
2680
 *
2681
 * Returns -1 on error, number of operands placed in op otherwise.
2682
 */
2683
static int
2684 1
einsum_sub_op_from_lists(PyObject *args,
2685
                char *subscripts, int subsize, PyArrayObject **op)
2686
{
2687 1
    int subindex = 0;
2688
    npy_intp i, nop;
2689

2690 1
    nop = PyTuple_Size(args)/2;
2691

2692 1
    if (nop == 0) {
2693 0
        PyErr_SetString(PyExc_ValueError, "must provide at least an "
2694
                        "operand and a subscripts list to einsum");
2695 0
        return -1;
2696
    }
2697 1
    else if (nop >= NPY_MAXARGS) {
2698 0
        PyErr_SetString(PyExc_ValueError, "too many operands");
2699 0
        return -1;
2700
    }
2701

2702
    /* Set the operands to NULL */
2703 1
    for (i = 0; i < nop; ++i) {
2704 1
        op[i] = NULL;
2705
    }
2706

2707
    /* Get the operands and build the subscript string */
2708 1
    for (i = 0; i < nop; ++i) {
2709 1
        PyObject *obj = PyTuple_GET_ITEM(args, 2*i);
2710
        int n;
2711

2712
        /* Comma between the subscripts for each operand */
2713 1
        if (i != 0) {
2714 1
            subscripts[subindex++] = ',';
2715 1
            if (subindex >= subsize) {
2716 0
                PyErr_SetString(PyExc_ValueError,
2717
                        "subscripts list is too long");
2718 0
                goto fail;
2719
            }
2720
        }
2721

2722 1
        op[i] = (PyArrayObject *)PyArray_FROM_OF(obj, NPY_ARRAY_ENSUREARRAY);
2723 1
        if (op[i] == NULL) {
2724
            goto fail;
2725
        }
2726

2727 1
        obj = PyTuple_GET_ITEM(args, 2*i+1);
2728 1
        n = einsum_list_to_subscripts(obj, subscripts+subindex,
2729
                                      subsize-subindex);
2730 1
        if (n < 0) {
2731
            goto fail;
2732
        }
2733 1
        subindex += n;
2734
    }
2735

2736
    /* Add the '->' to the string if provided */
2737 1
    if (PyTuple_Size(args) == 2*nop+1) {
2738
        PyObject *obj;
2739
        int n;
2740

2741 1
        if (subindex + 2 >= subsize) {
2742 0
            PyErr_SetString(PyExc_ValueError,
2743
                    "subscripts list is too long");
2744 0
            goto fail;
2745
        }
2746 1
        subscripts[subindex++] = '-';
2747 1
        subscripts[subindex++] = '>';
2748

2749 1
        obj = PyTuple_GET_ITEM(args, 2*nop);
2750 1
        n = einsum_list_to_subscripts(obj, subscripts+subindex,
2751
                                      subsize-subindex);
2752 1
        if (n < 0) {
2753
            goto fail;
2754
        }
2755 1
        subindex += n;
2756
    }
2757

2758
    /* NULL-terminate the subscripts string */
2759 1
    subscripts[subindex] = '\0';
2760

2761 1
    return nop;
2762

2763 1
fail:
2764 1
    for (i = 0; i < nop; ++i) {
2765 1
        Py_XDECREF(op[i]);
2766 1
        op[i] = NULL;
2767
    }
2768

2769
    return -1;
2770
}
2771

2772
static PyObject *
2773 1
array_einsum(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2774
{
2775 1
    char *subscripts = NULL, subscripts_buffer[256];
2776 1
    PyObject *str_obj = NULL, *str_key_obj = NULL;
2777
    PyObject *arg0;
2778
    int i, nop;
2779
    PyArrayObject *op[NPY_MAXARGS];
2780 1
    NPY_ORDER order = NPY_KEEPORDER;
2781 1
    NPY_CASTING casting = NPY_SAFE_CASTING;
2782 1
    PyArrayObject *out = NULL;
2783 1
    PyArray_Descr *dtype = NULL;
2784 1
    PyObject *ret = NULL;
2785

2786 1
    if (PyTuple_GET_SIZE(args) < 1) {
2787 1
        PyErr_SetString(PyExc_ValueError,
2788
                        "must specify the einstein sum subscripts string "
2789
                        "and at least one operand, or at least one operand "
2790
                        "and its corresponding subscripts list");
2791 1
        return NULL;
2792
    }
2793 1
    arg0 = PyTuple_GET_ITEM(args, 0);
2794

2795
    /* einsum('i,j', a, b), einsum('i,j->ij', a, b) */
2796 1
    if (PyBytes_Check(arg0) || PyUnicode_Check(arg0)) {
2797 1
        nop = einsum_sub_op_from_str(args, &str_obj, &subscripts, op);
2798
    }
2799
    /* einsum(a, [0], b, [1]), einsum(a, [0], b, [1], [0,1]) */
2800
    else {
2801 1
        nop = einsum_sub_op_from_lists(args, subscripts_buffer,
2802
                                    sizeof(subscripts_buffer), op);
2803 1
        subscripts = subscripts_buffer;
2804
    }
2805 1
    if (nop <= 0) {
2806
        goto finish;
2807
    }
2808

2809
    /* Get the keyword arguments */
2810 1
    if (kwds != NULL) {
2811
        PyObject *key, *value;
2812 1
        Py_ssize_t pos = 0;
2813 1
        while (PyDict_Next(kwds, &pos, &key, &value)) {
2814 1
            char *str = NULL;
2815

2816 1
            Py_XDECREF(str_key_obj);
2817 1
            str_key_obj = PyUnicode_AsASCIIString(key);
2818 1
            if (str_key_obj != NULL) {
2819 1
                key = str_key_obj;
2820
            }
2821

2822 1
            str = PyBytes_AsString(key);
2823

2824 1
            if (str == NULL) {
2825 0
                PyErr_Clear();
2826 0
                PyErr_SetString(PyExc_TypeError, "invalid keyword");
2827 0
                goto finish;
2828
            }
2829

2830 1
            if (strcmp(str,"out") == 0) {
2831 1
                if (PyArray_Check(value)) {
2832 1
                    out = (PyArrayObject *)value;
2833
                }
2834
                else {
2835 1
                    PyErr_SetString(PyExc_TypeError,
2836
                                "keyword parameter out must be an "
2837
                                "array for einsum");
2838 1
                    goto finish;
2839
                }
2840
            }
2841 1
            else if (strcmp(str,"order") == 0) {
2842 1
                if (!PyArray_OrderConverter(value, &order)) {
2843
                    goto finish;
2844
                }
2845
            }
2846 1
            else if (strcmp(str,"casting") == 0) {
2847 1
                if (!PyArray_CastingConverter(value, &casting)) {
2848
                    goto finish;
2849
                }
2850
            }
2851 1
            else if (strcmp(str,"dtype") == 0) {
2852 1
                if (!PyArray_DescrConverter2(value, &dtype)) {
2853
                    goto finish;
2854
                }
2855
            }
2856
            else {
2857 1
                PyErr_Format(PyExc_TypeError,
2858
                            "'%s' is an invalid keyword for einsum",
2859
                            str);
2860 1
                goto finish;
2861
            }
2862
        }
2863
    }
2864

2865 1
    ret = (PyObject *)PyArray_EinsteinSum(subscripts, nop, op, dtype,
2866
                                        order, casting, out);
2867

2868
    /* If no output was supplied, possibly convert to a scalar */
2869 1
    if (ret != NULL && out == NULL) {
2870 1
        ret = PyArray_Return((PyArrayObject *)ret);
2871
    }
2872

2873 1
finish:
2874 1
    for (i = 0; i < nop; ++i) {
2875 1
        Py_XDECREF(op[i]);
2876
    }
2877 1
    Py_XDECREF(dtype);
2878 1
    Py_XDECREF(str_obj);
2879 1
    Py_XDECREF(str_key_obj);
2880
    /* out is a borrowed reference */
2881

2882
    return ret;
2883
}
2884

2885
static PyObject *
2886 1
array_fastCopyAndTranspose(PyObject *NPY_UNUSED(dummy), PyObject *args)
2887
{
2888
    PyObject *a0;
2889

2890 1
    if (!PyArg_ParseTuple(args, "O:_fastCopyAndTranspose", &a0)) {
2891
        return NULL;
2892
    }
2893 1
    return PyArray_Return((PyArrayObject *)PyArray_CopyAndTranspose(a0));
2894
}
2895

2896
static PyObject *
2897 1
array_correlate(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2898
{
2899
    PyObject *shape, *a0;
2900 1
    int mode = 0;
2901
    static char *kwlist[] = {"a", "v", "mode", NULL};
2902

2903 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i:correlate", kwlist,
2904
                &a0, &shape, &mode)) {
2905
        return NULL;
2906
    }
2907 1
    return PyArray_Correlate(a0, shape, mode);
2908
}
2909

2910
static PyObject*
2911 1
array_correlate2(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2912
{
2913
    PyObject *shape, *a0;
2914 1
    int mode = 0;
2915
    static char *kwlist[] = {"a", "v", "mode", NULL};
2916

2917 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i:correlate2", kwlist,
2918
                &a0, &shape, &mode)) {
2919
        return NULL;
2920
    }
2921 1
    return PyArray_Correlate2(a0, shape, mode);
2922
}
2923

2924
static PyObject *
2925 1
array_arange(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) {
2926 1
    PyObject *o_start = NULL, *o_stop = NULL, *o_step = NULL, *range=NULL;
2927 1
    PyObject *like = NULL;
2928 1
    PyObject *array_function_result = NULL;
2929
    static char *kwd[] = {"start", "stop", "step", "dtype", "like", NULL};
2930 1
    PyArray_Descr *typecode = NULL;
2931

2932 1
    if (!PyArg_ParseTupleAndKeywords(args, kws, "O|OOO&$O:arange", kwd,
2933
                &o_start,
2934
                &o_stop,
2935
                &o_step,
2936
                PyArray_DescrConverter2, &typecode,
2937
                &like)) {
2938 0
        Py_XDECREF(typecode);
2939
        return NULL;
2940
    }
2941

2942 1
    array_function_result = array_implement_c_array_function_creation(
2943
            "arange", args, kws);
2944 1
    if (array_function_result != Py_NotImplemented) {
2945
        return array_function_result;
2946
    }
2947

2948 1
    range = PyArray_ArangeObj(o_start, o_stop, o_step, typecode);
2949 1
    Py_XDECREF(typecode);
2950

2951
    return range;
2952
}
2953

2954
/*NUMPY_API
2955
 *
2956
 * Included at the very first so not auto-grabbed and thus not labeled.
2957
 */
2958
NPY_NO_EXPORT unsigned int
2959 1
PyArray_GetNDArrayCVersion(void)
2960
{
2961 1
    return (unsigned int)NPY_ABI_VERSION;
2962
}
2963

2964
/*NUMPY_API
2965
 * Returns the built-in (at compilation time) C API version
2966
 */
2967
NPY_NO_EXPORT unsigned int
2968 1
PyArray_GetNDArrayCFeatureVersion(void)
2969
{
2970 1
    return (unsigned int)NPY_API_VERSION;
2971
}
2972

2973
static PyObject *
2974 0
array__get_ndarray_c_version(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
2975
{
2976
    static char *kwlist[] = {NULL};
2977

2978 0
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist )) {
2979
        return NULL;
2980
    }
2981 0
    return PyLong_FromLong( (long) PyArray_GetNDArrayCVersion() );
2982
}
2983

2984
/*NUMPY_API
2985
*/
2986
NPY_NO_EXPORT int
2987 1
PyArray_GetEndianness(void)
2988
{
2989
    const union {
2990
        npy_uint32 i;
2991
        char c[4];
2992
    } bint = {0x01020304};
2993

2994
    if (bint.c[0] == 1) {
2995
        return NPY_CPU_BIG;
2996
    }
2997
    else if (bint.c[0] == 4) {
2998
        return NPY_CPU_LITTLE;
2999
    }
3000
    else {
3001
        return NPY_CPU_UNKNOWN_ENDIAN;
3002
    }
3003
}
3004

3005
static PyObject *
3006 1
array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args)
3007
{
3008

3009
    PyObject *ret;
3010
    PyTypeObject *subtype;
3011 1
    PyArray_Dims shape = {NULL, 0};
3012 1
    PyArray_Descr *dtype = NULL;
3013

3014 1