1
/*
2
  Provide multidimensional arrays as a basic object type in python.
3

4
  Based on Original Numeric implementation
5
  Copyright (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu
6

7
  with contributions from many Numeric Python developers 1995-2004
8

9
  Heavily modified in 2005 with inspiration from Numarray
10

11
  by
12

13
  Travis Oliphant,  oliphant@ee.byu.edu
14
  Brigham Young University
15

16

17
maintainer email:  oliphant.travis@ieee.org
18

19
  Numarray design (which provided guidance) by
20
  Space Science Telescope Institute
21
  (J. Todd Miller, Perry Greenfield, Rick White)
22
*/
23
#define PY_SSIZE_T_CLEAN
24
#include <Python.h>
25
#include "structmember.h"
26

27
/*#include <stdio.h>*/
28
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
29
#define _MULTIARRAYMODULE
30
#include "numpy/arrayobject.h"
31
#include "numpy/arrayscalars.h"
32

33
#include "npy_config.h"
34

35
#include "npy_pycompat.h"
36

37
#include "common.h"
38

39
#include "number.h"
40
#include "usertypes.h"
41
#include "arraytypes.h"
42
#include "scalartypes.h"
43
#include "arrayobject.h"
44
#include "conversion_utils.h"
45
#include "ctors.h"
46
#include "dtypemeta.h"
47
#include "methods.h"
48
#include "descriptor.h"
49
#include "iterators.h"
50
#include "mapping.h"
51
#include "getset.h"
52
#include "sequence.h"
53
#include "npy_buffer.h"
54
#include "array_assign.h"
55
#include "alloc.h"
56
#include "mem_overlap.h"
57
#include "numpyos.h"
58
#include "strfuncs.h"
59

60
#include "binop_override.h"
61
#include "array_coercion.h"
62

63
/*NUMPY_API
64
  Compute the size of an array (in number of items)
65
*/
66
NPY_NO_EXPORT npy_intp
67 1
PyArray_Size(PyObject *op)
68
{
69 1
    if (PyArray_Check(op)) {
70 1
        return PyArray_SIZE((PyArrayObject *)op);
71
    }
72
    else {
73
        return 0;
74
    }
75
}
76

77
/*NUMPY_API
78
 *
79
 * Precondition: 'arr' is a copy of 'base' (though possibly with different
80
 * strides, ordering, etc.). This function sets the UPDATEIFCOPY flag and the
81
 * ->base pointer on 'arr', so that when 'arr' is destructed, it will copy any
82
 * changes back to 'base'. DEPRECATED, use PyArray_SetWritebackIfCopyBase
83
 *
84
 * Steals a reference to 'base'.
85
 *
86
 * Returns 0 on success, -1 on failure.
87
 */
88
NPY_NO_EXPORT int
89 0
PyArray_SetUpdateIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
90
{
91
    int ret;
92
    /* 2017-Nov  -10 1.14 (for PyPy only) */
93
    /* 2018-April-21 1.15 (all Python implementations) */
94 0
    if (DEPRECATE("PyArray_SetUpdateIfCopyBase is deprecated, use "
95
              "PyArray_SetWritebackIfCopyBase instead, and be sure to call "
96
              "PyArray_ResolveWritebackIfCopy before the array is deallocated, "
97
              "i.e. before the last call to Py_DECREF. If cleaning up from an "
98
              "error, PyArray_DiscardWritebackIfCopy may be called instead to "
99
              "throw away the scratch buffer.") < 0)
100
        return -1;
101 0
    ret = PyArray_SetWritebackIfCopyBase(arr, base);
102 0
    if (ret >=0) {
103 0
        PyArray_ENABLEFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY);
104
        PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
105
    }
106
    return ret;
107
}
108

109
/*NUMPY_API
110
 *
111
 * Precondition: 'arr' is a copy of 'base' (though possibly with different
112
 * strides, ordering, etc.). This function sets the WRITEBACKIFCOPY flag and the
113
 * ->base pointer on 'arr', call PyArray_ResolveWritebackIfCopy to copy any
114
 * changes back to 'base' before deallocating the array.
115
 *
116
 * Steals a reference to 'base'.
117
 *
118
 * Returns 0 on success, -1 on failure.
119
 */
120
NPY_NO_EXPORT int
121 1
PyArray_SetWritebackIfCopyBase(PyArrayObject *arr, PyArrayObject *base)
122
{
123 1
    if (base == NULL) {
124 0
        PyErr_SetString(PyExc_ValueError,
125
                  "Cannot WRITEBACKIFCOPY to NULL array");
126 0
        return -1;
127
    }
128 1
    if (PyArray_BASE(arr) != NULL) {
129 0
        PyErr_SetString(PyExc_ValueError,
130
                  "Cannot set array with existing base to WRITEBACKIFCOPY");
131 0
        goto fail;
132
    }
133 1
    if (PyArray_FailUnlessWriteable(base, "WRITEBACKIFCOPY base") < 0) {
134
        goto fail;
135
    }
136

137
    /*
138
     * Any writes to 'arr' will magically turn into writes to 'base', so we
139
     * should warn if necessary.
140
     */
141 1
    if (PyArray_FLAGS(base) & NPY_ARRAY_WARN_ON_WRITE) {
142 0
        PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
143
    }
144

145
    /*
146
     * Unlike PyArray_SetBaseObject, we do not compress the chain of base
147
     * references.
148
     */
149 1
    ((PyArrayObject_fields *)arr)->base = (PyObject *)base;
150 1
    PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
151 1
    PyArray_CLEARFLAGS(base, NPY_ARRAY_WRITEABLE);
152

153 1
    return 0;
154

155 0
  fail:
156 0
    Py_DECREF(base);
157
    return -1;
158
}
159

160
/*NUMPY_API
161
 * Sets the 'base' attribute of the array. This steals a reference
162
 * to 'obj'.
163
 *
164
 * Returns 0 on success, -1 on failure.
165
 */
166
NPY_NO_EXPORT int
167 1
PyArray_SetBaseObject(PyArrayObject *arr, PyObject *obj)
168
{
169 1
    if (obj == NULL) {
170 0
        PyErr_SetString(PyExc_ValueError,
171
                "Cannot set the NumPy array 'base' "
172
                "dependency to NULL after initialization");
173 0
        return -1;
174
    }
175
    /*
176
     * Allow the base to be set only once. Once the object which
177
     * owns the data is set, it doesn't make sense to change it.
178
     */
179 1
    if (PyArray_BASE(arr) != NULL) {
180 0
        Py_DECREF(obj);
181 0
        PyErr_SetString(PyExc_ValueError,
182
                "Cannot set the NumPy array 'base' "
183
                "dependency more than once");
184 0
        return -1;
185
    }
186

187
    /*
188
     * Don't allow infinite chains of views, always set the base
189
     * to the first owner of the data.
190
     * That is, either the first object which isn't an array,
191
     * or the first object which owns its own data.
192
     */
193

194 1
    while (PyArray_Check(obj) && (PyObject *)arr != obj) {
195 1
        PyArrayObject *obj_arr = (PyArrayObject *)obj;
196
        PyObject *tmp;
197

198
        /* Propagate WARN_ON_WRITE through views. */
199 1
        if (PyArray_FLAGS(obj_arr) & NPY_ARRAY_WARN_ON_WRITE) {
200 1
            PyArray_ENABLEFLAGS(arr, NPY_ARRAY_WARN_ON_WRITE);
201
        }
202

203
        /* If this array owns its own data, stop collapsing */
204 1
        if (PyArray_CHKFLAGS(obj_arr, NPY_ARRAY_OWNDATA)) {
205
            break;
206
        }
207

208 1
        tmp = PyArray_BASE(obj_arr);
209
        /* If there's no base, stop collapsing */
210 1
        if (tmp == NULL) {
211
            break;
212
        }
213
        /* Stop the collapse new base when the would not be of the same
214
         * type (i.e. different subclass).
215
         */
216 1
        if (Py_TYPE(tmp) != Py_TYPE(arr)) {
217
            break;
218
        }
219

220

221 1
        Py_INCREF(tmp);
222 1
        Py_DECREF(obj);
223
        obj = tmp;
224
    }
225

226
    /* Disallow circular references */
227 1
    if ((PyObject *)arr == obj) {
228 0
        Py_DECREF(obj);
229 0
        PyErr_SetString(PyExc_ValueError,
230
                "Cannot create a circular NumPy array 'base' dependency");
231 0
        return -1;
232
    }
233

234 1
    ((PyArrayObject_fields *)arr)->base = obj;
235

236 1
    return 0;
237
}
238

