1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3
#include "structmember.h"
4

5
/*#include <stdio.h>*/
6
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
7
#define _MULTIARRAYMODULE
8
#include "numpy/arrayobject.h"
9

10
#include "npy_config.h"
11
#include "npy_pycompat.h"
12
#include "npy_import.h"
13
#include "common.h"
14
#include "number.h"
15
#include "temp_elide.h"
16

17
#include "binop_override.h"
18
#include "ufunc_override.h"
19

20
/*************************************************************************
21
 ****************   Implement Number Protocol ****************************
22
 *************************************************************************/
23

24
NPY_NO_EXPORT NumericOps n_ops; /* NB: static objects initialized to zero */
25

26
/*
27
 * Forward declarations. Might want to move functions around instead
28
 */
29
static PyObject *
30
array_inplace_add(PyArrayObject *m1, PyObject *m2);
31
static PyObject *
32
array_inplace_subtract(PyArrayObject *m1, PyObject *m2);
33
static PyObject *
34
array_inplace_multiply(PyArrayObject *m1, PyObject *m2);
35
static PyObject *
36
array_inplace_true_divide(PyArrayObject *m1, PyObject *m2);
37
static PyObject *
38
array_inplace_floor_divide(PyArrayObject *m1, PyObject *m2);
39
static PyObject *
40
array_inplace_bitwise_and(PyArrayObject *m1, PyObject *m2);
41
static PyObject *
42
array_inplace_bitwise_or(PyArrayObject *m1, PyObject *m2);
43
static PyObject *
44
array_inplace_bitwise_xor(PyArrayObject *m1, PyObject *m2);
45
static PyObject *
46
array_inplace_left_shift(PyArrayObject *m1, PyObject *m2);
47
static PyObject *
48
array_inplace_right_shift(PyArrayObject *m1, PyObject *m2);
49
static PyObject *
50
array_inplace_remainder(PyArrayObject *m1, PyObject *m2);
51
static PyObject *
52
array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo));
53

54
/*
55
 * Dictionary can contain any of the numeric operations, by name.
56
 * Those not present will not be changed
57
 */
58

59
/* FIXME - macro contains a return */
60
#define SET(op)   temp = _PyDict_GetItemStringWithError(dict, #op); \
61
    if (temp == NULL && PyErr_Occurred()) { \
62
        return -1; \
63
    } \
64
    else if (temp != NULL) { \
65
        if (!(PyCallable_Check(temp))) { \
66
            return -1; \
67
        } \
68
        Py_INCREF(temp); \
69
        Py_XDECREF(n_ops.op); \
70
        n_ops.op = temp; \
71
    }
72

73
NPY_NO_EXPORT int
74 1
_PyArray_SetNumericOps(PyObject *dict)
75
{
76 1
    PyObject *temp = NULL;
77 1
    SET(add);
78 1
    SET(subtract);
79 1
    SET(multiply);
80 1
    SET(divide);
81 1
    SET(remainder);
82 1
    SET(divmod);
83 1
    SET(power);
84 1
    SET(square);
85 1
    SET(reciprocal);
86 1
    SET(_ones_like);
87 1
    SET(sqrt);
88 1
    SET(cbrt);
89 1
    SET(negative);
90 1
    SET(positive);
91 1
    SET(absolute);
92 1
    SET(invert);
93 1
    SET(left_shift);
94 1
    SET(right_shift);
95 1
    SET(bitwise_and);
96 1
    SET(bitwise_or);
97 1
    SET(bitwise_xor);
98 1
    SET(less);
99 1
    SET(less_equal);
100 1
    SET(equal);
101 1
    SET(not_equal);
102 1
    SET(greater);
103 1
    SET(greater_equal);
104 1
    SET(floor_divide);
105 1
    SET(true_divide);
106 1
    SET(logical_or);
107 1
    SET(logical_and);
108 1
    SET(floor);
109 1
    SET(ceil);
110 1
    SET(maximum);
111 1
    SET(minimum);
112 1
    SET(rint);
113 1
    SET(conjugate);
114 1
    SET(matmul);
115 1
    SET(clip);
116
    return 0;
117
}
118

119
/*NUMPY_API
120
 *Set internal structure with number functions that all arrays will use
121
 */
122
NPY_NO_EXPORT int
123 1
PyArray_SetNumericOps(PyObject *dict)
124
{
125
    /* 2018-09-09, 1.16 */
126 1
    if (DEPRECATE("PyArray_SetNumericOps is deprecated. Use "
127
        "PyUFunc_ReplaceLoopBySignature to replace ufunc inner loop functions "
128
        "instead.") < 0) {
129
        return -1;
130
    }
131 1
    return _PyArray_SetNumericOps(dict);
132
}
133

134
/* Note - macro contains goto */
135
#define GET(op) if (n_ops.op &&                                         \
136
                    (PyDict_SetItemString(dict, #op, n_ops.op)==-1))    \
137
        goto fail;
138

139
NPY_NO_EXPORT PyObject *
140 1
_PyArray_GetNumericOps(void)
141
{
142
    PyObject *dict;
143 1
    if ((dict = PyDict_New())==NULL)
144
        return NULL;
145 1
    GET(add);
146 1
    GET(subtract);
147 1
    GET(multiply);
148 1
    GET(divide);
149 1
    GET(remainder);
150 1
    GET(divmod);
151 1
    GET(power);
152 1
    GET(square);
153 1
    GET(reciprocal);
154 1
    GET(_ones_like);
155 1
    GET(sqrt);
156 1
    GET(negative);
157 1
    GET(positive);
158 1
    GET(absolute);
159 1
    GET(invert);
160 1
    GET(left_shift);
161 1
    GET(right_shift);
162 1
    GET(bitwise_and);
163 1
    GET(bitwise_or);
164 1
    GET(bitwise_xor);
165 1
    GET(less);
166 1
    GET(less_equal);
167 1
    GET(equal);
168 1
    GET(not_equal);
169 1
    GET(greater);
170 1
    GET(greater_equal);
171 1
    GET(floor_divide);
172 1
    GET(true_divide);
173 1
    GET(logical_or);
174 1
    GET(logical_and);
175 1
    GET(floor);
176 1
    GET(ceil);
177 1
    GET(maximum);
178 1
    GET(minimum);
179 1
    GET(rint);
180 1
    GET(conjugate);
181 1
    GET(matmul);
182 1
    GET(clip);
183
    return dict;
184

185 0
 fail:
186 0
    Py_DECREF(dict);
187
    return NULL;
188
}
189

190
/*NUMPY_API
191
  Get dictionary showing number functions that all arrays will use
192
*/
193
NPY_NO_EXPORT PyObject *
194 1
PyArray_GetNumericOps(void)
195
{
196
    /* 2018-09-09, 1.16 */
197 1
    if (DEPRECATE("PyArray_GetNumericOps is deprecated.") < 0) {
198
        return NULL;
199
    }
200 1
    return _PyArray_GetNumericOps();
201
}
202

203
static PyObject *
204 1
_get_keywords(int rtype, PyArrayObject *out)
205
{
206 1
    PyObject *kwds = NULL;
207 1
    if (rtype != NPY_NOTYPE || out != NULL) {
208 1
        kwds = PyDict_New();
209 1
        if (rtype != NPY_NOTYPE) {
210
            PyArray_Descr *descr;
211 1
            descr = PyArray_DescrFromType(rtype);
212 1
            if (descr) {
213 1
                PyDict_SetItemString(kwds, "dtype", (PyObject *)descr);
214 1
                Py_DECREF(descr);
215
            }
216
        }
217 1
        if (out != NULL) {
218 1
            PyDict_SetItemString(kwds, "out", (PyObject *)out);
219
        }
220
    }
221 1
    return kwds;
222
}
223

224
NPY_NO_EXPORT PyObject *
225 1
PyArray_GenericReduceFunction(PyArrayObject *m1, PyObject *op, int axis,
226
                              int rtype, PyArrayObject *out)
227
{
228 1
    PyObject *args, *ret = NULL, *meth;
229
    PyObject *kwds;
230 1
    if (op == NULL) {
231 0
        Py_INCREF(Py_NotImplemented);
232 0
        return Py_NotImplemented;
233
    }
234 1
    args = Py_BuildValue("(Oi)", m1, axis);
235 1
    kwds = _get_keywords(rtype, out);
236 1
    meth = PyObject_GetAttrString(op, "reduce");
237 1
    if (meth && PyCallable_Check(meth)) {
238 1
        ret = PyObject_Call(meth, args, kwds);
239
    }
240 1
    Py_DECREF(args);
241 1
    Py_DECREF(meth);
242 1
    Py_XDECREF(kwds);
243
    return ret;
244
}
245

246

247
NPY_NO_EXPORT PyObject *
248 1
PyArray_GenericAccumulateFunction(PyArrayObject *m1, PyObject *op, int axis,
249
                                  int rtype, PyArrayObject *out)
250
{
251 1
    PyObject *args, *ret = NULL, *meth;
252
    PyObject *kwds;
253 1
    if (op == NULL) {
254 0
        Py_INCREF(Py_NotImplemented);
255 0
        return Py_NotImplemented;
256
    }
257 1
    args = Py_BuildValue("(Oi)", m1, axis);
258 1
    kwds = _get_keywords(rtype, out);
259 1
    meth = PyObject_GetAttrString(op, "accumulate");
260 1
    if (meth && PyCallable_Check(meth)) {
261 1
        ret = PyObject_Call(meth, args, kwds);
262
    }
263 1
    Py_DECREF(args);
264 1
    Py_DECREF(meth);
265 1
    Py_XDECREF(kwds);
266
    return ret;
267
}
268

269

270
NPY_NO_EXPORT PyObject *
271 1
PyArray_GenericBinaryFunction(PyArrayObject *m1, PyObject *m2, PyObject *op)
272
{
273
    /*
274
     * I suspect that the next few lines are buggy and cause NotImplemented to
275
     * be returned at weird times... but if we raise an error here, then
276
     * *everything* breaks. (Like, 'arange(10) + 1' and just
277
     * 'repr(arange(10))' both blow up with an error here.) Not sure what's
278
     * going on with that, but I'll leave it alone for now. - njs, 2015-06-21
279
     */
280 1
    if (op == NULL) {
281 0
        Py_INCREF(Py_NotImplemented);
282 0
        return Py_NotImplemented;
283
    }
284

285 1
    return PyObject_CallFunctionObjArgs(op, m1, m2, NULL);
286
}
287

288
NPY_NO_EXPORT PyObject *
289 1
PyArray_GenericUnaryFunction(PyArrayObject *m1, PyObject *op)
290
{
291 1
    if (op == NULL) {
292 0
        Py_INCREF(Py_NotImplemented);
293 0
        return Py_NotImplemented;
294
    }
295 1
    return PyObject_CallFunctionObjArgs(op, m1, NULL);
296
}
297

298
static PyObject *
299
PyArray_GenericInplaceBinaryFunction(PyArrayObject *m1,
300
                                     PyObject *m2, PyObject *op)
301
{
302 1
    if (op == NULL) {
303 0
        Py_INCREF(Py_NotImplemented);
304
        return Py_NotImplemented;
305
    }
306 1
    return PyObject_CallFunctionObjArgs(op, m1, m2, m1, NULL);
307
}
308

309
static PyObject *
310
PyArray_GenericInplaceUnaryFunction(PyArrayObject *m1, PyObject *op)
311
{
312 1
    if (op == NULL) {
313 0
        Py_INCREF(Py_NotImplemented);
314
        return Py_NotImplemented;
315
    }
316 1
    return PyObject_CallFunctionObjArgs(op, m1, m1, NULL);
317
}
318

319
static PyObject *
320 1
array_add(PyArrayObject *m1, PyObject *m2)
321
{
322
    PyObject *res;
323

324 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_add, array_add);
325 1
    if (try_binary_elide(m1, m2, &array_inplace_add, &res, 1)) {
326 1
        return res;
327
    }
328 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.add);
329
}
330