239

240
/**
241
 * Assign an arbitrary object a NumPy array. This is largely basically
242
 * identical to PyArray_FromAny, but assigns directly to the output array.
243
 *
244
 * @param dest Array to be written to
245
 * @param src_object Object to be assigned, array-coercion rules apply.
246
 * @return 0 on success -1 on failures.
247
 */
248
/*NUMPY_API*/
249
NPY_NO_EXPORT int
250 1
PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
251
{
252 1
    int ret = 0;
253
    PyArrayObject *view;
254 1
    PyArray_Descr *dtype = NULL;
255
    int ndim;
256
    npy_intp dims[NPY_MAXDIMS];
257 1
    coercion_cache_obj *cache = NULL;
258

259
    /*
260
     * We have to set the maximum number of dimensions here to support
261
     * sequences within object arrays.
262
     */
263 1
    ndim = PyArray_DiscoverDTypeAndShape(src_object,
264
            PyArray_NDIM(dest), dims, &cache,
265 1
            NPY_DTYPE(PyArray_DESCR(dest)), PyArray_DESCR(dest), &dtype);
266 1
    if (ndim < 0) {
267
        return -1;
268
    }
269

270 1
    if (cache != NULL && !(cache->sequence)) {
271
        /* The input is an array or array object, so assign directly */
272
        assert(cache->converted_obj == src_object);
273 1
        view = (PyArrayObject *)cache->arr_or_sequence;
274 1
        Py_DECREF(dtype);
275 1
        ret = PyArray_AssignArray(dest, view, NULL, NPY_UNSAFE_CASTING);
276 1
        npy_free_coercion_cache(cache);
277 1
        return ret;
278
    }
279

280
    /*
281
     * We may need to broadcast, due to shape mismatches, in this case
282
     * create a temporary array first, and assign that after filling
283
     * it from the sequences/scalar.
284
     */
285 1
    if (ndim != PyArray_NDIM(dest) ||
286 1
            !PyArray_CompareLists(PyArray_DIMS(dest), dims, ndim)) {
287
        /*
288
         * Broadcasting may be necessary, so assign to a view first.
289
         * This branch could lead to a shape mismatch error later.
290
         */
291
        assert (ndim <= PyArray_NDIM(dest));  /* would error during discovery */
292 1
        view = (PyArrayObject *) PyArray_NewFromDescr(
293
                &PyArray_Type, dtype, ndim, dims, NULL, NULL,
294 1
                PyArray_FLAGS(dest) & NPY_ARRAY_F_CONTIGUOUS, NULL);
295 1
        if (view == NULL) {
296 0
            npy_free_coercion_cache(cache);
297 0
            return -1;
298
        }
299
    }
300
    else {
301 1
        Py_DECREF(dtype);
302
        view = dest;
303
    }
304

305
    /* Assign the values to `view` (whichever array that is) */
306 1
    if (cache == NULL) {
307
        /* single (non-array) item, assign immediately */
308 1
        if (PyArray_Pack(
309 1
                PyArray_DESCR(view), PyArray_DATA(view), src_object) < 0) {
310
            goto fail;
311
        }
312
    }
313
    else {
314 1
        if (PyArray_AssignFromCache(view, cache) < 0) {
315
            goto fail;
316
        }
317
    }
318 1
    if (view == dest) {
319
        return 0;
320
    }
321 1
    ret = PyArray_AssignArray(dest, view, NULL, NPY_UNSAFE_CASTING);
322 1
    Py_DECREF(view);
323
    return ret;
324

325 0
  fail:
326 0
    if (view != dest) {
327 0
        Py_DECREF(view);
328
    }
329
    return -1;
330
}
331

332

333
/* returns an Array-Scalar Object of the type of arr
334
   from the given pointer to memory -- main Scalar creation function
335
   default new method calls this.
336
*/
337

338
/* Ideally, here the descriptor would contain all the information needed.
339
   So, that we simply need the data and the descriptor, and perhaps
340
   a flag
341
*/
342

343

344
/*
345
  Given a string return the type-number for
346
  the data-type with that string as the type-object name.
347
  Returns NPY_NOTYPE without setting an error if no type can be
348
  found.  Only works for user-defined data-types.
349
*/
350

351
/*NUMPY_API
352
 */
353
NPY_NO_EXPORT int
354 0
PyArray_TypeNumFromName(char const *str)
355
{
356
    int i;
357
    PyArray_Descr *descr;
358

359 0
    for (i = 0; i < NPY_NUMUSERTYPES; i++) {
360 0
        descr = userdescrs[i];
361 0
        if (strcmp(descr->typeobj->tp_name, str) == 0) {
362 0
            return descr->type_num;
363
        }
364
    }
365
    return NPY_NOTYPE;
366
}
367

368
/*NUMPY_API
369
 *
370
 * If WRITEBACKIFCOPY and self has data, reset the base WRITEABLE flag,
371
 * copy the local data to base, release the local data, and set flags
372
 * appropriately. Return 0 if not relevant, 1 if success, < 0 on failure
373
 */
374
NPY_NO_EXPORT int
375 1
PyArray_ResolveWritebackIfCopy(PyArrayObject * self)
376
{
377 1
    PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
378 1
    if (fa && fa->base) {
379 1
        if ((fa->flags & NPY_ARRAY_UPDATEIFCOPY) || (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY)) {
380
            /*
381
             * UPDATEIFCOPY or WRITEBACKIFCOPY means that fa->base's data
382
             * should be updated with the contents
383
             * of self.
384
             * fa->base->flags is not WRITEABLE to protect the relationship
385
             * unlock it.
386
             */
387 1
            int retval = 0;
388 1
            PyArray_ENABLEFLAGS(((PyArrayObject *)fa->base),
389
                                                    NPY_ARRAY_WRITEABLE);
390 1
            PyArray_CLEARFLAGS(self, NPY_ARRAY_UPDATEIFCOPY);
391 1
            PyArray_CLEARFLAGS(self, NPY_ARRAY_WRITEBACKIFCOPY);
392 1
            retval = PyArray_CopyAnyInto((PyArrayObject *)fa->base, self);
393 1
            Py_DECREF(fa->base);
394 1
            fa->base = NULL;
395 1
            if (retval < 0) {
396
                /* this should never happen, how did the two copies of data
397
                 * get out of sync?
398
                 */
399
                return retval;
400
            }
401 1
            return 1;
402
        }
403
    }
404
    return 0;
405
}
406

407
/*********************** end C-API functions **********************/
408

409

410
/* dealloc must not raise an error, best effort try to write
411
   to stderr and clear the error
412
*/
413

414
static NPY_INLINE void
415 1
WARN_IN_DEALLOC(PyObject* warning, const char * msg) {
416 1
    if (PyErr_WarnEx(warning, msg, 1) < 0) {
417
        PyObject * s;
418

419 0
        s = PyUnicode_FromString("array_dealloc");
420 0
        if (s) {
421 0
            PyErr_WriteUnraisable(s);
422 0
            Py_DECREF(s);
423
        }
424
        else {
425 0
            PyErr_WriteUnraisable(Py_None);
426
        }
427
    }
428
}
429

430
/* array object functions */
431

432
static void
433 1
array_dealloc(PyArrayObject *self)
434
{
435 1
    PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
436

437 1
    _dealloc_cached_buffer_info((PyObject*)self);
438

439 1
    if (fa->weakreflist != NULL) {
440 1
        PyObject_ClearWeakRefs((PyObject *)self);
441
    }
442 1
    if (fa->base) {
443
        int retval;
444 1
        if (PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY)
445
        {
446 1
            char const * msg = "WRITEBACKIFCOPY detected in array_dealloc. "
447
                " Required call to PyArray_ResolveWritebackIfCopy or "
448
                "PyArray_DiscardWritebackIfCopy is missing.";
449
            /*
450
             * prevent reaching 0 twice and thus recursing into dealloc.
451
             * Increasing sys.gettotalrefcount, but path should not be taken.
452
             */
453 1
            Py_INCREF(self);
454 1
            WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg);
455 1
            retval = PyArray_ResolveWritebackIfCopy(self);
456 1
            if (retval < 0)
457
            {
458 0
                PyErr_Print();
459 0
                PyErr_Clear();
460
            }
461
        }
462 1
        if (PyArray_FLAGS(self) & NPY_ARRAY_UPDATEIFCOPY) {
463
            /* DEPRECATED, remove once the flag is removed */
464 0
            char const * msg = "UPDATEIFCOPY detected in array_dealloc. "
465
                " Required call to PyArray_ResolveWritebackIfCopy or "
466
                "PyArray_DiscardWritebackIfCopy is missing";
467
            /*
468
             * prevent reaching 0 twice and thus recursing into dealloc.
469
             * Increasing sys.gettotalrefcount, but path should not be taken.
470
             */
471 0
            Py_INCREF(self);
472
            /* 2017-Nov-10 1.14 */
473 0
            WARN_IN_DEALLOC(PyExc_DeprecationWarning, msg);
474 0
            retval = PyArray_ResolveWritebackIfCopy(self);
475 0
            if (retval < 0)
476
            {
477 0
                PyErr_Print();
478 0
                PyErr_Clear();
479
            }
480
        }
481
        /*
482
         * If fa->base is non-NULL, it is something
483
         * to DECREF -- either a view or a buffer object
484
         */
485 1
        Py_XDECREF(fa->base);
486
    }