331
static PyObject *
332 1
array_subtract(PyArrayObject *m1, PyObject *m2)
333
{
334
    PyObject *res;
335

336 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_subtract, array_subtract);
337 1
    if (try_binary_elide(m1, m2, &array_inplace_subtract, &res, 0)) {
338 0
        return res;
339
    }
340 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.subtract);
341
}
342

343
static PyObject *
344 1
array_multiply(PyArrayObject *m1, PyObject *m2)
345
{
346
    PyObject *res;
347

348 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_multiply, array_multiply);
349 1
    if (try_binary_elide(m1, m2, &array_inplace_multiply, &res, 1)) {
350 1
        return res;
351
    }
352 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.multiply);
353
}
354

355
static PyObject *
356 1
array_remainder(PyArrayObject *m1, PyObject *m2)
357
{
358 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_remainder, array_remainder);
359 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.remainder);
360
}
361

362
static PyObject *
363 1
array_divmod(PyArrayObject *m1, PyObject *m2)
364
{
365 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_divmod, array_divmod);
366 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.divmod);
367
}
368

369
/* Need this to be version dependent on account of the slot check */
370
static PyObject *
371 1
array_matrix_multiply(PyArrayObject *m1, PyObject *m2)
372
{
373 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_matrix_multiply, array_matrix_multiply);
374 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.matmul);
375
}
376

377
static PyObject *
378 1
array_inplace_matrix_multiply(
379
        PyArrayObject *NPY_UNUSED(m1), PyObject *NPY_UNUSED(m2))
380
{
381 1
    PyErr_SetString(PyExc_TypeError,
382
                    "In-place matrix multiplication is not (yet) supported. "
383
                    "Use 'a = a @ b' instead of 'a @= b'.");
384 1
    return NULL;
385
}
386

387
/*
388
 * Determine if object is a scalar and if so, convert the object
389
 * to a double and place it in the out_exponent argument
390
 * and return the "scalar kind" as a result.   If the object is
391
 * not a scalar (or if there are other error conditions)
392
 * return NPY_NOSCALAR, and out_exponent is undefined.
393
 */
394
static NPY_SCALARKIND
395 1
is_scalar_with_conversion(PyObject *o2, double* out_exponent)
396
{
397
    PyObject *temp;
398 1
    const int optimize_fpexps = 1;
399

400 1
    if (PyInt_Check(o2)) {
401 1
        *out_exponent = (double)PyLong_AsLong(o2);
402 1
        return NPY_INTPOS_SCALAR;
403
    }
404 1
    if (optimize_fpexps && PyFloat_Check(o2)) {
405 1
        *out_exponent = PyFloat_AsDouble(o2);
406 1
        return NPY_FLOAT_SCALAR;
407
    }
408 1
    if (PyArray_Check(o2)) {
409 1
        if ((PyArray_NDIM((PyArrayObject *)o2) == 0) &&
410 0
                ((PyArray_ISINTEGER((PyArrayObject *)o2) ||
411 0
                 (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) {
412 0
            temp = Py_TYPE(o2)->tp_as_number->nb_float(o2);
413 0
            if (temp == NULL) {
414
                return NPY_NOSCALAR;
415
            }
416 0
            *out_exponent = PyFloat_AsDouble(o2);
417 0
            Py_DECREF(temp);
418 0
            if (PyArray_ISINTEGER((PyArrayObject *)o2)) {
419
                return NPY_INTPOS_SCALAR;
420
            }
421
            else { /* ISFLOAT */
422
                return NPY_FLOAT_SCALAR;
423
            }
424
        }
425
    }
426 1
    else if (PyArray_IsScalar(o2, Integer) ||
427 1
                (optimize_fpexps && PyArray_IsScalar(o2, Floating))) {
428 0
        temp = Py_TYPE(o2)->tp_as_number->nb_float(o2);
429 0
        if (temp == NULL) {
430
            return NPY_NOSCALAR;
431
        }
432 0
        *out_exponent = PyFloat_AsDouble(o2);
433 0
        Py_DECREF(temp);
434

435 0
        if (PyArray_IsScalar(o2, Integer)) {
436
                return NPY_INTPOS_SCALAR;
437
        }
438
        else { /* IsScalar(o2, Floating) */
439
            return NPY_FLOAT_SCALAR;
440
        }
441
    }
442 1
    else if (PyIndex_Check(o2)) {
443 0
        PyObject* value = PyNumber_Index(o2);
444
        Py_ssize_t val;
445 0
        if (value==NULL) {
446 0
            if (PyErr_Occurred()) {
447 0
                PyErr_Clear();
448
            }
449
            return NPY_NOSCALAR;
450
        }
451 0
        val = PyLong_AsSsize_t(value);
452 0
        if (error_converting(val)) {
453 0
            PyErr_Clear();
454 0
            return NPY_NOSCALAR;
455
        }
456 0
        *out_exponent = (double) val;
457 0
        return NPY_INTPOS_SCALAR;
458
    }
459
    return NPY_NOSCALAR;
460
}
461

462
/*
463
 * optimize float array or complex array to a scalar power
464
 * returns 0 on success, -1 if no optimization is possible
465
 * the result is in value (can be NULL if an error occurred)
466
 */
467
static int
468 1
fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace,
469
                  PyObject **value)
470
{
471
    double exponent;
472
    NPY_SCALARKIND kind;   /* NPY_NOSCALAR is not scalar */
473

474 1
    if (PyArray_Check(a1) &&
475 1
            !PyArray_ISOBJECT(a1) &&
476
            ((kind=is_scalar_with_conversion(o2, &exponent))>0)) {
477 1
        PyObject *fastop = NULL;
478 1
        if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) {
479 1
            if (exponent == 1.0) {
480 1
                fastop = n_ops.positive;
481
            }
482 1
            else if (exponent == -1.0) {
483 1
                fastop = n_ops.reciprocal;
484
            }
485 1
            else if (exponent ==  0.0) {
486 1
                fastop = n_ops._ones_like;
487
            }
488 1
            else if (exponent ==  0.5) {
489 1
                fastop = n_ops.sqrt;
490
            }
491 1
            else if (exponent ==  2.0) {
492 1
                fastop = n_ops.square;
493
            }
494
            else {
495
                return -1;
496
            }
497

498 1
            if (inplace || can_elide_temp_unary(a1)) {
499 1
                *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
500
            }
501
            else {
502 1
                *value = PyArray_GenericUnaryFunction(a1, fastop);
503
            }
504
            return 0;
505
        }
506
        /* Because this is called with all arrays, we need to
507
         *  change the output if the kind of the scalar is different
508
         *  than that of the input and inplace is not on ---
509
         *  (thus, the input should be up-cast)
510
         */
511 1
        else if (exponent == 2.0) {
512 1
            fastop = n_ops.square;
513 1
            if (inplace) {
514 0
                *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
515
            }
516
            else {
517
                /* We only special-case the FLOAT_SCALAR and integer types */
518 1
                if (kind == NPY_FLOAT_SCALAR && PyArray_ISINTEGER(a1)) {
519 1
                    PyArray_Descr *dtype = PyArray_DescrFromType(NPY_DOUBLE);
520 1
                    a1 = (PyArrayObject *)PyArray_CastToType(a1, dtype,
521 1
                            PyArray_ISFORTRAN(a1));
522 1
                    if (a1 != NULL) {
523
                        /* cast always creates a new array */
524 1
                        *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
525 1
                        Py_DECREF(a1);
526
                    }
527
                }
528
                else {
529 1
                    *value = PyArray_GenericUnaryFunction(a1, fastop);
530
                }
531
            }
532
            return 0;
533
        }
534
    }
535
    /* no fast operation found */
536
    return -1;
537
}
538

539
static PyObject *
540 1
array_power(PyArrayObject *a1, PyObject *o2, PyObject *modulo)
541
{
542 1
    PyObject *value = NULL;
543

544 1
    if (modulo != Py_None) {
545
        /* modular exponentiation is not implemented (gh-8804) */
546 0
        Py_INCREF(Py_NotImplemented);
547 0
        return Py_NotImplemented;
548
    }
549

550 1
    BINOP_GIVE_UP_IF_NEEDED(a1, o2, nb_power, array_power);
551 1
    if (fast_scalar_power(a1, o2, 0, &value) != 0) {
552 1
        value = PyArray_GenericBinaryFunction(a1, o2, n_ops.power);
553
    }
554 1
    return value;
555
}
556

557
static PyObject *
558 1
array_positive(PyArrayObject *m1)
559
{
560
    /*
561
     * For backwards compatibility, where + just implied a copy,
562
     * we cannot just call n_ops.positive.  Instead, we do the following
563
     * 1. Try n_ops.positive
564
     * 2. If we get an exception, check whether __array_ufunc__ is
565
     *    overridden; if so, we live in the future and we allow the
566
     *    TypeError to be passed on.
567
     * 3. If not, give a deprecation warning and return a copy.
568
     */
569
    PyObject *value;
570 1
    if (can_elide_temp_unary(m1)) {
571 0
        value = PyArray_GenericInplaceUnaryFunction(m1, n_ops.positive);
572
    }
573
    else {
574 1
        value = PyArray_GenericUnaryFunction(m1, n_ops.positive);
575
    }
576 1
    if (value == NULL) {
577
        /*
578
         * We first fetch the error, as it needs to be clear to check
579
         * for the override.  When the deprecation is removed,
580
         * this whole stanza can be deleted.
581
         */
582
        PyObject *exc, *val, *tb;
583 1
        PyErr_Fetch(&exc, &val, &tb);
584 1
        if (PyUFunc_HasOverride((PyObject *)m1)) {
585 1
            PyErr_Restore(exc, val, tb);
586 1
            return NULL;
587
        }
588 1
        Py_XDECREF(exc);
589 1
        Py_XDECREF(val);
590 1
        Py_XDECREF(tb);
591

592
        /* 2018-06-28, 1.16.0 */
593 1
        if (DEPRECATE("Applying '+' to a non-numerical array is "
594
                      "ill-defined. Returning a copy, but in the future "
595
                      "this will error.") < 0) {
596
            return NULL;
597
        }
598 1
        value = PyArray_Return((PyArrayObject *)PyArray_Copy(m1));
599
    }
600
    return value;
601
}
602

603
static PyObject *
604 1
array_negative(PyArrayObject *m1)
605
{
606 1
    if (can_elide_temp_unary(m1)) {
607 0
        return PyArray_GenericInplaceUnaryFunction(m1, n_ops.negative);
608
    }
609 1
    return PyArray_GenericUnaryFunction(m1, n_ops.negative);
610
}
611

612
static PyObject *
613 1
array_absolute(PyArrayObject *m1)
614
{
615 1
    if (can_elide_temp_unary(m1) && !PyArray_ISCOMPLEX(m1)) {
616 0
        return PyArray_GenericInplaceUnaryFunction(m1, n_ops.absolute);
617
    }
618 1
    return PyArray_GenericUnaryFunction(m1, n_ops.absolute);
619
}
620

621
static PyObject *
622 1
array_invert(PyArrayObject *m1)
623
{
624 1
    if (can_elide_temp_unary(m1)) {
625 0
        return PyArray_GenericInplaceUnaryFunction(m1, n_ops.invert);
626
    }
627 1
    return PyArray_GenericUnaryFunction(m1, n_ops.invert);
628
}
629

630
static PyObject *
631 1
array_left_shift(PyArrayObject *m1, PyObject *m2)
632
{
633
    PyObject *res;
634

635 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_lshift, array_left_shift);
636 1
    if (try_binary_elide(m1, m2, &array_inplace_left_shift, &res, 0)) {
637 0
        return res;
638
    }
639 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.left_shift);
640
}
641