487

488 1
    if ((fa->flags & NPY_ARRAY_OWNDATA) && fa->data) {
489
        /* Free internal references if an Object array */
490 1
        if (PyDataType_FLAGCHK(fa->descr, NPY_ITEM_REFCOUNT)) {
491 1
            PyArray_XDECREF(self);
492
        }
493 1
        npy_free_cache(fa->data, PyArray_NBYTES(self));
494
    }
495

496
    /* must match allocation in PyArray_NewFromDescr */
497 1
    npy_free_cache_dim(fa->dimensions, 2 * fa->nd);
498 1
    Py_DECREF(fa->descr);
499 1
    Py_TYPE(self)->tp_free((PyObject *)self);
500
}
501

502
/*NUMPY_API
503
 * Prints the raw data of the ndarray in a form useful for debugging
504
 * low-level C issues.
505
 */
506
NPY_NO_EXPORT void
507 0
PyArray_DebugPrint(PyArrayObject *obj)
508
{
509
    int i;
510 0
    PyArrayObject_fields *fobj = (PyArrayObject_fields *)obj;
511

512 0
    printf("-------------------------------------------------------\n");
513 0
    printf(" Dump of NumPy ndarray at address %p\n", obj);
514 0
    if (obj == NULL) {
515 0
        printf(" It's NULL!\n");
516 0
        printf("-------------------------------------------------------\n");
517 0
        fflush(stdout);
518 0
        return;
519
    }
520 0
    printf(" ndim   : %d\n", fobj->nd);
521 0
    printf(" shape  :");
522 0
    for (i = 0; i < fobj->nd; ++i) {
523 0
        printf(" %" NPY_INTP_FMT, fobj->dimensions[i]);
524
    }
525 0
    printf("\n");
526

527 0
    printf(" dtype  : ");
528 0
    PyObject_Print((PyObject *)fobj->descr, stdout, 0);
529 0
    printf("\n");
530 0
    printf(" data   : %p\n", fobj->data);
531 0
    printf(" strides:");
532 0
    for (i = 0; i < fobj->nd; ++i) {
533 0
        printf(" %" NPY_INTP_FMT, fobj->strides[i]);
534
    }
535 0
    printf("\n");
536

537 0
    printf(" base   : %p\n", fobj->base);
538

539 0
    printf(" flags :");
540 0
    if (fobj->flags & NPY_ARRAY_C_CONTIGUOUS)
541
        printf(" NPY_C_CONTIGUOUS");
542 0
    if (fobj->flags & NPY_ARRAY_F_CONTIGUOUS)
543
        printf(" NPY_F_CONTIGUOUS");
544 0
    if (fobj->flags & NPY_ARRAY_OWNDATA)
545
        printf(" NPY_OWNDATA");
546 0
    if (fobj->flags & NPY_ARRAY_ALIGNED)
547
        printf(" NPY_ALIGNED");
548 0
    if (fobj->flags & NPY_ARRAY_WRITEABLE)
549
        printf(" NPY_WRITEABLE");
550 0
    if (fobj->flags & NPY_ARRAY_UPDATEIFCOPY)
551
        printf(" NPY_UPDATEIFCOPY");
552 0
    if (fobj->flags & NPY_ARRAY_WRITEBACKIFCOPY)
553
        printf(" NPY_WRITEBACKIFCOPY");
554 0
    printf("\n");
555

556 0
    if (fobj->base != NULL && PyArray_Check(fobj->base)) {
557 0
        printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
558 0
        printf("Dump of array's BASE:\n");
559 0
        PyArray_DebugPrint((PyArrayObject *)fobj->base);
560
        printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
561
    }
562 0
    printf("-------------------------------------------------------\n");
563 0
    fflush(stdout);
564
}
565

566

567
/*NUMPY_API
568
 * This function is scheduled to be removed
569
 *
570
 * TO BE REMOVED - NOT USED INTERNALLY.
571
 */
572
NPY_NO_EXPORT void
573 0
PyArray_SetDatetimeParseFunction(PyObject *NPY_UNUSED(op))
574
{
575
}
576

577
/*NUMPY_API
578
 */
579
NPY_NO_EXPORT int
580 0
PyArray_CompareUCS4(npy_ucs4 const *s1, npy_ucs4 const *s2, size_t len)
581
{
582
    npy_ucs4 c1, c2;
583 1
    while(len-- > 0) {
584 1
        c1 = *s1++;
585 1
        c2 = *s2++;
586 1
        if (c1 != c2) {
587 1
            return (c1 < c2) ? -1 : 1;
588
        }
589
    }
590
    return 0;
591
}
592

593
/*NUMPY_API
594
 */
595
NPY_NO_EXPORT int
596 0
PyArray_CompareString(const char *s1, const char *s2, size_t len)
597
{
598 0
    const unsigned char *c1 = (unsigned char *)s1;
599 0
    const unsigned char *c2 = (unsigned char *)s2;
600
    size_t i;
601

602 0
    for(i = 0; i < len; ++i) {
603 0
        if (c1[i] != c2[i]) {
604 0
            return (c1[i] > c2[i]) ? 1 : -1;
605
        }
606
    }
607
    return 0;
608
}
609

610

611
/* Call this from contexts where an array might be written to, but we have no
612
 * way to tell. (E.g., when converting to a read-write buffer.)
613
 */
614
NPY_NO_EXPORT int
615 1
array_might_be_written(PyArrayObject *obj)
616
{
617 1
    const char *msg =
618
        "Numpy has detected that you (may be) writing to an array with\n"
619
        "overlapping memory from np.broadcast_arrays. If this is intentional\n"
620
        "set the WRITEABLE flag True or make a copy immediately before writing.";
621 1
    if (PyArray_FLAGS(obj) & NPY_ARRAY_WARN_ON_WRITE) {
622 1
        if (DEPRECATE(msg) < 0) {
623
            return -1;
624
        }
625
        /* Only warn once per array */
626
        while (1) {
627 1
            PyArray_CLEARFLAGS(obj, NPY_ARRAY_WARN_ON_WRITE);
628 1
            if (!PyArray_BASE(obj) || !PyArray_Check(PyArray_BASE(obj))) {
629
                break;
630
            }
631 1
            obj = (PyArrayObject *)PyArray_BASE(obj);
632
        }
633
    }
634
    return 0;
635
}
636

637
/*NUMPY_API
638
 *
639
 * This function does nothing if obj is writeable, and raises an exception
640
 * (and returns -1) if obj is not writeable. It may also do other
641
 * house-keeping, such as issuing warnings on arrays which are transitioning
642
 * to become views. Always call this function at some point before writing to
643
 * an array.
644
 *
645
 * 'name' is a name for the array, used to give better error
646
 * messages. Something like "assignment destination", "output array", or even
647
 * just "array".
648
 */
649
NPY_NO_EXPORT int
650 1
PyArray_FailUnlessWriteable(PyArrayObject *obj, const char *name)
651
{
652 1
    if (!PyArray_ISWRITEABLE(obj)) {
653 1
        PyErr_Format(PyExc_ValueError, "%s is read-only", name);
654 1
        return -1;
655
    }
656 1
    if (array_might_be_written(obj) < 0) {
657
        return -1;
658
    }
659 1
    return 0;
660
}
661