642
static PyObject *
643 1
array_right_shift(PyArrayObject *m1, PyObject *m2)
644
{
645
    PyObject *res;
646

647 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_rshift, array_right_shift);
648 1
    if (try_binary_elide(m1, m2, &array_inplace_right_shift, &res, 0)) {
649 0
        return res;
650
    }
651 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.right_shift);
652
}
653

654
static PyObject *
655 1
array_bitwise_and(PyArrayObject *m1, PyObject *m2)
656
{
657
    PyObject *res;
658

659 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_and, array_bitwise_and);
660 1
    if (try_binary_elide(m1, m2, &array_inplace_bitwise_and, &res, 1)) {
661 0
        return res;
662
    }
663 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_and);
664
}
665

666
static PyObject *
667 1
array_bitwise_or(PyArrayObject *m1, PyObject *m2)
668
{
669
    PyObject *res;
670

671 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_or, array_bitwise_or);
672 1
    if (try_binary_elide(m1, m2, &array_inplace_bitwise_or, &res, 1)) {
673 0
        return res;
674
    }
675 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_or);
676
}
677

678
static PyObject *
679 1
array_bitwise_xor(PyArrayObject *m1, PyObject *m2)
680
{
681
    PyObject *res;
682

683 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_xor, array_bitwise_xor);
684 1
    if (try_binary_elide(m1, m2, &array_inplace_bitwise_xor, &res, 1)) {
685 0
        return res;
686
    }
687 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_xor);
688
}
689

690
static PyObject *
691 1
array_inplace_add(PyArrayObject *m1, PyObject *m2)
692
{
693 1
    INPLACE_GIVE_UP_IF_NEEDED(
694
            m1, m2, nb_inplace_add, array_inplace_add);
695 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.add);
696
}
697

698
static PyObject *
699 1
array_inplace_subtract(PyArrayObject *m1, PyObject *m2)
700
{
701 1
    INPLACE_GIVE_UP_IF_NEEDED(
702
            m1, m2, nb_inplace_subtract, array_inplace_subtract);
703 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.subtract);
704
}
705

706
static PyObject *
707 1
array_inplace_multiply(PyArrayObject *m1, PyObject *m2)
708
{
709 1
    INPLACE_GIVE_UP_IF_NEEDED(
710
            m1, m2, nb_inplace_multiply, array_inplace_multiply);
711 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.multiply);
712
}
713

714
static PyObject *
715 1
array_inplace_remainder(PyArrayObject *m1, PyObject *m2)
716
{
717 1
    INPLACE_GIVE_UP_IF_NEEDED(
718
            m1, m2, nb_inplace_remainder, array_inplace_remainder);
719 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.remainder);
720
}
721

722
static PyObject *
723 1
array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo))
724
{
725
    /* modulo is ignored! */
726 1
    PyObject *value = NULL;
727

728 1
    INPLACE_GIVE_UP_IF_NEEDED(
729
            a1, o2, nb_inplace_power, array_inplace_power);
730 1
    if (fast_scalar_power(a1, o2, 1, &value) != 0) {
731 1
        value = PyArray_GenericInplaceBinaryFunction(a1, o2, n_ops.power);
732
    }
733 1
    return value;
734
}
735

736
static PyObject *
737 1
array_inplace_left_shift(PyArrayObject *m1, PyObject *m2)
738
{
739 1
    INPLACE_GIVE_UP_IF_NEEDED(
740
            m1, m2, nb_inplace_lshift, array_inplace_left_shift);
741 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.left_shift);
742
}
743

744
static PyObject *
745 1
array_inplace_right_shift(PyArrayObject *m1, PyObject *m2)
746
{
747 1
    INPLACE_GIVE_UP_IF_NEEDED(
748
            m1, m2, nb_inplace_rshift, array_inplace_right_shift);
749 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.right_shift);
750
}
751