662
/* This also handles possibly mis-aligned data */
663
/* Compare s1 and s2 which are not necessarily NULL-terminated.
664
   s1 is of length len1
665
   s2 is of length len2
666
   If they are NULL terminated, then stop comparison.
667
*/
668
static int
669 1
_myunincmp(npy_ucs4 const *s1, npy_ucs4 const *s2, int len1, int len2)
670
{
671
    npy_ucs4 const *sptr;
672 1
    npy_ucs4 *s1t = NULL;
673 1
    npy_ucs4 *s2t = NULL;
674
    int val;
675
    npy_intp size;
676
    int diff;
677

678
    /* Replace `s1` and `s2` with aligned copies if needed */
679 1
    if ((npy_intp)s1 % sizeof(npy_ucs4) != 0) {
680 1
        size = len1*sizeof(npy_ucs4);
681 1
        s1t = malloc(size);
682 1
        memcpy(s1t, s1, size);
683 1
        s1 = s1t;
684
    }
685 1
    if ((npy_intp)s2 % sizeof(npy_ucs4) != 0) {
686 0
        size = len2*sizeof(npy_ucs4);
687 0
        s2t = malloc(size);
688 0
        memcpy(s2t, s2, size);
689 0
        s2 = s1t;
690
    }
691

692 1
    val = PyArray_CompareUCS4(s1, s2, PyArray_MIN(len1,len2));
693 1
    if ((val != 0) || (len1 == len2)) {
694
        goto finish;
695
    }
696 1
    if (len2 > len1) {
697 1
        sptr = s2+len1;
698 1
        val = -1;
699 1
        diff = len2-len1;
700
    }
701
    else {
702 1
        sptr = s1+len2;
703 1
        val = 1;
704 1
        diff=len1-len2;
705
    }
706 1
    while (diff--) {
707 1
        if (*sptr != 0) {
708
            goto finish;
709
        }
710 1
        sptr++;
711
    }
712
    val = 0;
713

714 1
 finish:
715
    /* Cleanup the aligned copies */
716 1
    if (s1t) {
717 1
        free(s1t);
718
    }
719 1
    if (s2t) {
720 0
        free(s2t);
721
    }
722 1
    return val;
723
}
724

725

726

727

728
/*
729
 * Compare s1 and s2 which are not necessarily NULL-terminated.
730
 * s1 is of length len1
731
 * s2 is of length len2
732
 * If they are NULL terminated, then stop comparison.
733
 */
734
static int
735 1
_mystrncmp(char const *s1, char const *s2, int len1, int len2)
736
{
737
    char const *sptr;
738
    int val;
739
    int diff;
740

741 1
    val = memcmp(s1, s2, PyArray_MIN(len1, len2));
742 1
    if ((val != 0) || (len1 == len2)) {
743
        return val;
744
    }
745 1
    if (len2 > len1) {
746 1
        sptr = s2 + len1;
747 1
        val = -1;
748 1
        diff = len2 - len1;
749
    }
750
    else {
751 1
        sptr = s1 + len2;
752 1
        val = 1;
753 1
        diff = len1 - len2;
754
    }
755 1
    while (diff--) {
756 1
        if (*sptr != 0) {
757
            return val;
758
        }
759 1
        sptr++;
760
    }
761
    return 0; /* Only happens if NULLs are everywhere */
762
}
763

764
/* Borrowed from Numarray */
765

766
#define SMALL_STRING 2048
767

768 1
static void _rstripw(char *s, int n)
769
{
770
    int i;
771 1
    for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
772 1
        int c = s[i];
773

774 1
        if (!c || NumPyOS_ascii_isspace((int)c)) {
775 1
            s[i] = 0;
776
        }
777
        else {
778
            break;
779
        }
780
    }
781
}
782

783 1
static void _unistripw(npy_ucs4 *s, int n)
784
{
785
    int i;
786 1
    for (i = n - 1; i >= 1; i--) { /* Never strip to length 0. */
787 1
        npy_ucs4 c = s[i];
788 1
        if (!c || NumPyOS_ascii_isspace((int)c)) {
789 1
            s[i] = 0;
790
        }
791
        else {
792
            break;
793
        }
794
    }
795
}
796

797

798
static char *
799 1
_char_copy_n_strip(char const *original, char *temp, int nc)
800
{
801 1
    if (nc > SMALL_STRING) {
802 0
        temp = malloc(nc);
803 0
        if (!temp) {
804 0
            PyErr_NoMemory();
805 0
            return NULL;
806
        }
807
    }
808 1
    memcpy(temp, original, nc);
809 1
    _rstripw(temp, nc);
810 1
    return temp;
811
}
812

813
static void
814 1
_char_release(char *ptr, int nc)
815
{
816 1
    if (nc > SMALL_STRING) {
817 0
        free(ptr);
818
    }
819
}
820

821
static char *
822 1
_uni_copy_n_strip(char const *original, char *temp, int nc)
823
{
824 1
    if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
825 1
        temp = malloc(nc*sizeof(npy_ucs4));
826 1
        if (!temp) {
827 0
            PyErr_NoMemory();
828 0
            return NULL;
829
        }
830
    }
831 1
    memcpy(temp, original, nc*sizeof(npy_ucs4));
832 1
    _unistripw((npy_ucs4 *)temp, nc);
833 1
    return temp;
834
}
835

836
static void
837 1
_uni_release(char *ptr, int nc)
838
{
839 1
    if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
840 1
        free(ptr);
841
    }
842
}
843

844

845
/* End borrowed from numarray */
846

847
#define _rstrip_loop(CMP) {                                     \
848
        void *aptr, *bptr;                                      \
849
        char atemp[SMALL_STRING], btemp[SMALL_STRING];          \
850
        while(size--) {                                         \
851
            aptr = stripfunc(iself->dataptr, atemp, N1);        \
852
            if (!aptr) return -1;                               \
853
            bptr = stripfunc(iother->dataptr, btemp, N2);       \
854
            if (!bptr) {                                        \
855
                relfunc(aptr, N1);                              \
856
                return -1;                                      \
857
            }                                                   \
858
            val = compfunc(aptr, bptr, N1, N2);                  \
859
            *dptr = (val CMP 0);                                \
860
            PyArray_ITER_NEXT(iself);                           \
861
            PyArray_ITER_NEXT(iother);                          \
862
            dptr += 1;                                          \
863
            relfunc(aptr, N1);                                  \
864
            relfunc(bptr, N2);                                  \
865
        }                                                       \
866
    }
867

868
#define _reg_loop(CMP) {                                \
869
        while(size--) {                                 \
870
            val = compfunc((void *)iself->dataptr,       \
871
                          (void *)iother->dataptr,      \
872
                          N1, N2);                      \
873
            *dptr = (val CMP 0);                        \
874
            PyArray_ITER_NEXT(iself);                   \
875
            PyArray_ITER_NEXT(iother);                  \
876
            dptr += 1;                                  \
877
        }                                               \
878
    }
879

880
static int
881 1
_compare_strings(PyArrayObject *result, PyArrayMultiIterObject *multi,
882
                 int cmp_op, void *func, int rstrip)
883
{
884
    PyArrayIterObject *iself, *iother;
885
    npy_bool *dptr;
886
    npy_intp size;
887
    int val;
888
    int N1, N2;
889
    int (*compfunc)(void *, void *, int, int);
890
    void (*relfunc)(char *, int);
891
    char* (*stripfunc)(char const *, char *, int);
892

893 1
    compfunc = func;
894 1
    dptr = (npy_bool *)PyArray_DATA(result);
895 1
    iself = multi->iters[0];
896 1
    iother = multi->iters[1];
897 1
    size = multi->size;
898 1
    N1 = PyArray_DESCR(iself->ao)->elsize;
899 1
    N2 = PyArray_DESCR(iother->ao)->elsize;
900 1
    if ((void *)compfunc == (void *)_myunincmp) {
901 1
        N1 >>= 2;
902 1
        N2 >>= 2;
903 1
        stripfunc = _uni_copy_n_strip;
904 1
        relfunc = _uni_release;
905
    }
906
    else {
907
        stripfunc = _char_copy_n_strip;
908
        relfunc = _char_release;
909
    }
910 1
    switch (cmp_op) {
911 1
    case Py_EQ:
912 1
        if (rstrip) {
913 1
            _rstrip_loop(==);
914
        } else {
915 1
            _reg_loop(==);
916
        }
917
        break;
918 1
    case Py_NE:
919 1
        if (rstrip) {
920 1
            _rstrip_loop(!=);
921
        } else {
922 1
            _reg_loop(!=);
923
        }
924
        break;
925 1
    case Py_LT:
926 1
        if (rstrip) {
927 1
            _rstrip_loop(<);
928
        } else {
929 1
            _reg_loop(<);
930
        }
931
        break;
932 1
    case Py_LE:
933 1
        if (rstrip) {
934 1
            _rstrip_loop(<=);
935
        } else {
936 1
            _reg_loop(<=);
937
        }
938
        break;
939 1
    case Py_GT:
940 1
        if (rstrip) {
941 1
            _rstrip_loop(>);
942
        } else {
943 1
            _reg_loop(>);
944
        }
945
        break;
946 1
    case Py_GE:
947 1
        if (rstrip) {
948 1
            _rstrip_loop(>=);
949
        } else {
950 1
            _reg_loop(>=);
951
        }
952
        break;
953 0
    default:
954 0
        PyErr_SetString(PyExc_RuntimeError, "bad comparison operator");
955 0
        return -1;
956
    }
957
    return 0;
958
}
959