752
static PyObject *
753 1
array_inplace_bitwise_and(PyArrayObject *m1, PyObject *m2)
754
{
755 1
    INPLACE_GIVE_UP_IF_NEEDED(
756
            m1, m2, nb_inplace_and, array_inplace_bitwise_and);
757 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_and);
758
}
759

760
static PyObject *
761 1
array_inplace_bitwise_or(PyArrayObject *m1, PyObject *m2)
762
{
763 1
    INPLACE_GIVE_UP_IF_NEEDED(
764
            m1, m2, nb_inplace_or, array_inplace_bitwise_or);
765 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_or);
766
}
767

768
static PyObject *
769 1
array_inplace_bitwise_xor(PyArrayObject *m1, PyObject *m2)
770
{
771 1
    INPLACE_GIVE_UP_IF_NEEDED(
772
            m1, m2, nb_inplace_xor, array_inplace_bitwise_xor);
773 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_xor);
774
}
775

776
static PyObject *
777 1
array_floor_divide(PyArrayObject *m1, PyObject *m2)
778
{
779
    PyObject *res;
780

781 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_floor_divide, array_floor_divide);
782 1
    if (try_binary_elide(m1, m2, &array_inplace_floor_divide, &res, 0)) {
783 1
        return res;
784
    }
785 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.floor_divide);
786
}
787

788
static PyObject *
789 1
array_true_divide(PyArrayObject *m1, PyObject *m2)
790
{
791
    PyObject *res;
792

793 1
    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_true_divide, array_true_divide);
794 1
    if (PyArray_CheckExact(m1) &&
795 1
            (PyArray_ISFLOAT(m1) || PyArray_ISCOMPLEX(m1)) &&
796 1
            try_binary_elide(m1, m2, &array_inplace_true_divide, &res, 0)) {
797 0
        return res;
798
    }
799 1
    return PyArray_GenericBinaryFunction(m1, m2, n_ops.true_divide);
800
}
801

802
static PyObject *
803 1
array_inplace_floor_divide(PyArrayObject *m1, PyObject *m2)
804
{
805 1
    INPLACE_GIVE_UP_IF_NEEDED(
806
            m1, m2, nb_inplace_floor_divide, array_inplace_floor_divide);
807 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2,
808
                                                n_ops.floor_divide);
809
}
810

811
static PyObject *
812 1
array_inplace_true_divide(PyArrayObject *m1, PyObject *m2)
813
{
814 1
    INPLACE_GIVE_UP_IF_NEEDED(
815
            m1, m2, nb_inplace_true_divide, array_inplace_true_divide);
816 1
    return PyArray_GenericInplaceBinaryFunction(m1, m2,
817
                                                n_ops.true_divide);
818
}
819

820

821
static int
822 1
_array_nonzero(PyArrayObject *mp)
823
{
824
    npy_intp n;
825

826 1
    n = PyArray_SIZE(mp);
827 1
    if (n == 1) {
828
        int res;
829 1
        if (Py_EnterRecursiveCall(" while converting array to bool")) {
830
            return -1;
831
        }
832 1
        res = PyArray_DESCR(mp)->f->nonzero(PyArray_DATA(mp), mp);
833
        /* nonzero has no way to indicate an error, but one can occur */
834 1
        if (PyErr_Occurred()) {
835 1
            res = -1;
836
        }
837 1
        Py_LeaveRecursiveCall();
838
        return res;
839
    }
840 1
    else if (n == 0) {
841
        /* 2017-09-25, 1.14 */
842 1
        if (DEPRECATE("The truth value of an empty array is ambiguous. "
843
                      "Returning False, but in future this will result in an error. "
844
                      "Use `array.size > 0` to check that an array is not empty.") < 0) {
845
            return -1;
846
        }
847 1
        return 0;
848
    }
849
    else {
850 1
        PyErr_SetString(PyExc_ValueError,
851
                        "The truth value of an array "
852
                        "with more than one element is ambiguous. "
853
                        "Use a.any() or a.all()");
854 1
        return -1;
855
    }
856
}
857

858
/*
859
 * Convert the array to a scalar if allowed, and apply the builtin function
860
 * to it. The where argument is passed onto Py_EnterRecursiveCall when the
861
 * array contains python objects.
862
 */
863
NPY_NO_EXPORT PyObject *
864 1
array_scalar_forward(PyArrayObject *v,
865
                     PyObject *(*builtin_func)(PyObject *),
866
                     const char *where)