960
#undef _reg_loop
961
#undef _rstrip_loop
962
#undef SMALL_STRING
963

964
NPY_NO_EXPORT PyObject *
965 1
_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
966
                     int rstrip)
967
{
968
    PyArrayObject *result;
969
    PyArrayMultiIterObject *mit;
970
    int val;
971

972
    /* Cast arrays to a common type */
973 1
    if (PyArray_TYPE(self) != PyArray_DESCR(other)->type_num) {
974
        /*
975
         * Comparison between Bytes and Unicode is not defined in Py3K;
976
         * we follow.
977
         */
978 1
        Py_INCREF(Py_NotImplemented);
979 1
        return Py_NotImplemented;
980
    }
981 1
    if (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other)) {
982
        PyObject *new;
983 1
        if (PyArray_TYPE(self) == NPY_STRING &&
984
                PyArray_DESCR(other)->type_num == NPY_UNICODE) {
985
            PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(other));
986
            unicode->elsize = PyArray_DESCR(self)->elsize << 2;
987
            new = PyArray_FromAny((PyObject *)self, unicode,
988
                                  0, 0, 0, NULL);
989
            if (new == NULL) {
990
                return NULL;
991
            }
992
            Py_INCREF(other);
993
            self = (PyArrayObject *)new;
994
        }
995 1
        else if ((PyArray_TYPE(self) == NPY_UNICODE) &&
996 1
                 ((PyArray_DESCR(other)->type_num == NPY_STRING) ||
997 1
                 (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other)))) {
998 1
            PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(self));
999

1000 1
            if (PyArray_DESCR(other)->type_num == NPY_STRING) {
1001 0
                unicode->elsize = PyArray_DESCR(other)->elsize << 2;
1002
            }
1003
            else {
1004 1
                unicode->elsize = PyArray_DESCR(other)->elsize;
1005
            }
1006 1
            new = PyArray_FromAny((PyObject *)other, unicode,
1007
                                  0, 0, 0, NULL);
1008 1
            if (new == NULL) {
1009
                return NULL;
1010
            }
1011 1
            Py_INCREF(self);
1012 1
            other = (PyArrayObject *)new;
1013
        }
1014
        else {
1015 0
            PyErr_SetString(PyExc_TypeError,
1016
                            "invalid string data-types "
1017
                            "in comparison");
1018 0
            return NULL;
1019
        }
1020
    }
1021
    else {
1022 1
        Py_INCREF(self);
1023 1
        Py_INCREF(other);
1024
    }
1025

1026
    /* Broad-cast the arrays to a common shape */
1027 1
    mit = (PyArrayMultiIterObject *)PyArray_MultiIterNew(2, self, other);
1028 1
    Py_DECREF(self);
1029 1
    Py_DECREF(other);
1030 1
    if (mit == NULL) {
1031
        return NULL;
1032
    }
1033

1034 1
    result = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
1035
                                  PyArray_DescrFromType(NPY_BOOL),
1036
                                  mit->nd,
1037 1
                                  mit->dimensions,
1038
                                  NULL, NULL, 0,
1039
                                  NULL);
1040 1
    if (result == NULL) {
1041
        goto finish;
1042
    }
1043

1044 1
    if (PyArray_TYPE(self) == NPY_UNICODE) {
1045 1
        val = _compare_strings(result, mit, cmp_op, _myunincmp, rstrip);
1046
    }
1047
    else {
1048 1
        val = _compare_strings(result, mit, cmp_op, _mystrncmp, rstrip);
1049
    }
1050

1051 1
    if (val < 0) {
1052 0
        Py_DECREF(result);
1053
        result = NULL;
1054
    }
1055

1056 1
 finish:
1057 1
    Py_DECREF(mit);
1058
    return (PyObject *)result;
1059
}
1060

1061
/*
1062
 * VOID-type arrays can only be compared equal and not-equal
1063
 * in which case the fields are all compared by extracting the fields
1064
 * and testing one at a time...
1065
 * equality testing is performed using logical_ands on all the fields.
1066
 * in-equality testing is performed using logical_ors on all the fields.
1067
 *
1068
 * VOID-type arrays without fields are compared for equality by comparing their
1069
 * memory at each location directly (using string-code).
1070
 */
1071
static PyObject *
1072 1
_void_compare(PyArrayObject *self, PyArrayObject *other, int cmp_op)
1073
{
1074 1
    if (!(cmp_op == Py_EQ || cmp_op == Py_NE)) {
1075 0
        PyErr_SetString(PyExc_ValueError,
1076
                "Void-arrays can only be compared for equality.");
1077 0
        return NULL;
1078
    }
1079 1
    if (PyArray_HASFIELDS(self)) {
1080 1
        PyObject *res = NULL, *temp, *a, *b;
1081
        PyObject *key, *value, *temp2;
1082
        PyObject *op;
1083 1
        Py_ssize_t pos = 0;
1084 1
        npy_intp result_ndim = PyArray_NDIM(self) > PyArray_NDIM(other) ?
1085 1
                            PyArray_NDIM(self) : PyArray_NDIM(other);
1086

1087 1
        op = (cmp_op == Py_EQ ? n_ops.logical_and : n_ops.logical_or);
1088 1
        while (PyDict_Next(PyArray_DESCR(self)->fields, &pos, &key, &value)) {
1089 1
            if (NPY_TITLE_KEY(key, value)) {
1090 1
                continue;
1091
            }
1092 1
            a = array_subscript_asarray(self, key);
1093 1
            if (a == NULL) {
1094 0
                Py_XDECREF(res);
1095
                return NULL;
1096
            }
1097 1
            b = array_subscript_asarray(other, key);
1098 1
            if (b == NULL) {
1099 0
                Py_XDECREF(res);
1100 0
                Py_DECREF(a);
1101
                return NULL;
1102
            }
1103 1
            temp = array_richcompare((PyArrayObject *)a,b,cmp_op);
1104 1
            Py_DECREF(a);
1105 1
            Py_DECREF(b);
1106 1
            if (temp == NULL) {
1107 1
                Py_XDECREF(res);
1108
                return NULL;
1109
            }
1110

1111
            /*
1112
             * If the field type has a non-trivial shape, additional
1113
             * dimensions will have been appended to `a` and `b`.
1114
             * In that case, reduce them using `op`.
1115
             */
1116 1
            if (PyArray_Check(temp) &&
1117 1
                        PyArray_NDIM((PyArrayObject *)temp) > result_ndim) {
1118
                /* If the type was multidimensional, collapse that part to 1-D
1119
                 */
1120 1
                if (PyArray_NDIM((PyArrayObject *)temp) != result_ndim+1) {
1121
                    npy_intp dimensions[NPY_MAXDIMS];
1122
                    PyArray_Dims newdims;
1123

1124 1
                    newdims.ptr = dimensions;
1125 1
                    newdims.len = result_ndim+1;
1126 1
                    if (result_ndim) {
1127 1
                        memcpy(dimensions, PyArray_DIMS((PyArrayObject *)temp),
1128
                               sizeof(npy_intp)*result_ndim);
1129
                    }
1130 1
                    dimensions[result_ndim] = -1;
1131 1
                    temp2 = PyArray_Newshape((PyArrayObject *)temp,
1132
                                             &newdims, NPY_ANYORDER);
1133 1
                    if (temp2 == NULL) {
1134 0
                        Py_DECREF(temp);
1135 0
                        Py_XDECREF(res);
1136 0
                        return NULL;
1137
                    }
1138 1
                    Py_DECREF(temp);
1139 1
                    temp = temp2;
1140
                }
1141
                /* Reduce the extra dimension of `temp` using `op` */
1142 1
                temp2 = PyArray_GenericReduceFunction((PyArrayObject *)temp,
1143
                                                      op, result_ndim,
1144
                                                      NPY_BOOL, NULL);
1145 1
                if (temp2 == NULL) {
1146 0
                    Py_DECREF(temp);
1147 0
                    Py_XDECREF(res);
1148
                    return NULL;
1149
                }
1150 1
                Py_DECREF(temp);
1151
                temp = temp2;
1152
            }
1153

1154 1
            if (res == NULL) {
1155
                res = temp;
1156
            }
1157
            else {
1158 1
                temp2 = PyObject_CallFunction(op, "OO", res, temp);
1159 1
                Py_DECREF(temp);
1160 1
                Py_DECREF(res);
1161 1
                if (temp2 == NULL) {
1162
                    return NULL;
1163
                }
1164
                res = temp2;
1165
            }
1166
        }
1167 1
        if (res == NULL && !PyErr_Occurred()) {
1168
            /* these dtypes had no fields. Use a MultiIter to broadcast them
1169
             * to an output array, and fill with True (for EQ)*/
1170 1
            PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)
1171
                                          PyArray_MultiIterNew(2, self, other);
1172 1
            if (mit == NULL) {
1173
                return NULL;
1174
            }
1175

1176 1
            res = PyArray_NewFromDescr(&PyArray_Type,
1177
                                       PyArray_DescrFromType(NPY_BOOL),
1178 1
                                       mit->nd, mit->dimensions,
1179
                                       NULL, NULL, 0, NULL);
1180 1
            Py_DECREF(mit);
1181 1
            if (res) {
1182 1
                 PyArray_FILLWBYTE((PyArrayObject *)res,
1183
                                   cmp_op == Py_EQ ? 1 : 0);
1184
            }
1185
        }
1186
        return res;
1187
    }