867
{
868
    PyObject *scalar;
869 1
    if (PyArray_SIZE(v) != 1) {
870 1
        PyErr_SetString(PyExc_TypeError, "only size-1 arrays can be"\
871
                        " converted to Python scalars");
872 1
        return NULL;
873
    }
874

875 1
    scalar = PyArray_GETITEM(v, PyArray_DATA(v));
876 1
    if (scalar == NULL) {
877
        return NULL;
878
    }
879

880
    /* Need to guard against recursion if our array holds references */
881 1
    if (PyDataType_REFCHK(PyArray_DESCR(v))) {
882
        PyObject *res;
883 1
        if (Py_EnterRecursiveCall(where) != 0) {
884 1
            Py_DECREF(scalar);
885
            return NULL;
886
        }
887 1
        res = builtin_func(scalar);
888 1
        Py_DECREF(scalar);
889 1
        Py_LeaveRecursiveCall();
890
        return res;
891
    }
892
    else {
893
        PyObject *res;
894 1
        res = builtin_func(scalar);
895 1
        Py_DECREF(scalar);
896
        return res;
897
    }
898
}
899

900

901
NPY_NO_EXPORT PyObject *
902 1
array_float(PyArrayObject *v)
903
{
904 1
    return array_scalar_forward(v, &PyNumber_Float, " in ndarray.__float__");
905
}
906

907
NPY_NO_EXPORT PyObject *
908 1
array_int(PyArrayObject *v)
909
{
910 1
    return array_scalar_forward(v, &PyNumber_Long, " in ndarray.__int__");
911
}
912

913
static PyObject *
914 1
array_index(PyArrayObject *v)
915
{
916 1
    if (!PyArray_ISINTEGER(v) || PyArray_NDIM(v) != 0) {
917 1
        PyErr_SetString(PyExc_TypeError,
918
            "only integer scalar arrays can be converted to a scalar index");
919 1
        return NULL;
920
    }
921 1
    return PyArray_GETITEM(v, PyArray_DATA(v));
922
}
923

924

925
NPY_NO_EXPORT PyNumberMethods array_as_number = {
926
    .nb_add = (binaryfunc)array_add,
927
    .nb_subtract = (binaryfunc)array_subtract,
928
    .nb_multiply = (binaryfunc)array_multiply,
929
    .nb_remainder = (binaryfunc)array_remainder,
930
    .nb_divmod = (binaryfunc)array_divmod,
931
    .nb_power = (ternaryfunc)array_power,
932
    .nb_negative = (unaryfunc)array_negative,
933
    .nb_positive = (unaryfunc)array_positive,
934
    .nb_absolute = (unaryfunc)array_absolute,
935
    .nb_bool = (inquiry)_array_nonzero,
936
    .nb_invert = (unaryfunc)array_invert,
937
    .nb_lshift = (binaryfunc)array_left_shift,
938
    .nb_rshift = (binaryfunc)array_right_shift,
939
    .nb_and = (binaryfunc)array_bitwise_and,
940
    .nb_xor = (binaryfunc)array_bitwise_xor,
941
    .nb_or = (binaryfunc)array_bitwise_or,
942

943
    .nb_int = (unaryfunc)array_int,
944
    .nb_float = (unaryfunc)array_float,
945
    .nb_index = (unaryfunc)array_index,
946

947
    .nb_inplace_add = (binaryfunc)array_inplace_add,
948
    .nb_inplace_subtract = (binaryfunc)array_inplace_subtract,
949
    .nb_inplace_multiply = (binaryfunc)array_inplace_multiply,
950
    .nb_inplace_remainder = (binaryfunc)array_inplace_remainder,
951
    .nb_inplace_power = (ternaryfunc)array_inplace_power,
952
    .nb_inplace_lshift = (binaryfunc)array_inplace_left_shift,
953
    .nb_inplace_rshift = (binaryfunc)array_inplace_right_shift,
954
    .nb_inplace_and = (binaryfunc)array_inplace_bitwise_and,
955
    .nb_inplace_xor = (binaryfunc)array_inplace_bitwise_xor,
956
    .nb_inplace_or = (binaryfunc)array_inplace_bitwise_or,
957

958
    .nb_floor_divide = (binaryfunc)array_floor_divide,
959
    .nb_true_divide = (binaryfunc)array_true_divide,
960
    .nb_inplace_floor_divide = (binaryfunc)array_inplace_floor_divide,
961
    .nb_inplace_true_divide = (binaryfunc)array_inplace_true_divide,
962

963
    .nb_matrix_multiply = (binaryfunc)array_matrix_multiply,
964
    .nb_inplace_matrix_multiply = (binaryfunc)array_inplace_matrix_multiply,
965
};

Read our documentation on viewing source code .

Loading