1188
    else {
1189
        /* compare as a string. Assumes self and other have same descr->type */
1190 1
        return _strings_richcompare(self, other, cmp_op, 0);
1191
    }
1192
}
1193

1194
/*
1195
 * Silence the current error and emit a deprecation warning instead.
1196
 *
1197
 * If warnings are raised as errors, this sets the warning __cause__ to the
1198
 * silenced error.
1199
 */
1200
NPY_NO_EXPORT int
1201 0
DEPRECATE_silence_error(const char *msg) {
1202
    PyObject *exc, *val, *tb;
1203 0
    PyErr_Fetch(&exc, &val, &tb);
1204 0
    if (DEPRECATE(msg) < 0) {
1205 0
        npy_PyErr_ChainExceptionsCause(exc, val, tb);
1206 0
        return -1;
1207
    }
1208 0
    Py_XDECREF(exc);
1209 0
    Py_XDECREF(val);
1210 0
    Py_XDECREF(tb);
1211
    return 0;
1212
}
1213

1214
/*
1215
 * Comparisons can fail, but we do not always want to pass on the exception
1216
 * (see comment in array_richcompare below), but rather return NotImplemented.
1217
 * Here, an exception should be set on entrance.
1218
 * Returns either NotImplemented with the exception cleared, or NULL
1219
 * with the exception set.
1220
 * Raises deprecation warnings for cases where behaviour is meant to change
1221
 * (2015-05-14, 1.10)
1222
 */
1223

1224
NPY_NO_EXPORT PyObject *
1225 1
_failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
1226
{
1227
    PyObject *exc, *val, *tb;
1228
    PyArrayObject *array_other;
1229
    int other_is_flexible, ndim_other;
1230 1
    int self_is_flexible = PyTypeNum_ISFLEXIBLE(PyArray_DESCR(self)->type_num);
1231

1232 1
    PyErr_Fetch(&exc, &val, &tb);
1233
    /*
1234
     * Determine whether other has a flexible dtype; here, inconvertible
1235
     * is counted as inflexible.  (This repeats work done in the ufunc,
1236
     * but OK to waste some time in an unlikely path.)
1237
     */
1238 1
    array_other = (PyArrayObject *)PyArray_FROM_O(other);
1239 1
    if (array_other) {
1240 1
        other_is_flexible = PyTypeNum_ISFLEXIBLE(
1241
            PyArray_DESCR(array_other)->type_num);
1242 1
        ndim_other = PyArray_NDIM(array_other);
1243 1
        Py_DECREF(array_other);
1244
    }
1245
    else {
1246 1
        PyErr_Clear(); /* we restore the original error if needed */
1247 1
        other_is_flexible = 0;
1248 1
        ndim_other = 0;
1249
    }
1250 1
    if (cmp_op == Py_EQ || cmp_op == Py_NE) {
1251
        /*
1252
         * note: for == and !=, a structured dtype self cannot get here,
1253
         * but a string can. Other can be string or structured.
1254
         */
1255 1
        if (other_is_flexible || self_is_flexible) {
1256
            /*
1257
             * For scalars, returning NotImplemented is correct.
1258
             * For arrays, we emit a future deprecation warning.
1259
             * When this warning is removed, a correctly shaped
1260
             * array of bool should be returned.
1261
             */
1262 1
            if (ndim_other != 0 || PyArray_NDIM(self) != 0) {
1263
                /* 2015-05-14, 1.10 */
1264 1
                if (DEPRECATE_FUTUREWARNING(
1265
                        "elementwise comparison failed; returning scalar "
1266
                        "instead, but in the future will perform "
1267
                        "elementwise comparison") < 0) {
1268
                    goto fail;
1269
                }
1270
            }
1271
        }
1272
        else {
1273
            /*
1274
             * If neither self nor other had a flexible dtype, the error cannot
1275
             * have been caused by a lack of implementation in the ufunc.
1276
             *
1277
             * 2015-05-14, 1.10
1278
             */
1279 1
            if (DEPRECATE(
1280
                    "elementwise comparison failed; "
1281
                    "this will raise an error in the future.") < 0) {
1282
                goto fail;
1283
            }
1284
        }
1285 1
        Py_XDECREF(exc);
1286 1
        Py_XDECREF(val);
1287 1
        Py_XDECREF(tb);
1288 1
        Py_INCREF(Py_NotImplemented);
1289 1
        return Py_NotImplemented;
1290
    }
1291 1
    else if (other_is_flexible || self_is_flexible) {
1292
        /*
1293
         * For LE, LT, GT, GE and a flexible self or other, we return
1294
         * NotImplemented, which is the correct answer since the ufuncs do
1295
         * not in fact implement loops for those.  This will get us the
1296
         * desired TypeError.
1297
         */
1298 1
        Py_XDECREF(exc);
1299 1
        Py_XDECREF(val);
1300 1
        Py_XDECREF(tb);
1301 1
        Py_INCREF(Py_NotImplemented);
1302 1
        return Py_NotImplemented;
1303
    }
1304
    else {
1305
        /* LE, LT, GT, or GE with non-flexible other; just pass on error */
1306
        goto fail;
1307
    }
1308

1309 1
fail:
1310
    /*
1311
     * Reraise the original exception, possibly chaining with a new one.
1312
     */
1313 1
    npy_PyErr_ChainExceptionsCause(exc, val, tb);
1314 1
    return NULL;
1315
}
1316

1317
NPY_NO_EXPORT PyObject *
1318 1
array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
1319
{
1320
    PyArrayObject *array_other;
1321 1
    PyObject *obj_self = (PyObject *)self;
1322 1
    PyObject *result = NULL;
1323

1324
    /* Special case for string arrays (which don't and currently can't have
1325
     * ufunc loops defined, so there's no point in trying).
1326
     */
1327 1
    if (PyArray_ISSTRING(self)) {
1328 1
        array_other = (PyArrayObject *)PyArray_FromObject(other,
1329
                                                          NPY_NOTYPE, 0, 0);
1330 1
        if (array_other == NULL) {
1331 0
            PyErr_Clear();
1332
            /* Never mind, carry on, see what happens */
1333
        }
1334 1
        else if (!PyArray_ISSTRING(array_other)) {
1335 1
            Py_DECREF(array_other);
1336
            /* Never mind, carry on, see what happens */
1337
        }
1338
        else {
1339 1
            result = _strings_richcompare(self, array_other, cmp_op, 0);
1340 1
            Py_DECREF(array_other);
1341
            return result;
1342
        }
1343
        /* If we reach this point, it means that we are not comparing
1344
         * string-to-string. It's possible that this will still work out,
1345
         * e.g. if the other array is an object array, then both will be cast
1346
         * to object or something? I don't know how that works actually, but
1347
         * it does, b/c this works:
1348
         *   l = ["a", "b"]
1349
         *   assert np.array(l, dtype="S1") == np.array(l, dtype="O")
1350
         * So we fall through and see what happens.
1351
         */
1352
    }
1353

1354 1
    switch (cmp_op) {
1355 1
    case Py_LT:
1356 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1357 1
        result = PyArray_GenericBinaryFunction(self, other, n_ops.less);
1358 1
        break;
1359 1
    case Py_LE:
1360 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1361 1
        result = PyArray_GenericBinaryFunction(self, other, n_ops.less_equal);
1362 1
        break;
1363 1
    case Py_EQ:
1364 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1365
        /*
1366
         * The ufunc does not support void/structured types, so these
1367
         * need to be handled specifically. Only a few cases are supported.
1368
         */
1369

1370 1
        if (PyArray_TYPE(self) == NPY_VOID) {
1371
            int _res;
1372

1373 1
            array_other = (PyArrayObject *)PyArray_FROM_O(other);
1374
            /*
1375
             * If not successful, indicate that the items cannot be compared
1376
             * this way.
1377
             */
1378 1
            if (array_other == NULL) {
1379
                /* 2015-05-07, 1.10 */
1380 0
                if (DEPRECATE_silence_error(
1381
                        "elementwise == comparison failed and returning scalar "
1382
                        "instead; this will raise an error in the future.") < 0) {
1383
                    return NULL;
1384
                }
1385 0
                Py_INCREF(Py_NotImplemented);
1386 0
                return Py_NotImplemented;
1387
            }
1388

1389 1
            _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1390
                                         PyArray_DESCR(array_other),
1391
                                         NPY_EQUIV_CASTING);
1392 1
            if (_res == 0) {
1393
                /* 2015-05-07, 1.10 */
1394 1
                Py_DECREF(array_other);
1395 1
                if (DEPRECATE_FUTUREWARNING(
1396
                        "elementwise == comparison failed and returning scalar "
1397
                        "instead; this will raise an error or perform "
1398
                        "elementwise comparison in the future.") < 0) {
1399
                    return NULL;
1400
                }
1401 1
                Py_INCREF(Py_False);
1402 1
                return Py_False;
1403
            }
1404
            else {
1405 1
                result = _void_compare(self, array_other, cmp_op);
1406
            }
1407 1
            Py_DECREF(array_other);
1408
            return result;
1409
        }
1410

1411 1
        result = PyArray_GenericBinaryFunction(self,
1412
                (PyObject *)other,
1413
                n_ops.equal);
1414 1
        break;
1415 1
    case Py_NE:
1416 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1417
        /*
1418
         * The ufunc does not support void/structured types, so these
1419
         * need to be handled specifically. Only a few cases are supported.
1420
         */
1421

1422 1
        if (PyArray_TYPE(self) == NPY_VOID) {
1423
            int _res;
1424

1425 1
            array_other = (PyArrayObject *)PyArray_FROM_O(other);
1426
            /*
1427
             * If not successful, indicate that the items cannot be compared
1428
             * this way.
1429
            */
1430 1
            if (array_other == NULL) {
1431
                /* 2015-05-07, 1.10 */
1432 0
                if (DEPRECATE_silence_error(
1433
                        "elementwise != comparison failed and returning scalar "
1434
                        "instead; this will raise an error in the future.") < 0) {
1435
                    return NULL;
1436
                }
1437 0
                Py_INCREF(Py_NotImplemented);
1438 0
                return Py_NotImplemented;
1439
            }
1440

1441 1
            _res = PyArray_CanCastTypeTo(PyArray_DESCR(self),
1442
                                         PyArray_DESCR(array_other),
1443
                                         NPY_EQUIV_CASTING);
1444 1
            if (_res == 0) {
1445
                /* 2015-05-07, 1.10 */
1446 1
                Py_DECREF(array_other);
1447 1
                if (DEPRECATE_FUTUREWARNING(
1448
                        "elementwise != comparison failed and returning scalar "
1449
                        "instead; this will raise an error or perform "
1450
                        "elementwise comparison in the future.") < 0) {
1451
                    return NULL;
1452
                }
1453 1
                Py_INCREF(Py_True);
1454 1
                return Py_True;
1455
            }
1456
            else {
1457 1
                result = _void_compare(self, array_other, cmp_op);
1458 1
                Py_DECREF(array_other);
1459
            }
1460
            return result;
1461
        }
1462

1463 1
        result = PyArray_GenericBinaryFunction(self, (PyObject *)other,
1464
                n_ops.not_equal);
1465 1
        break;
1466 1
    case Py_GT:
1467 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1468 1
        result = PyArray_GenericBinaryFunction(self, other,
1469
                n_ops.greater);
1470 1
        break;
1471 1
    case Py_GE:
1472 1
        RICHCMP_GIVE_UP_IF_NEEDED(obj_self, other);
1473 1
        result = PyArray_GenericBinaryFunction(self, other,
1474
                n_ops.greater_equal);
1475 1
        break;
1476 0
    default:
1477 0
        Py_INCREF(Py_NotImplemented);
1478 0
        return Py_NotImplemented;
1479
    }
1480 1
    if (result == NULL) {
1481
        /*
1482
         * 2015-05-14, 1.10; updated 2018-06-18, 1.16.
1483
         *
1484
         * Comparisons can raise errors when element-wise comparison is not
1485
         * possible. Some of these, though, should not be passed on.
1486
         * In particular, the ufuncs do not have loops for flexible dtype,
1487
         * so those should be treated separately.  Furthermore, for EQ and NE,
1488
         * we should never fail.
1489
         *
1490
         * Our ideal behaviour would be:
1491
         *
1492
         * 1. For EQ and NE:
1493
         *   - If self and other are scalars, return NotImplemented,
1494
         *     so that python can assign True of False as appropriate.
1495
         *   - If either is an array, return an array of False or True.
1496
         *
1497
         * 2. For LT, LE, GE, GT:
1498
         *   - If self or other was flexible, return NotImplemented
1499
         *     (as is in fact the case), so python can raise a TypeError.
1500
         *   - If other is not convertible to an array, pass on the error
1501
         *     (MHvK, 2018-06-18: not sure about this, but it's what we have).
1502
         *
1503
         * However, for backwards compatibility, we cannot yet return arrays,
1504
         * so we raise warnings instead.
1505
         */
1506 1
        result = _failed_comparison_workaround(self, other, cmp_op);
1507
    }
1508
    return result;
1509
}
1510

1511
/*NUMPY_API
1512
 */
1513
NPY_NO_EXPORT int
1514 0
PyArray_ElementStrides(PyObject *obj)
1515
{
1516
    PyArrayObject *arr;
1517
    int itemsize;
1518
    int i, ndim;
1519
    npy_intp *strides;
1520

1521 0
    if (!PyArray_Check(obj)) {
1522
        return 0;
1523
    }
1524

1525 0
    arr = (PyArrayObject *)obj;
1526

1527 0
    itemsize = PyArray_ITEMSIZE(arr);
1528 0
    ndim = PyArray_NDIM(arr);
1529 0
    strides = PyArray_STRIDES(arr);
1530

1531 0
    for (i = 0; i < ndim; i++) {
1532 0
        if ((strides[i] % itemsize) != 0) {
1533
            return 0;
1534
        }
1535
    }
1536
    return 1;
1537
}
1538

1539
/*
1540
 * This routine checks to see if newstrides (of length nd) will not
1541
 * ever be able to walk outside of the memory implied numbytes and offset.
1542
 *
1543
 * The available memory is assumed to start at -offset and proceed
1544
 * to numbytes-offset.  The strides are checked to ensure
1545
 * that accessing memory using striding will not try to reach beyond
1546
 * this memory for any of the axes.
1547
 *
1548
 * If numbytes is 0 it will be calculated using the dimensions and
1549
 * element-size.
1550
 *
1551
 * This function checks for walking beyond the beginning and right-end
1552
 * of the buffer and therefore works for any integer stride (positive
1553
 * or negative).
1554
 */
1555

1556
/*NUMPY_API*/
1557
NPY_NO_EXPORT npy_bool
1558 1
PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp offset,
1559
                     npy_intp const *dims, npy_intp const *newstrides)
1560
{
1561
    npy_intp begin, end;
1562
    npy_intp lower_offset;
1563
    npy_intp upper_offset;
1564

1565 1
    if (numbytes == 0) {
1566 1
        numbytes = PyArray_MultiplyList(dims, nd) * elsize;
1567
    }
1568

1569 1
    begin = -offset;
1570 1
    end = numbytes - offset;
1571

1572 1
    offset_bounds_from_strides(elsize, nd, dims, newstrides,
1573
                                        &lower_offset, &upper_offset);
1574

1575 1
    if ((upper_offset > end) || (lower_offset < begin)) {
1576
        return NPY_FALSE;
1577
    }
1578 1
    return NPY_TRUE;
1579
}
1580

1581

1582
static PyObject *
1583 1
array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
1584
{
1585
    static char *kwlist[] = {"shape", "dtype", "buffer", "offset", "strides",
1586
                             "order", NULL};
1587 1
    PyArray_Descr *descr = NULL;
1588
    int itemsize;
1589 1
    PyArray_Dims dims = {NULL, 0};
1590 1
    PyArray_Dims strides = {NULL, -1};
1591
    PyArray_Chunk buffer;
1592 1
    npy_longlong offset = 0;
1593 1
    NPY_ORDER order = NPY_CORDER;
1594 1
    int is_f_order = 0;
1595
    PyArrayObject *ret;
1596

1597 1
    buffer.ptr = NULL;
1598
    /*
1599
     * Usually called with shape and type but can also be called with buffer,
1600
     * strides, and swapped info For now, let's just use this to create an
1601
     * empty, contiguous array of a specific type and shape.
1602
     */
1603 1
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&LO&O&:ndarray",
1604
                                     kwlist, PyArray_IntpConverter,
1605
                                     &dims,
1606
                                     PyArray_DescrConverter,
1607
                                     &descr,
1608
                                     PyArray_BufferConverter,
1609
                                     &buffer,
1610
                                     &offset,
1611
                                     &PyArray_OptionalIntpConverter,
1612
                                     &strides,
1613
                                     &PyArray_OrderConverter,
1614
                                     &order)) {
1615
        goto fail;
1616
    }
1617 1
    if (order == NPY_FORTRANORDER) {
1618 1
        is_f_order = 1;
1619
    }
1620 1
    if (descr == NULL) {
1621 1
        descr = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
1622
    }
1623

1624 1
    itemsize = descr->elsize;
1625

1626 1
    if (strides.len != -1) {
1627
        npy_intp nb, off;
1628 1
        if (strides.len != dims.len) {
1629 1
            PyErr_SetString(PyExc_ValueError,
1630
                            "strides, if given, must be "   \
1631
                            "the same length as shape");
1632 1
            goto fail;
1633
        }
1634

1635 1
        if (buffer.ptr == NULL) {
1636
            nb = 0;
1637
            off = 0;
1638
        }
1639
        else {
1640 1
            nb = buffer.len;
1641 1
            off = (npy_intp) offset;
1642
        }
1643

1644

1645 1
        if (!PyArray_CheckStrides(itemsize, dims.len,
1646
                                  nb, off,
1647 1
                                  dims.ptr, strides.ptr)) {
1648 1
            PyErr_SetString(PyExc_ValueError,
1649
                            "strides is incompatible "      \
1650
                            "with shape of requested "      \
1651
                            "array and size of buffer");
1652 1
            goto fail;
1653
        }
1654
    }
1655

1656 1
    if (buffer.ptr == NULL) {
1657 1
        ret = (PyArrayObject *)
1658 1
            PyArray_NewFromDescr_int(subtype, descr,
1659
                                     (int)dims.len,
1660 1
                                     dims.ptr,
1661 1
                                     strides.ptr, NULL, is_f_order, NULL, NULL,
1662
                                     0, 1);
1663 1
        if (ret == NULL) {
1664 0
            descr = NULL;
1665 0
            goto fail;
1666
        }
1667 1
        if (PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT)) {
1668
            /* place Py_None in object positions */
1669 1
            PyArray_FillObjectArray(ret, Py_None);
1670 1
            if (PyErr_Occurred()) {
1671 0
                descr = NULL;
1672 0
                goto fail;
1673
            }
1674
        }
1675
    }
1676
    else {
1677
        /* buffer given -- use it */
1678 1
        if (dims.len == 1 && dims.ptr[0] == -1) {
1679 0
            dims.ptr[0] = (buffer.len-(npy_intp)offset) / itemsize;
1680
        }
1681 1
        else if ((strides.ptr == NULL) &&
1682 1
                 (buffer.len < (offset + (((npy_intp)itemsize)*
1683 1
                                          PyArray_MultiplyList(dims.ptr,
1684
                                                               dims.len))))) {
1685 1
            PyErr_SetString(PyExc_TypeError,
1686
                            "buffer is too small for "      \
1687
                            "requested array");
1688 1
            goto fail;
1689
        }
1690
        /* get writeable and aligned */
1691 1
        if (is_f_order) {
1692 1
            buffer.flags |= NPY_ARRAY_F_CONTIGUOUS;
1693
        }
1694 1
        ret = (PyArrayObject *)PyArray_NewFromDescr_int(
1695
                subtype, descr,
1696 1
                dims.len, dims.ptr, strides.ptr, offset + (char *)buffer.ptr,
1697
                buffer.flags, NULL, buffer.base,
1698
                0, 1);
1699 1
        if (ret == NULL) {
1700 1
            descr = NULL;
1701 1
            goto fail;
1702
        }
1703
    }
1704

1705 1
    npy_free_cache_dim_obj(dims);
1706 1
    npy_free_cache_dim_obj(strides);
1707 1
    return (PyObject *)ret;
1708

1709 1
 fail:
1710 1
    Py_XDECREF(descr);
1711 1
    npy_free_cache_dim_obj(dims);
1712 1
    npy_free_cache_dim_obj(strides);
1713 1
    return NULL;
1714
}
1715

1716

1717
static PyObject *
1718 1
array_iter(PyArrayObject *arr)
1719
{
1720 1
    if (PyArray_NDIM(arr) == 0) {
1721 0
        PyErr_SetString(PyExc_TypeError,
1722
                        "iteration over a 0-d array");
1723 0
        return NULL;
1724
    }
1725 1
    return PySeqIter_New((PyObject *)arr);
1726
}
1727

1728
static PyObject *
1729 1
array_alloc(PyTypeObject *type, Py_ssize_t NPY_UNUSED(nitems))
1730
{
1731
    /* nitems will always be 0 */
1732 1
    PyObject *obj = PyObject_Malloc(type->tp_basicsize);
1733 1
    PyObject_Init(obj, type);
1734 1
    return obj;
1735
}
1736

1737
static void
1738 1
array_free(PyObject * v)
1739
{
1740
    /* avoid same deallocator as PyBaseObject, see gentype_free */
1741 1
    PyObject_Free(v);
1742
}
1743

1744

1745
NPY_NO_EXPORT PyTypeObject PyArray_Type = {
1746
    PyVarObject_HEAD_INIT(NULL, 0)
1747
    .tp_name = "numpy.ndarray",
1748
    .tp_basicsize = NPY_SIZEOF_PYARRAYOBJECT,
1749
    /* methods */
1750
    .tp_dealloc = (destructor)array_dealloc,
1751
    .tp_repr = (reprfunc)array_repr,
1752
    .tp_as_number = &array_as_number,
1753
    .tp_as_sequence = &array_as_sequence,
1754
    .tp_as_mapping = &array_as_mapping,
1755
    /*
1756
     * The tp_hash slot will be set PyObject_HashNotImplemented when the
1757
     * module is loaded.
1758
     */
1759
    .tp_str = (reprfunc)array_str,
1760
    .tp_as_buffer = &array_as_buffer,
1761
    .tp_flags =(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE),
1762

1763
    .tp_richcompare = (richcmpfunc)array_richcompare,
1764
    .tp_weaklistoffset = offsetof(PyArrayObject_fields, weakreflist),
1765
    .tp_iter = (getiterfunc)array_iter,
1766
    .tp_methods = array_methods,
1767
    .tp_getset = array_getsetlist,
1768
    .tp_alloc = (allocfunc)array_alloc,
1769
    .tp_new = (newfunc)array_new,
1770
    .tp_free = (freefunc)array_free,
1771
};

Read our documentation on viewing source code .

Loading