~ubuntu-branches/ubuntu/precise/python-numpy/precise

« back to all changes in this revision

Viewing changes to numpy/core/src/umath/ufunc_object.c

  • Committer: Package Import Robot
  • Author(s): Julian Taylor
  • Date: 2012-02-11 12:55:21 UTC
  • mfrom: (7.1.9 experimental) (7.2.3 sid)
  • Revision ID: package-import@ubuntu.com-20120211125521-31q3am7pp3mvt1ho
Tags: 1:1.6.1-5ubuntu1
* debian/patches/search-multiarch-paths.patch: (LP: #818867)
  - add multiarch libdirs to numpy.distutils.system_info
* Merge from Debian unstable, remaining changes:
  - debian/patches/20_disable-plot-extension.patch
     Disable plot_directive extension, and catch ImportErrors when
     matplotlib cannot be imported, which allows us to remove
     python-matplotlib from dependencies.  This is required because
     python-numpy is in main, while python-matplotlib is in universe.
  - Build using dh_python2
    add bin/f2py* to .install files
  - keep Replaces: python-numpy (<< 1:1.3.0-4) in python-numpy-dbg
    for lucid upgrades

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
#include "numpy/noprefix.h"
39
39
#include "numpy/ufuncobject.h"
 
40
#include "lowlevel_strided_loops.h"
40
41
 
41
42
#include "ufunc_object.h"
42
43
 
 
44
/********** PRINTF DEBUG TRACING **************/
 
45
#define NPY_UF_DBG_TRACING 0
 
46
 
 
47
#if NPY_UF_DBG_TRACING
 
48
#define NPY_UF_DBG_PRINT(s) printf("%s", s)
 
49
#define NPY_UF_DBG_PRINT1(s, p1) printf(s, p1)
 
50
#define NPY_UF_DBG_PRINT2(s, p1, p2) printf(s, p1, p2)
 
51
#define NPY_UF_DBG_PRINT3(s, p1, p2, p3) printf(s, p1, p2, p3)
 
52
#else
 
53
#define NPY_UF_DBG_PRINT(s)
 
54
#define NPY_UF_DBG_PRINT1(s, p1)
 
55
#define NPY_UF_DBG_PRINT2(s, p1, p2)
 
56
#define NPY_UF_DBG_PRINT3(s, p1, p2, p3)
 
57
#endif
 
58
/**********************************************/
 
59
 
 
60
 
 
61
/********************/
43
62
#define USE_USE_DEFAULTS 1
 
63
#define USE_NEW_ITERATOR_GENFUNC 1
 
64
/********************/
44
65
 
45
66
/* ---------------------------------------------------------------- */
46
67
 
206
227
#define SIGNATURE_NOBUFFER_UFUNCLOOP 4
207
228
 
208
229
 
209
 
static char
210
 
_lowest_type(char intype)
211
 
{
212
 
    switch(intype) {
213
 
    /* case PyArray_BYTE */
214
 
    case PyArray_SHORT:
215
 
    case PyArray_INT:
216
 
    case PyArray_LONG:
217
 
    case PyArray_LONGLONG:
218
 
        return PyArray_BYTE;
219
 
    /* case PyArray_UBYTE */
220
 
    case PyArray_USHORT:
221
 
    case PyArray_UINT:
222
 
    case PyArray_ULONG:
223
 
    case PyArray_ULONGLONG:
224
 
        return PyArray_UBYTE;
225
 
    /* case PyArray_FLOAT:*/
226
 
    case PyArray_DOUBLE:
227
 
    case PyArray_LONGDOUBLE:
228
 
        return PyArray_FLOAT;
229
 
    /* case PyArray_CFLOAT:*/
230
 
    case PyArray_CDOUBLE:
231
 
    case PyArray_CLONGDOUBLE:
232
 
        return PyArray_CFLOAT;
233
 
    default:
234
 
        return intype;
235
 
    }
236
 
}
237
 
 
238
 
static char *_types_msg =  "function not supported for these types, "   \
239
 
    "and can't coerce safely to supported types";
240
 
 
241
230
/*
242
231
 * This function analyzes the input arguments
243
232
 * and determines an appropriate __array_prepare__ function to call
244
233
 * for the outputs.
245
234
 *
246
 
 * If an output argument is provided, then it is wrapped
 
235
 * If an output argument is provided, then it is prepped
247
236
 * with its own __array_prepare__ not with the one determined by
248
237
 * the input arguments.
249
238
 *
250
239
 * if the provided output argument is already an ndarray,
251
 
 * the wrapping function is None (which means no wrapping will
 
240
 * the prepping function is None (which means no prepping will
252
241
 * be done --- not even PyArray_Return).
253
242
 *
254
 
 * A NULL is placed in output_wrap for outputs that
 
243
 * A NULL is placed in output_prep for outputs that
255
244
 * should just have PyArray_Return called.
256
245
 */
257
246
static void
258
 
_find_array_prepare(PyObject *args, PyObject **output_wrap, int nin, int nout)
 
247
_find_array_prepare(PyObject *args, PyObject *kwds,
 
248
                    PyObject **output_prep, int nin, int nout)
259
249
{
260
250
    Py_ssize_t nargs;
261
251
    int i;
262
252
    int np = 0;
263
 
    PyObject *with_wrap[NPY_MAXARGS], *wraps[NPY_MAXARGS];
264
 
    PyObject *obj, *wrap = NULL;
 
253
    PyObject *with_prep[NPY_MAXARGS], *preps[NPY_MAXARGS];
 
254
    PyObject *obj, *prep = NULL;
 
255
 
 
256
    /* If a 'subok' parameter is passed and isn't True, don't wrap */
 
257
    if (kwds != NULL && (obj = PyDict_GetItemString(kwds, "subok")) != NULL) {
 
258
        if (obj != Py_True) {
 
259
            for (i = 0; i < nout; i++) {
 
260
                output_prep[i] = NULL;
 
261
            }
 
262
            return;
 
263
        }
 
264
    }
265
265
 
266
266
    nargs = PyTuple_GET_SIZE(args);
267
267
    for (i = 0; i < nin; i++) {
269
269
        if (PyArray_CheckExact(obj) || PyArray_IsAnyScalar(obj)) {
270
270
            continue;
271
271
        }
272
 
        wrap = PyObject_GetAttrString(obj, "__array_prepare__");
273
 
        if (wrap) {
274
 
            if (PyCallable_Check(wrap)) {
275
 
                with_wrap[np] = obj;
276
 
                wraps[np] = wrap;
 
272
        prep = PyObject_GetAttrString(obj, "__array_prepare__");
 
273
        if (prep) {
 
274
            if (PyCallable_Check(prep)) {
 
275
                with_prep[np] = obj;
 
276
                preps[np] = prep;
277
277
                ++np;
278
278
            }
279
279
            else {
280
 
                Py_DECREF(wrap);
281
 
                wrap = NULL;
 
280
                Py_DECREF(prep);
 
281
                prep = NULL;
282
282
            }
283
283
        }
284
284
        else {
286
286
        }
287
287
    }
288
288
    if (np > 0) {
289
 
        /* If we have some wraps defined, find the one of highest priority */
290
 
        wrap = wraps[0];
 
289
        /* If we have some preps defined, find the one of highest priority */
 
290
        prep = preps[0];
291
291
        if (np > 1) {
292
 
            double maxpriority = PyArray_GetPriority(with_wrap[0],
 
292
            double maxpriority = PyArray_GetPriority(with_prep[0],
293
293
                        PyArray_SUBTYPE_PRIORITY);
294
294
            for (i = 1; i < np; ++i) {
295
 
                double priority = PyArray_GetPriority(with_wrap[i],
 
295
                double priority = PyArray_GetPriority(with_prep[i],
296
296
                            PyArray_SUBTYPE_PRIORITY);
297
297
                if (priority > maxpriority) {
298
298
                    maxpriority = priority;
299
 
                    Py_DECREF(wrap);
300
 
                    wrap = wraps[i];
 
299
                    Py_DECREF(prep);
 
300
                    prep = preps[i];
301
301
                }
302
302
                else {
303
 
                    Py_DECREF(wraps[i]);
 
303
                    Py_DECREF(preps[i]);
304
304
                }
305
305
            }
306
306
        }
307
307
    }
308
308
 
309
309
    /*
310
 
     * Here wrap is the wrapping function determined from the
 
310
     * Here prep is the prepping function determined from the
311
311
     * input arrays (could be NULL).
312
312
     *
313
313
     * For all the output arrays decide what to do.
314
314
     *
315
 
     * 1) Use the wrap function determined from the input arrays
 
315
     * 1) Use the prep function determined from the input arrays
316
316
     * This is the default if the output array is not
317
317
     * passed in.
318
318
     *
324
324
    for (i = 0; i < nout; i++) {
325
325
        int j = nin + i;
326
326
        int incref = 1;
327
 
        output_wrap[i] = wrap;
 
327
        output_prep[i] = prep;
 
328
        obj = NULL;
328
329
        if (j < nargs) {
329
330
            obj = PyTuple_GET_ITEM(args, j);
330
 
            if (obj == Py_None) {
331
 
                continue;
 
331
            /* Output argument one may also be in a keyword argument */
 
332
            if (i == 0 && obj == Py_None && kwds != NULL) {
 
333
                obj = PyDict_GetItemString(kwds, "out");
332
334
            }
 
335
        }
 
336
        /* Output argument one may also be in a keyword argument */
 
337
        else if (i == 0 && kwds != NULL) {
 
338
            obj = PyDict_GetItemString(kwds, "out");
 
339
        }
 
340
 
 
341
        if (obj != Py_None && obj != NULL) {
333
342
            if (PyArray_CheckExact(obj)) {
334
 
                output_wrap[i] = Py_None;
 
343
                /* None signals to not call any wrapping */
 
344
                output_prep[i] = Py_None;
335
345
            }
336
346
            else {
337
 
                PyObject *owrap = PyObject_GetAttrString(obj,
 
347
                PyObject *oprep = PyObject_GetAttrString(obj,
338
348
                            "__array_prepare__");
339
349
                incref = 0;
340
 
                if (!(owrap) || !(PyCallable_Check(owrap))) {
341
 
                    Py_XDECREF(owrap);
342
 
                    owrap = wrap;
 
350
                if (!(oprep) || !(PyCallable_Check(oprep))) {
 
351
                    Py_XDECREF(oprep);
 
352
                    oprep = prep;
343
353
                    incref = 1;
344
354
                    PyErr_Clear();
345
355
                }
346
 
                output_wrap[i] = owrap;
 
356
                output_prep[i] = oprep;
347
357
            }
348
358
        }
 
359
 
349
360
        if (incref) {
350
 
            Py_XINCREF(output_wrap[i]);
 
361
            Py_XINCREF(output_prep[i]);
351
362
        }
352
363
    }
353
 
    Py_XDECREF(wrap);
 
364
    Py_XDECREF(prep);
354
365
    return;
355
366
}
356
367
 
357
 
/*
358
 
 * Called for non-NULL user-defined functions.
359
 
 * The object should be a CObject pointing to a linked-list of functions
360
 
 * storing the function, data, and signature of all user-defined functions.
361
 
 * There must be a match with the input argument types or an error
362
 
 * will occur.
363
 
 */
364
 
static int
365
 
_find_matching_userloop(PyObject *obj, int *arg_types,
366
 
                        PyArray_SCALARKIND *scalars,
367
 
                        PyUFuncGenericFunction *function, void **data,
368
 
                        int nargs, int nin)
369
 
{
370
 
    PyUFunc_Loop1d *funcdata;
371
 
    int i;
372
 
 
373
 
    funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
374
 
    while (funcdata != NULL) {
375
 
        for (i = 0; i < nin; i++) {
376
 
            if (!PyArray_CanCoerceScalar(arg_types[i],
377
 
                                         funcdata->arg_types[i],
378
 
                                         scalars[i]))
379
 
                break;
380
 
        }
381
 
        if (i == nin) {
382
 
            /* match found */
383
 
            *function = funcdata->func;
384
 
            *data = funcdata->data;
385
 
            /* Make sure actual arg_types supported by the loop are used */
386
 
            for (i = 0; i < nargs; i++) {
387
 
                arg_types[i] = funcdata->arg_types[i];
388
 
            }
389
 
            return 0;
390
 
        }
391
 
        funcdata = funcdata->next;
392
 
    }
393
 
    return -1;
394
 
}
395
 
 
396
 
/*
397
 
 * if only one type is specified then it is the "first" output data-type
398
 
 * and the first signature matching this output data-type is returned.
399
 
 *
400
 
 * if a tuple of types is specified then an exact match to the signature
401
 
 * is searched and it much match exactly or an error occurs
402
 
 */
403
 
static int
404
 
extract_specified_loop(PyUFuncObject *self, int *arg_types,
405
 
                       PyUFuncGenericFunction *function, void **data,
406
 
                       PyObject *type_tup, int userdef)
407
 
{
408
 
    Py_ssize_t n = 1;
409
 
    int *rtypenums;
410
 
    static char msg[] = "loop written to specified type(s) not found";
411
 
    PyArray_Descr *dtype;
412
 
    int nargs;
413
 
    int i, j;
414
 
    int strtype = 0;
415
 
 
416
 
    nargs = self->nargs;
417
 
    if (PyTuple_Check(type_tup)) {
418
 
        n = PyTuple_GET_SIZE(type_tup);
419
 
        if (n != 1 && n != nargs) {
420
 
            PyErr_Format(PyExc_ValueError,
421
 
                         "a type-tuple must be specified " \
422
 
                         "of length 1 or %d for %s", nargs,
423
 
                         self->name ? self->name : "(unknown)");
424
 
            return -1;
425
 
        }
426
 
    }
427
 
    else if (PyString_Check(type_tup)) {
428
 
            Py_ssize_t slen;
429
 
            char *thestr;
430
 
 
431
 
            slen = PyString_GET_SIZE(type_tup);
432
 
            thestr = PyString_AS_STRING(type_tup);
433
 
            for (i = 0; i < slen - 2; i++) {
434
 
                if (thestr[i] == '-' && thestr[i+1] == '>') {
435
 
                    break;
436
 
                }
437
 
            }
438
 
            if (i < slen-2) {
439
 
                strtype = 1;
440
 
                n = slen - 2;
441
 
                if (i != self->nin
442
 
                    || slen - 2 - i != self->nout) {
443
 
                    PyErr_Format(PyExc_ValueError,
444
 
                                 "a type-string for %s, "   \
445
 
                                 "requires %d typecode(s) before " \
446
 
                                 "and %d after the -> sign",
447
 
                                 self->name ? self->name : "(unknown)",
448
 
                                 self->nin, self->nout);
449
 
                    return -1;
450
 
                }
451
 
            }
452
 
        }
453
 
    rtypenums = (int *)_pya_malloc(n*sizeof(int));
454
 
    if (rtypenums == NULL) {
455
 
        PyErr_NoMemory();
456
 
        return -1;
457
 
    }
458
 
 
459
 
    if (strtype) {
460
 
        char *ptr;
461
 
        ptr = PyString_AS_STRING(type_tup);
462
 
        i = 0;
463
 
        while (i < n) {
464
 
            if (*ptr == '-' || *ptr == '>') {
465
 
                ptr++;
466
 
                continue;
467
 
            }
468
 
            dtype = PyArray_DescrFromType((int) *ptr);
469
 
            if (dtype == NULL) {
470
 
                goto fail;
471
 
            }
472
 
            rtypenums[i] = dtype->type_num;
473
 
            Py_DECREF(dtype);
474
 
            ptr++;
475
 
            i++;
476
 
        }
477
 
    }
478
 
    else if (PyTuple_Check(type_tup)) {
479
 
        for (i = 0; i < n; i++) {
480
 
            if (PyArray_DescrConverter(PyTuple_GET_ITEM(type_tup, i),
481
 
                                       &dtype) == NPY_FAIL) {
482
 
                goto fail;
483
 
            }
484
 
            rtypenums[i] = dtype->type_num;
485
 
            Py_DECREF(dtype);
486
 
        }
487
 
    }
488
 
    else {
489
 
        if (PyArray_DescrConverter(type_tup, &dtype) == NPY_FAIL) {
490
 
            goto fail;
491
 
        }
492
 
        rtypenums[0] = dtype->type_num;
493
 
        Py_DECREF(dtype);
494
 
    }
495
 
 
496
 
    if (userdef > 0) {
497
 
        /* search in the user-defined functions */
498
 
        PyObject *key, *obj;
499
 
        PyUFunc_Loop1d *funcdata;
500
 
 
501
 
        obj = NULL;
502
 
        key = PyInt_FromLong((long) userdef);
503
 
        if (key == NULL) {
504
 
            goto fail;
505
 
        }
506
 
        obj = PyDict_GetItem(self->userloops, key);
507
 
        Py_DECREF(key);
508
 
        if (obj == NULL) {
509
 
            PyErr_SetString(PyExc_TypeError,
510
 
                            "user-defined type used in ufunc" \
511
 
                            " with no registered loops");
512
 
            goto fail;
513
 
        }
514
 
        /*
515
 
         * extract the correct function
516
 
         * data and argtypes
517
 
         */
518
 
        funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
519
 
        while (funcdata != NULL) {
520
 
            if (n != 1) {
521
 
                for (i = 0; i < nargs; i++) {
522
 
                    if (rtypenums[i] != funcdata->arg_types[i]) {
523
 
                        break;
524
 
                    }
525
 
                }
526
 
            }
527
 
            else if (rtypenums[0] == funcdata->arg_types[self->nin]) {
528
 
                i = nargs;
529
 
            }
530
 
            else {
531
 
                i = -1;
532
 
            }
533
 
            if (i == nargs) {
534
 
                *function = funcdata->func;
535
 
                *data = funcdata->data;
536
 
                for(i = 0; i < nargs; i++) {
537
 
                    arg_types[i] = funcdata->arg_types[i];
538
 
                }
539
 
                Py_DECREF(obj);
540
 
                goto finish;
541
 
            }
542
 
            funcdata = funcdata->next;
543
 
        }
544
 
        PyErr_SetString(PyExc_TypeError, msg);
545
 
        goto fail;
546
 
    }
547
 
 
548
 
    /* look for match in self->functions */
549
 
    for (j = 0; j < self->ntypes; j++) {
550
 
        if (n != 1) {
551
 
            for(i = 0; i < nargs; i++) {
552
 
                if (rtypenums[i] != self->types[j*nargs + i]) {
553
 
                    break;
554
 
                }
555
 
            }
556
 
        }
557
 
        else if (rtypenums[0] == self->types[j*nargs+self->nin]) {
558
 
            i = nargs;
559
 
        }
560
 
        else {
561
 
            i = -1;
562
 
        }
563
 
        if (i == nargs) {
564
 
            *function = self->functions[j];
565
 
            *data = self->data[j];
566
 
            for (i = 0; i < nargs; i++) {
567
 
                arg_types[i] = self->types[j*nargs+i];
568
 
            }
569
 
            goto finish;
570
 
        }
571
 
    }
572
 
    PyErr_SetString(PyExc_TypeError, msg);
573
 
 
574
 
 fail:
575
 
    _pya_free(rtypenums);
576
 
    return -1;
577
 
 
578
 
 finish:
579
 
    _pya_free(rtypenums);
580
 
    return 0;
581
 
}
582
 
 
583
 
 
584
 
/*
585
 
 * Called to determine coercion
586
 
 * Can change arg_types.
587
 
 */
588
 
static int
589
 
select_types(PyUFuncObject *self, int *arg_types,
590
 
             PyUFuncGenericFunction *function, void **data,
591
 
             PyArray_SCALARKIND *scalars,
592
 
             PyObject *typetup)
593
 
{
594
 
    int i, j;
595
 
    char start_type;
596
 
    int userdef = -1;
597
 
    int userdef_ind = -1;
598
 
 
599
 
    if (self->userloops) {
600
 
        for(i = 0; i < self->nin; i++) {
601
 
            if (PyTypeNum_ISUSERDEF(arg_types[i])) {
602
 
                userdef = arg_types[i];
603
 
                userdef_ind = i;
604
 
                break;
605
 
            }
606
 
        }
607
 
    }
608
 
 
609
 
    if (typetup != NULL)
610
 
        return extract_specified_loop(self, arg_types, function, data,
611
 
                                      typetup, userdef);
612
 
 
613
 
    if (userdef > 0) {
614
 
        PyObject *key, *obj;
615
 
        int ret = -1;
616
 
        obj = NULL;
617
 
 
618
 
        /*
619
 
         * Look through all the registered loops for all the user-defined
620
 
         * types to find a match.
621
 
         */
622
 
        while (ret == -1) {
623
 
            if (userdef_ind >= self->nin) {
624
 
                break;
625
 
            }
626
 
            userdef = arg_types[userdef_ind++];
627
 
            if (!(PyTypeNum_ISUSERDEF(userdef))) {
628
 
                continue;
629
 
            }
630
 
            key = PyInt_FromLong((long) userdef);
631
 
            if (key == NULL) {
632
 
                return -1;
633
 
            }
634
 
            obj = PyDict_GetItem(self->userloops, key);
635
 
            Py_DECREF(key);
636
 
            if (obj == NULL) {
637
 
                continue;
638
 
            }
639
 
            /*
640
 
             * extract the correct function
641
 
             * data and argtypes for this user-defined type.
642
 
             */
643
 
            ret = _find_matching_userloop(obj, arg_types, scalars,
644
 
                                          function, data, self->nargs,
645
 
                                          self->nin);
646
 
        }
647
 
        if (ret == 0) {
648
 
            return ret;
649
 
        }
650
 
        PyErr_SetString(PyExc_TypeError, _types_msg);
651
 
        return ret;
652
 
    }
653
 
 
654
 
    start_type = arg_types[0];
655
 
    /*
656
 
     * If the first argument is a scalar we need to place
657
 
     * the start type as the lowest type in the class
658
 
     */
659
 
    if (scalars[0] != PyArray_NOSCALAR) {
660
 
        start_type = _lowest_type(start_type);
661
 
    }
662
 
 
663
 
    i = 0;
664
 
    while (i < self->ntypes && start_type > self->types[i*self->nargs]) {
665
 
        i++;
666
 
    }
667
 
    for (; i < self->ntypes; i++) {
668
 
        for (j = 0; j < self->nin; j++) {
669
 
            if (!PyArray_CanCoerceScalar(arg_types[j],
670
 
                                         self->types[i*self->nargs + j],
671
 
                                         scalars[j]))
672
 
                break;
673
 
        }
674
 
        if (j == self->nin) {
675
 
            break;
676
 
        }
677
 
    }
678
 
    if (i >= self->ntypes) {
679
 
        PyErr_SetString(PyExc_TypeError, _types_msg);
680
 
        return -1;
681
 
    }
682
 
    for (j = 0; j < self->nargs; j++) {
683
 
        arg_types[j] = self->types[i*self->nargs+j];
684
 
    }
685
 
    if (self->data) {
686
 
        *data = self->data[i];
687
 
    }
688
 
    else {
689
 
        *data = NULL;
690
 
    }
691
 
    *function = self->functions[i];
692
 
 
693
 
    return 0;
694
 
}
695
 
 
696
368
#if USE_USE_DEFAULTS==1
697
369
static int PyUFunc_NUM_NODEFAULTS = 0;
698
370
#endif
699
371
static PyObject *PyUFunc_PYVALS_NAME = NULL;
700
372
 
701
373
 
 
374
/*
 
375
 * Extracts some values from the global pyvals tuple.
 
376
 * ref - should hold the global tuple
 
377
 * name - is the name of the ufunc (ufuncobj->name)
 
378
 * bufsize - receives the buffer size to use
 
379
 * errmask - receives the bitmask for error handling
 
380
 * errobj - receives the python object to call with the error,
 
381
 *          if an error handling method is 'call'
 
382
 */
702
383
static int
703
384
_extract_pyvals(PyObject *ref, char *name, int *bufsize,
704
385
                int *errmask, PyObject **errobj)
761
442
 
762
443
 
763
444
 
764
 
/*UFUNC_API*/
 
445
/*UFUNC_API
 
446
 *
 
447
 * On return, if errobj is populated with a non-NULL value, the caller
 
448
 * owns a new reference to errobj.
 
449
 */
765
450
NPY_NO_EXPORT int
766
451
PyUFunc_GetPyValues(char *name, int *bufsize, int *errmask, PyObject **errobj)
767
452
{
791
476
    return _extract_pyvals(ref, name, bufsize, errmask, errobj);
792
477
}
793
478
 
794
 
/*
795
 
 * Create copies for any arrays that are less than loop->bufsize
796
 
 * in total size (or core_enabled) and are mis-behaved or in need
797
 
 * of casting.
798
 
 */
799
 
static int
800
 
_create_copies(PyUFuncLoopObject *loop, int *arg_types, PyArrayObject **mps)
801
 
{
802
 
    int nin = loop->ufunc->nin;
803
 
    int i;
804
 
    intp size;
805
 
    PyObject *new;
806
 
    PyArray_Descr *ntype;
807
 
    PyArray_Descr *atype;
808
 
 
809
 
    for (i = 0; i < nin; i++) {
810
 
        size = PyArray_SIZE(mps[i]);
811
 
        /*
812
 
         * if the type of mps[i] is equivalent to arg_types[i]
813
 
         * then set arg_types[i] equal to type of mps[i] for later checking....
814
 
         */
815
 
        if (PyArray_TYPE(mps[i]) != arg_types[i]) {
816
 
            ntype = mps[i]->descr;
817
 
            atype = PyArray_DescrFromType(arg_types[i]);
818
 
            if (PyArray_EquivTypes(atype, ntype)) {
819
 
                arg_types[i] = ntype->type_num;
820
 
            }
821
 
            Py_DECREF(atype);
822
 
        }
823
 
        if (size < loop->bufsize || loop->ufunc->core_enabled) {
824
 
            if (!(PyArray_ISBEHAVED_RO(mps[i]))
825
 
                || PyArray_TYPE(mps[i]) != arg_types[i]) {
826
 
                ntype = PyArray_DescrFromType(arg_types[i]);
827
 
                new = PyArray_FromAny((PyObject *)mps[i],
828
 
                                      ntype, 0, 0,
829
 
                                      FORCECAST | ALIGNED, NULL);
830
 
                if (new == NULL) {
831
 
                        return -1;
832
 
                }
833
 
                Py_DECREF(mps[i]);
834
 
                mps[i] = (PyArrayObject *)new;
835
 
            }
836
 
        }
837
 
    }
838
 
    return 0;
839
 
}
840
 
 
841
479
#define _GETATTR_(str, rstr) do {if (strcmp(name, #str) == 0)     \
842
480
        return PyObject_HasAttrString(op, "__" #rstr "__");} while (0);
843
481
 
1065
703
    return -1;
1066
704
}
1067
705
 
 
706
 
 
707
/********* GENERIC UFUNC USING ITERATOR *********/
 
708
 
1068
709
/*
1069
 
 * Concatenate the loop and core dimensions of
1070
 
 * PyArrayMultiIterObject's iarg-th argument, to recover a full
1071
 
 * dimension array (used for output arguments).
 
710
 * Parses the positional and keyword arguments for a generic ufunc call.
 
711
 *
 
712
 * Note that if an error is returned, the caller must free the
 
713
 * non-zero references in out_op.  This
 
714
 * function does not do its own clean-up.
1072
715
 */
1073
 
static npy_intp*
1074
 
_compute_output_dims(PyUFuncLoopObject *loop, int iarg,
1075
 
                     int *out_nd, npy_intp *tmp_dims)
1076
 
{
1077
 
    int i;
1078
 
    PyUFuncObject *ufunc = loop->ufunc;
1079
 
    if (ufunc->core_enabled == 0) {
1080
 
        /* case of ufunc with trivial core-signature */
1081
 
        *out_nd = loop->nd;
1082
 
        return loop->dimensions;
1083
 
    }
1084
 
 
1085
 
    *out_nd = loop->nd + ufunc->core_num_dims[iarg];
1086
 
    if (*out_nd > NPY_MAXARGS) {
1087
 
        PyErr_SetString(PyExc_ValueError,
1088
 
                        "dimension of output variable exceeds limit");
1089
 
        return NULL;
1090
 
    }
1091
 
 
1092
 
    /* copy loop dimensions */
1093
 
    memcpy(tmp_dims, loop->dimensions, sizeof(npy_intp) * loop->nd);
1094
 
 
1095
 
    /* copy core dimension */
1096
 
    for (i = 0; i < ufunc->core_num_dims[iarg]; i++) {
1097
 
        tmp_dims[loop->nd + i] = loop->core_dim_sizes[1 +
1098
 
            ufunc->core_dim_ixs[ufunc->core_offsets[iarg] + i]];
1099
 
    }
1100
 
    return tmp_dims;
1101
 
}
1102
 
 
1103
 
/* Check and set core_dim_sizes and core_strides for the i-th argument. */
1104
 
static int
1105
 
_compute_dimension_size(PyUFuncLoopObject *loop, PyArrayObject **mps, int i)
1106
 
{
1107
 
    PyUFuncObject *ufunc = loop->ufunc;
1108
 
    int j = ufunc->core_offsets[i];
1109
 
    int k = PyArray_NDIM(mps[i]) - ufunc->core_num_dims[i];
1110
 
    int ind;
1111
 
    for (ind = 0; ind < ufunc->core_num_dims[i]; ind++, j++, k++) {
1112
 
        npy_intp dim = k < 0 ? 1 : PyArray_DIM(mps[i], k);
1113
 
        /* First element of core_dim_sizes will be used for looping */
1114
 
        int dim_ix = ufunc->core_dim_ixs[j] + 1;
1115
 
        if (loop->core_dim_sizes[dim_ix] == 1) {
1116
 
            /* broadcast core dimension  */
1117
 
            loop->core_dim_sizes[dim_ix] = dim;
1118
 
        }
1119
 
        else if (dim != 1 && dim != loop->core_dim_sizes[dim_ix]) {
1120
 
            PyErr_SetString(PyExc_ValueError, "core dimensions mismatch");
1121
 
            return -1;
1122
 
        }
1123
 
        /* First ufunc->nargs elements will be used for looping */
1124
 
        loop->core_strides[ufunc->nargs + j] =
1125
 
            dim == 1 ? 0 : PyArray_STRIDE(mps[i], k);
1126
 
    }
1127
 
    return 0;
1128
 
}
1129
 
 
1130
 
/* Return a view of array "ap" with "core_nd" dimensions cut from tail. */
1131
 
static PyArrayObject *
1132
 
_trunc_coredim(PyArrayObject *ap, int core_nd)
1133
 
{
1134
 
    PyArrayObject *ret;
1135
 
    int nd = ap->nd - core_nd;
1136
 
 
1137
 
    if (nd < 0) {
1138
 
        nd = 0;
1139
 
    }
1140
 
    /* The following code is basically taken from PyArray_Transpose */
1141
 
    /* NewFromDescr will steal this reference */
1142
 
    Py_INCREF(ap->descr);
1143
 
    ret = (PyArrayObject *)
1144
 
        PyArray_NewFromDescr(Py_TYPE(ap), ap->descr,
1145
 
                             nd, ap->dimensions,
1146
 
                             ap->strides, ap->data, ap->flags,
1147
 
                             (PyObject *)ap);
1148
 
    if (ret == NULL) {
1149
 
        return NULL;
1150
 
    }
1151
 
    /* point at true owner of memory: */
1152
 
    ret->base = (PyObject *)ap;
1153
 
    Py_INCREF(ap);
1154
 
    PyArray_UpdateFlags(ret, CONTIGUOUS | FORTRAN);
1155
 
    return ret;
1156
 
}
1157
 
 
1158
 
static Py_ssize_t
1159
 
construct_arrays(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps,
1160
 
                 PyObject *typetup)
1161
 
{
1162
 
    Py_ssize_t nargs;
1163
 
    int i;
1164
 
    int arg_types[NPY_MAXARGS];
1165
 
    PyArray_SCALARKIND scalars[NPY_MAXARGS];
1166
 
    PyArray_SCALARKIND maxarrkind, maxsckind, new;
1167
 
    PyUFuncObject *self = loop->ufunc;
1168
 
    Bool allscalars = TRUE;
1169
 
    PyTypeObject *subtype = &PyArray_Type;
1170
 
    PyObject *context = NULL;
1171
 
    PyObject *obj;
1172
 
    int flexible = 0;
1173
 
    int object = 0;
1174
 
 
1175
 
    npy_intp temp_dims[NPY_MAXDIMS];
1176
 
    npy_intp *out_dims;
1177
 
    int out_nd;
1178
 
    PyObject *wraparr[NPY_MAXARGS];
 
716
static int get_ufunc_arguments(PyUFuncObject *self,
 
717
                PyObject *args, PyObject *kwds,
 
718
                PyArrayObject **out_op,
 
719
                NPY_ORDER *out_order,
 
720
                NPY_CASTING *out_casting,
 
721
                PyObject **out_extobj,
 
722
                PyObject **out_typetup,
 
723
                int *out_subok,
 
724
                int *out_any_object)
 
725
{
 
726
    npy_intp i, nargs, nin = self->nin;
 
727
    PyObject *obj, *context;
 
728
    PyObject *str_key_obj = NULL;
 
729
    char *ufunc_name;
 
730
 
 
731
    int any_flexible = 0, any_object = 0;
 
732
 
 
733
    ufunc_name = self->name ? self->name : "<unnamed ufunc>";
1179
734
 
1180
735
    /* Check number of arguments */
1181
736
    nargs = PyTuple_Size(args);
1182
 
    if ((nargs < self->nin) || (nargs > self->nargs)) {
 
737
    if ((nargs < nin) || (nargs > self->nargs)) {
1183
738
        PyErr_SetString(PyExc_ValueError, "invalid number of arguments");
1184
739
        return -1;
1185
740
    }
1186
741
 
1187
 
    /* Get each input argument */
1188
 
    maxarrkind = PyArray_NOSCALAR;
1189
 
    maxsckind = PyArray_NOSCALAR;
1190
 
    for(i = 0; i < self->nin; i++) {
1191
 
        obj = PyTuple_GET_ITEM(args,i);
 
742
    /* Get input arguments */
 
743
    for(i = 0; i < nin; ++i) {
 
744
        obj = PyTuple_GET_ITEM(args, i);
1192
745
        if (!PyArray_Check(obj) && !PyArray_IsScalar(obj, Generic)) {
 
746
            /*
 
747
             * TODO: There should be a comment here explaining what
 
748
             *       context does.
 
749
             */
1193
750
            context = Py_BuildValue("OOi", self, args, i);
 
751
            if (context == NULL) {
 
752
                return -1;
 
753
            }
1194
754
        }
1195
755
        else {
1196
756
            context = NULL;
1197
757
        }
1198
 
        mps[i] = (PyArrayObject *)PyArray_FromAny(obj, NULL, 0, 0, 0, context);
 
758
        out_op[i] = (PyArrayObject *)PyArray_FromAny(obj,
 
759
                                        NULL, 0, 0, 0, context);
1199
760
        Py_XDECREF(context);
1200
 
        if (mps[i] == NULL) {
1201
 
            return -1;
1202
 
        }
1203
 
        arg_types[i] = PyArray_TYPE(mps[i]);
1204
 
        if (!flexible && PyTypeNum_ISFLEXIBLE(arg_types[i])) {
1205
 
            flexible = 1;
1206
 
        }
1207
 
        if (!object && PyTypeNum_ISOBJECT(arg_types[i])) {
1208
 
            object = 1;
1209
 
        }
1210
 
        /*
1211
 
         * debug
1212
 
         * fprintf(stderr, "array %d has reference %d\n", i,
1213
 
         * (mps[i])->ob_refcnt);
1214
 
         */
1215
 
 
1216
 
        /*
1217
 
         * Scalars are 0-dimensional arrays at this point
1218
 
         */
1219
 
 
1220
 
        /*
1221
 
         * We need to keep track of whether or not scalars
1222
 
         * are mixed with arrays of different kinds.
1223
 
         */
1224
 
 
1225
 
        if (mps[i]->nd > 0) {
1226
 
            scalars[i] = PyArray_NOSCALAR;
1227
 
            allscalars = FALSE;
1228
 
            new = PyArray_ScalarKind(arg_types[i], NULL);
1229
 
            maxarrkind = NPY_MAX(new, maxarrkind);
1230
 
        }
1231
 
        else {
1232
 
            scalars[i] = PyArray_ScalarKind(arg_types[i], &(mps[i]));
1233
 
            maxsckind = NPY_MAX(scalars[i], maxsckind);
1234
 
        }
1235
 
    }
1236
 
 
1237
 
    /* We don't do strings */
1238
 
    if (flexible && !object) {
1239
 
        loop->notimplemented = 1;
1240
 
        return nargs;
1241
 
    }
1242
 
 
1243
 
    /*
1244
 
     * If everything is a scalar, or scalars mixed with arrays of
1245
 
     * different kinds of lesser kinds then use normal coercion rules
1246
 
     */
1247
 
    if (allscalars || (maxsckind > maxarrkind)) {
1248
 
        for (i = 0; i < self->nin; i++) {
1249
 
            scalars[i] = PyArray_NOSCALAR;
1250
 
        }
1251
 
    }
1252
 
 
1253
 
    /* Select an appropriate function for these argument types. */
1254
 
    if (select_types(loop->ufunc, arg_types, &(loop->function),
1255
 
                     &(loop->funcdata), scalars, typetup) == -1) {
1256
 
        return -1;
1257
 
    }
1258
 
    /*
1259
 
     * FAIL with NotImplemented if the other object has
1260
 
     * the __r<op>__ method and has __array_priority__ as
1261
 
     * an attribute (signalling it can handle ndarray's)
1262
 
     * and is not already an ndarray or a subtype of the same type.
1263
 
     */
1264
 
    if ((arg_types[1] == PyArray_OBJECT)
1265
 
        && (loop->ufunc->nin==2) && (loop->ufunc->nout == 1)) {
1266
 
        PyObject *_obj = PyTuple_GET_ITEM(args, 1);
1267
 
        if (!PyArray_CheckExact(_obj)
1268
 
            /* If both are same subtype of object arrays, then proceed */
1269
 
            && !(Py_TYPE(_obj) == Py_TYPE(PyTuple_GET_ITEM(args, 0)))
1270
 
            && PyObject_HasAttrString(_obj, "__array_priority__")
1271
 
            && _has_reflected_op(_obj, loop->ufunc->name)) {
1272
 
            loop->notimplemented = 1;
1273
 
            return nargs;
1274
 
        }
1275
 
    }
1276
 
 
1277
 
    /*
1278
 
     * Create copies for some of the arrays if they are small
1279
 
     * enough and not already contiguous
1280
 
     */
1281
 
    if (_create_copies(loop, arg_types, mps) < 0) {
1282
 
        return -1;
1283
 
    }
1284
 
 
1285
 
    /*
1286
 
     * Only use loop dimensions when constructing Iterator:
1287
 
     * temporarily replace mps[i] (will be recovered below).
1288
 
     */
1289
 
    if (self->core_enabled) {
1290
 
        for (i = 0; i < self->nin; i++) {
1291
 
            PyArrayObject *ao;
1292
 
 
1293
 
            if (_compute_dimension_size(loop, mps, i) < 0) {
1294
 
                return -1;
1295
 
            }
1296
 
            ao = _trunc_coredim(mps[i], self->core_num_dims[i]);
1297
 
            if (ao == NULL) {
1298
 
                return -1;
1299
 
            }
1300
 
            mps[i] = ao;
1301
 
        }
1302
 
    }
1303
 
 
1304
 
    /* Create Iterators for the Inputs */
1305
 
    for (i = 0; i < self->nin; i++) {
1306
 
        loop->iters[i] = (PyArrayIterObject *)
1307
 
            PyArray_IterNew((PyObject *)mps[i]);
1308
 
        if (loop->iters[i] == NULL) {
1309
 
            return -1;
1310
 
        }
1311
 
    }
1312
 
 
1313
 
    /* Recover mps[i]. */
1314
 
    if (self->core_enabled) {
1315
 
        for (i = 0; i < self->nin; i++) {
1316
 
            PyArrayObject *ao = mps[i];
1317
 
            mps[i] = (PyArrayObject *)mps[i]->base;
1318
 
            Py_DECREF(ao);
1319
 
        }
1320
 
    }
1321
 
 
1322
 
    /* Broadcast the result */
1323
 
    loop->numiter = self->nin;
1324
 
    if (PyArray_Broadcast((PyArrayMultiIterObject *)loop) < 0) {
1325
 
        return -1;
1326
 
    }
1327
 
 
1328
 
    /* Get any return arguments */
1329
 
    for (i = self->nin; i < nargs; i++) {
1330
 
        mps[i] = (PyArrayObject *)PyTuple_GET_ITEM(args, i);
1331
 
        if (((PyObject *)mps[i])==Py_None) {
1332
 
            mps[i] = NULL;
 
761
        if (out_op[i] == NULL) {
 
762
            return -1;
 
763
        }
 
764
        if (!any_flexible &&
 
765
                PyTypeNum_ISFLEXIBLE(PyArray_DESCR(out_op[i])->type_num)) {
 
766
            any_flexible = 1;
 
767
        }
 
768
        if (!any_object &&
 
769
                PyTypeNum_ISOBJECT(PyArray_DESCR(out_op[i])->type_num)) {
 
770
            any_object = 1;
 
771
        }
 
772
    }
 
773
 
 
774
    /*
 
775
     * Indicate not implemented if there are flexible objects (structured
 
776
     * type or string) but no object types.
 
777
     *
 
778
     * Not sure - adding this increased to 246 errors, 150 failures.
 
779
     */
 
780
    if (any_flexible && !any_object) {
 
781
        return -2;
 
782
 
 
783
    }
 
784
 
 
785
    /* Get positional output arguments */
 
786
    for (i = nin; i < nargs; ++i) {
 
787
        obj = PyTuple_GET_ITEM(args, i);
 
788
        /* Translate None to NULL */
 
789
        if (obj == Py_None) {
1333
790
            continue;
1334
791
        }
1335
 
        Py_INCREF(mps[i]);
1336
 
        if (!PyArray_Check((PyObject *)mps[i])) {
1337
 
            PyObject *new;
1338
 
            if (PyArrayIter_Check(mps[i])) {
1339
 
                new = PyObject_CallMethod((PyObject *)mps[i],
1340
 
                                          "__array__", NULL);
1341
 
                Py_DECREF(mps[i]);
1342
 
                mps[i] = (PyArrayObject *)new;
1343
 
            }
1344
 
            else {
1345
 
                PyErr_SetString(PyExc_TypeError,
1346
 
                                "return arrays must be "\
1347
 
                                "of ArrayType");
1348
 
                Py_DECREF(mps[i]);
1349
 
                mps[i] = NULL;
1350
 
                return -1;
1351
 
            }
1352
 
        }
1353
 
 
1354
 
        if (self->core_enabled) {
1355
 
            if (_compute_dimension_size(loop, mps, i) < 0) {
1356
 
                return -1;
1357
 
            }
1358
 
        }
1359
 
        out_dims = _compute_output_dims(loop, i, &out_nd, temp_dims);
1360
 
        if (!out_dims) {
1361
 
            return -1;
1362
 
        }
1363
 
        if (mps[i]->nd != out_nd
1364
 
            || !PyArray_CompareLists(mps[i]->dimensions, out_dims, out_nd)) {
1365
 
            PyErr_SetString(PyExc_ValueError, "invalid return array shape");
1366
 
            Py_DECREF(mps[i]);
1367
 
            mps[i] = NULL;
1368
 
            return -1;
1369
 
        }
1370
 
        if (!PyArray_ISWRITEABLE(mps[i])) {
1371
 
            PyErr_SetString(PyExc_ValueError, "return array is not writeable");
1372
 
            Py_DECREF(mps[i]);
1373
 
            mps[i] = NULL;
1374
 
            return -1;
1375
 
        }
1376
 
    }
1377
 
 
1378
 
    /* construct any missing return arrays and make output iterators */
1379
 
    for(i = self->nin; i < self->nargs; i++) {
1380
 
        PyArray_Descr *ntype;
1381
 
 
1382
 
        if (mps[i] == NULL) {
1383
 
            out_dims = _compute_output_dims(loop, i, &out_nd, temp_dims);
1384
 
            if (!out_dims) {
1385
 
                return -1;
1386
 
            }
1387
 
            mps[i] = (PyArrayObject *)PyArray_New(subtype,
1388
 
                                                  out_nd,
1389
 
                                                  out_dims,
1390
 
                                                  arg_types[i],
1391
 
                                                  NULL, NULL,
1392
 
                                                  0, 0, NULL);
1393
 
            if (mps[i] == NULL) {
1394
 
                return -1;
1395
 
            }
1396
 
        }
1397
 
 
1398
 
        /*
1399
 
         * reset types for outputs that are equivalent
1400
 
         * -- no sense casting uselessly
1401
 
         */
 
792
        /* If it's an array, can use it */
 
793
        if (PyArray_Check(obj)) {
 
794
            if (!PyArray_ISWRITEABLE(obj)) {
 
795
                PyErr_SetString(PyExc_ValueError,
 
796
                                "return array is not writeable");
 
797
                return -1;
 
798
            }
 
799
            Py_INCREF(obj);
 
800
            out_op[i] = (PyArrayObject *)obj;
 
801
        }
1402
802
        else {
1403
 
            if (mps[i]->descr->type_num != arg_types[i]) {
1404
 
                PyArray_Descr *atype;
1405
 
                ntype = mps[i]->descr;
1406
 
                atype = PyArray_DescrFromType(arg_types[i]);
1407
 
                if (PyArray_EquivTypes(atype, ntype)) {
1408
 
                    arg_types[i] = ntype->type_num;
1409
 
                }
1410
 
                Py_DECREF(atype);
1411
 
            }
1412
 
 
1413
 
            /* still not the same -- or will we have to use buffers?*/
1414
 
            if (mps[i]->descr->type_num != arg_types[i]
1415
 
                || !PyArray_ISBEHAVED_RO(mps[i])) {
1416
 
                if (loop->size < loop->bufsize || self->core_enabled) {
1417
 
                    PyObject *new;
1418
 
                    /*
1419
 
                     * Copy the array to a temporary copy
1420
 
                     * and set the UPDATEIFCOPY flag
1421
 
                     */
1422
 
                    ntype = PyArray_DescrFromType(arg_types[i]);
1423
 
                    new = PyArray_FromAny((PyObject *)mps[i],
1424
 
                                          ntype, 0, 0,
1425
 
                                          FORCECAST | ALIGNED |
1426
 
                                          UPDATEIFCOPY, NULL);
1427
 
                    if (new == NULL) {
1428
 
                        return -1;
1429
 
                    }
1430
 
                    Py_DECREF(mps[i]);
1431
 
                    mps[i] = (PyArrayObject *)new;
1432
 
                }
1433
 
            }
1434
 
        }
1435
 
 
1436
 
        if (self->core_enabled) {
1437
 
            PyArrayObject *ao;
1438
 
 
1439
 
            /* computer for all output arguments, and set strides in "loop" */
1440
 
            if (_compute_dimension_size(loop, mps, i) < 0) {
1441
 
                return -1;
1442
 
            }
1443
 
            ao = _trunc_coredim(mps[i], self->core_num_dims[i]);
1444
 
            if (ao == NULL) {
1445
 
                return -1;
1446
 
            }
1447
 
            /* Temporarily modify mps[i] for constructing iterator. */
1448
 
            mps[i] = ao;
1449
 
        }
1450
 
 
1451
 
        loop->iters[i] = (PyArrayIterObject *)
1452
 
            PyArray_IterNew((PyObject *)mps[i]);
1453
 
        if (loop->iters[i] == NULL) {
1454
 
            return -1;
1455
 
        }
1456
 
 
1457
 
        /* Recover mps[i]. */
1458
 
        if (self->core_enabled) {
1459
 
            PyArrayObject *ao = mps[i];
1460
 
            mps[i] = (PyArrayObject *)mps[i]->base;
1461
 
            Py_DECREF(ao);
1462
 
        }
1463
 
 
1464
 
    }
1465
 
 
1466
 
    /*
1467
 
     * Use __array_prepare__ on all outputs
1468
 
     * if present on one of the input arguments.
1469
 
     * If present for multiple inputs:
1470
 
     * use __array_prepare__ of input object with largest
1471
 
     * __array_priority__ (default = 0.0)
1472
 
     *
1473
 
     * Exception:  we should not wrap outputs for items already
1474
 
     * passed in as output-arguments.  These items should either
1475
 
     * be left unwrapped or wrapped by calling their own __array_prepare__
1476
 
     * routine.
1477
 
     *
1478
 
     * For each output argument, wrap will be either
1479
 
     * NULL --- call PyArray_Return() -- default if no output arguments given
1480
 
     * None --- array-object passed in don't call PyArray_Return
1481
 
     * method --- the __array_prepare__ method to call.
1482
 
     */
1483
 
    _find_array_prepare(args, wraparr, loop->ufunc->nin, loop->ufunc->nout);
1484
 
 
1485
 
    /* wrap outputs */
1486
 
    for (i = 0; i < loop->ufunc->nout; i++) {
1487
 
        int j = loop->ufunc->nin+i;
1488
 
        PyObject *wrap;
1489
 
        PyObject *res;
1490
 
        wrap = wraparr[i];
1491
 
        if (wrap != NULL) {
1492
 
            if (wrap == Py_None) {
1493
 
                Py_DECREF(wrap);
1494
 
                continue;
1495
 
            }
1496
 
            res = PyObject_CallFunction(wrap, "O(OOi)",
1497
 
                        mps[j], loop->ufunc, args, i);
1498
 
            Py_DECREF(wrap);
1499
 
            if ((res == NULL) || (res == Py_None)) {
1500
 
                if (!PyErr_Occurred()){
1501
 
                    PyErr_SetString(PyExc_TypeError,
1502
 
                            "__array_prepare__ must return an ndarray or subclass thereof");
1503
 
                }
1504
 
                return -1;
1505
 
            }
1506
 
            Py_DECREF(mps[j]);
1507
 
            mps[j] = (PyArrayObject *)res;
1508
 
        }
1509
 
    }
1510
 
 
1511
 
    /*
1512
 
     * If any of different type, or misaligned or swapped
1513
 
     * then must use buffers
1514
 
     */
1515
 
    loop->bufcnt = 0;
1516
 
    loop->obj = 0;
1517
 
    /* Determine looping method needed */
1518
 
    loop->meth = NO_UFUNCLOOP;
1519
 
    if (loop->size == 0) {
1520
 
        return nargs;
1521
 
    }
1522
 
    if (self->core_enabled) {
1523
 
        loop->meth = SIGNATURE_NOBUFFER_UFUNCLOOP;
1524
 
    }
1525
 
    for (i = 0; i < self->nargs; i++) {
1526
 
        loop->needbuffer[i] = 0;
1527
 
        if (arg_types[i] != mps[i]->descr->type_num
1528
 
            || !PyArray_ISBEHAVED_RO(mps[i])) {
1529
 
            if (self->core_enabled) {
1530
 
                PyErr_SetString(PyExc_RuntimeError,
1531
 
                                "never reached; copy should have been made");
1532
 
                return -1;
1533
 
            }
1534
 
            loop->meth = BUFFER_UFUNCLOOP;
1535
 
            loop->needbuffer[i] = 1;
1536
 
        }
1537
 
        if (!(loop->obj & UFUNC_OBJ_ISOBJECT)
1538
 
                && ((mps[i]->descr->type_num == PyArray_OBJECT)
1539
 
                    || (arg_types[i] == PyArray_OBJECT))) {
1540
 
            loop->obj = UFUNC_OBJ_ISOBJECT|UFUNC_OBJ_NEEDS_API;
1541
 
        }
1542
 
    }
1543
 
 
1544
 
    if (self->core_enabled && (loop->obj & UFUNC_OBJ_ISOBJECT)) {
1545
 
        PyErr_SetString(PyExc_TypeError,
1546
 
                        "Object type not allowed in ufunc with signature");
1547
 
        return -1;
1548
 
    }
1549
 
    if (loop->meth == NO_UFUNCLOOP) {
1550
 
        loop->meth = ONE_UFUNCLOOP;
1551
 
 
1552
 
        /* All correct type and BEHAVED */
1553
 
        /* Check for non-uniform stridedness */
1554
 
        for (i = 0; i < self->nargs; i++) {
1555
 
            if (!(loop->iters[i]->contiguous)) {
1556
 
                /*
1557
 
                 * May still have uniform stride
1558
 
                 * if (broadcast result) <= 1-d
1559
 
                 */
1560
 
                if (mps[i]->nd != 0 &&                  \
1561
 
                    (loop->iters[i]->nd_m1 > 0)) {
1562
 
                    loop->meth = NOBUFFER_UFUNCLOOP;
1563
 
                    break;
1564
 
                }
1565
 
            }
1566
 
        }
1567
 
        if (loop->meth == ONE_UFUNCLOOP) {
1568
 
            for (i = 0; i < self->nargs; i++) {
1569
 
                loop->bufptr[i] = mps[i]->data;
1570
 
            }
1571
 
        }
1572
 
    }
1573
 
 
1574
 
    loop->numiter = self->nargs;
1575
 
 
1576
 
    /* Fill in steps  */
1577
 
    if (loop->meth == SIGNATURE_NOBUFFER_UFUNCLOOP && loop->nd == 0) {
1578
 
        /* Use default core_strides */
1579
 
    }
1580
 
    else if (loop->meth != ONE_UFUNCLOOP) {
1581
 
        int ldim;
1582
 
        intp minsum;
1583
 
        intp maxdim;
1584
 
        PyArrayIterObject *it;
1585
 
        intp stride_sum[NPY_MAXDIMS];
1586
 
        int j;
1587
 
 
1588
 
        /* Fix iterators */
1589
 
 
1590
 
        /*
1591
 
         * Optimize axis the iteration takes place over
1592
 
         *
1593
 
         * The first thought was to have the loop go
1594
 
         * over the largest dimension to minimize the number of loops
1595
 
         *
1596
 
         * However, on processors with slow memory bus and cache,
1597
 
         * the slowest loops occur when the memory access occurs for
1598
 
         * large strides.
1599
 
         *
1600
 
         * Thus, choose the axis for which strides of the last iterator is
1601
 
         * smallest but non-zero.
1602
 
         */
1603
 
        for (i = 0; i < loop->nd; i++) {
1604
 
            stride_sum[i] = 0;
1605
 
            for (j = 0; j < loop->numiter; j++) {
1606
 
                stride_sum[i] += loop->iters[j]->strides[i];
1607
 
            }
1608
 
        }
1609
 
 
1610
 
        ldim = loop->nd - 1;
1611
 
        minsum = stride_sum[loop->nd - 1];
1612
 
        for (i = loop->nd - 2; i >= 0; i--) {
1613
 
            if (stride_sum[i] < minsum ) {
1614
 
                ldim = i;
1615
 
                minsum = stride_sum[i];
1616
 
            }
1617
 
        }
1618
 
        maxdim = loop->dimensions[ldim];
1619
 
        loop->size /= maxdim;
1620
 
        loop->bufcnt = maxdim;
1621
 
        loop->lastdim = ldim;
1622
 
 
1623
 
        /*
1624
 
         * Fix the iterators so the inner loop occurs over the
1625
 
         * largest dimensions -- This can be done by
1626
 
         * setting the size to 1 in that dimension
1627
 
         * (just in the iterators)
1628
 
         */
1629
 
        for (i = 0; i < loop->numiter; i++) {
1630
 
            it = loop->iters[i];
1631
 
            it->contiguous = 0;
1632
 
            it->size /= (it->dims_m1[ldim] + 1);
1633
 
            it->dims_m1[ldim] = 0;
1634
 
            it->backstrides[ldim] = 0;
1635
 
 
1636
 
            /*
1637
 
             * (won't fix factors because we
1638
 
             * don't use PyArray_ITER_GOTO1D
1639
 
             * so don't change them)
1640
 
             *
1641
 
             * Set the steps to the strides in that dimension
1642
 
             */
1643
 
            loop->steps[i] = it->strides[ldim];
1644
 
        }
1645
 
 
1646
 
        /*
1647
 
         * Set looping part of core_dim_sizes and core_strides.
1648
 
         */
1649
 
        if (loop->meth == SIGNATURE_NOBUFFER_UFUNCLOOP) {
1650
 
            loop->core_dim_sizes[0] = maxdim;
1651
 
            for (i = 0; i < self->nargs; i++) {
1652
 
                loop->core_strides[i] = loop->steps[i];
1653
 
            }
1654
 
        }
1655
 
 
1656
 
        /*
1657
 
         * fix up steps where we will be copying data to
1658
 
         * buffers and calculate the ninnerloops and leftover
1659
 
         * values -- if step size is already zero that is not changed...
1660
 
         */
1661
 
        if (loop->meth == BUFFER_UFUNCLOOP) {
1662
 
            loop->leftover = maxdim % loop->bufsize;
1663
 
            loop->ninnerloops = (maxdim / loop->bufsize) + 1;
1664
 
            for (i = 0; i < self->nargs; i++) {
1665
 
                if (loop->needbuffer[i] && loop->steps[i]) {
1666
 
                    loop->steps[i] = mps[i]->descr->elsize;
1667
 
                }
1668
 
                /* These are changed later if casting is needed */
1669
 
            }
1670
 
        }
1671
 
    }
1672
 
    else if (loop->meth == ONE_UFUNCLOOP) {
1673
 
        /* uniformly-strided case */
1674
 
        for (i = 0; i < self->nargs; i++) {
1675
 
            if (PyArray_SIZE(mps[i]) == 1) {
1676
 
                loop->steps[i] = 0;
1677
 
            }
1678
 
            else {
1679
 
                loop->steps[i] = mps[i]->strides[mps[i]->nd - 1];
1680
 
            }
1681
 
        }
1682
 
    }
1683
 
 
1684
 
 
1685
 
    /* Finally, create memory for buffers if we need them */
1686
 
 
1687
 
    /*
1688
 
     * Buffers for scalars are specially made small -- scalars are
1689
 
     * not copied multiple times
1690
 
     */
1691
 
    if (loop->meth == BUFFER_UFUNCLOOP) {
1692
 
        int cnt = 0, cntcast = 0;
1693
 
        int scnt = 0, scntcast = 0;
1694
 
        char *castptr;
1695
 
        char *bufptr;
1696
 
        int last_was_scalar = 0;
1697
 
        int last_cast_was_scalar = 0;
1698
 
        int oldbufsize = 0;
1699
 
        int oldsize = 0;
1700
 
        int scbufsize = 4*sizeof(double);
1701
 
        int memsize;
1702
 
        PyArray_Descr *descr;
1703
 
 
1704
 
        /* compute the element size */
1705
 
        for (i = 0; i < self->nargs; i++) {
1706
 
            if (!loop->needbuffer[i]) {
1707
 
                continue;
1708
 
            }
1709
 
            if (arg_types[i] != mps[i]->descr->type_num) {
1710
 
                descr = PyArray_DescrFromType(arg_types[i]);
1711
 
                if (loop->steps[i]) {
1712
 
                    cntcast += descr->elsize;
1713
 
                }
1714
 
                else {
1715
 
                    scntcast += descr->elsize;
1716
 
                }
1717
 
                if (i < self->nin) {
1718
 
                    loop->cast[i] = PyArray_GetCastFunc(mps[i]->descr,
1719
 
                                            arg_types[i]);
1720
 
                }
1721
 
                else {
1722
 
                    loop->cast[i] = PyArray_GetCastFunc \
1723
 
                        (descr, mps[i]->descr->type_num);
1724
 
                }
1725
 
                Py_DECREF(descr);
1726
 
                if (!loop->cast[i]) {
1727
 
                    return -1;
1728
 
                }
1729
 
            }
1730
 
            loop->swap[i] = !(PyArray_ISNOTSWAPPED(mps[i]));
1731
 
            if (loop->steps[i]) {
1732
 
                cnt += mps[i]->descr->elsize;
1733
 
            }
1734
 
            else {
1735
 
                scnt += mps[i]->descr->elsize;
1736
 
            }
1737
 
        }
1738
 
        memsize = loop->bufsize*(cnt+cntcast) + scbufsize*(scnt+scntcast);
1739
 
        loop->buffer[0] = PyDataMem_NEW(memsize);
1740
 
 
1741
 
        /*
1742
 
         * debug
1743
 
         * fprintf(stderr, "Allocated buffer at %p of size %d, cnt=%d, cntcast=%d\n",
1744
 
         *               loop->buffer[0], loop->bufsize * (cnt + cntcast), cnt, cntcast);
1745
 
         */
1746
 
        if (loop->buffer[0] == NULL) {
1747
 
            PyErr_NoMemory();
1748
 
            return -1;
1749
 
        }
1750
 
        if (loop->obj & UFUNC_OBJ_ISOBJECT) {
1751
 
            memset(loop->buffer[0], 0, memsize);
1752
 
        }
1753
 
        castptr = loop->buffer[0] + loop->bufsize*cnt + scbufsize*scnt;
1754
 
        bufptr = loop->buffer[0];
1755
 
        loop->objfunc = 0;
1756
 
        for (i = 0; i < self->nargs; i++) {
1757
 
            if (!loop->needbuffer[i]) {
1758
 
                continue;
1759
 
            }
1760
 
            loop->buffer[i] = bufptr + (last_was_scalar ? scbufsize :
1761
 
                                        loop->bufsize)*oldbufsize;
1762
 
            last_was_scalar = (loop->steps[i] == 0);
1763
 
            bufptr = loop->buffer[i];
1764
 
            oldbufsize = mps[i]->descr->elsize;
1765
 
            /* fprintf(stderr, "buffer[%d] = %p\n", i, loop->buffer[i]); */
1766
 
            if (loop->cast[i]) {
1767
 
                PyArray_Descr *descr;
1768
 
                loop->castbuf[i] = castptr + (last_cast_was_scalar ? scbufsize :
1769
 
                                              loop->bufsize)*oldsize;
1770
 
                last_cast_was_scalar = last_was_scalar;
1771
 
                /* fprintf(stderr, "castbuf[%d] = %p\n", i, loop->castbuf[i]); */
1772
 
                descr = PyArray_DescrFromType(arg_types[i]);
1773
 
                oldsize = descr->elsize;
1774
 
                Py_DECREF(descr);
1775
 
                loop->bufptr[i] = loop->castbuf[i];
1776
 
                castptr = loop->castbuf[i];
1777
 
                if (loop->steps[i]) {
1778
 
                    loop->steps[i] = oldsize;
1779
 
                }
1780
 
            }
1781
 
            else {
1782
 
                loop->bufptr[i] = loop->buffer[i];
1783
 
            }
1784
 
            if (!loop->objfunc && (loop->obj & UFUNC_OBJ_ISOBJECT)) {
1785
 
                if (arg_types[i] == PyArray_OBJECT) {
1786
 
                    loop->objfunc = 1;
1787
 
                }
1788
 
            }
1789
 
        }
1790
 
    }
1791
 
 
1792
 
    if (_does_loop_use_arrays(loop->funcdata)) {
1793
 
        loop->funcdata = (void*)mps;
1794
 
    }
1795
 
 
1796
 
    return nargs;
1797
 
}
1798
 
 
1799
 
static void
1800
 
ufuncreduce_dealloc(PyUFuncReduceObject *self)
1801
 
{
1802
 
    if (self->ufunc) {
1803
 
        Py_XDECREF(self->it);
1804
 
        Py_XDECREF(self->rit);
1805
 
        Py_XDECREF(self->ret);
1806
 
        Py_XDECREF(self->errobj);
1807
 
        Py_XDECREF(self->decref);
1808
 
        if (self->buffer) {
1809
 
            PyDataMem_FREE(self->buffer);
1810
 
        }
1811
 
        Py_DECREF(self->ufunc);
1812
 
    }
1813
 
    _pya_free(self);
1814
 
}
1815
 
 
1816
 
static void
1817
 
ufuncloop_dealloc(PyUFuncLoopObject *self)
1818
 
{
1819
 
    int i;
1820
 
 
1821
 
    if (self->ufunc != NULL) {
1822
 
        if (self->core_dim_sizes) {
1823
 
            _pya_free(self->core_dim_sizes);
1824
 
        }
1825
 
        if (self->core_strides) {
1826
 
            _pya_free(self->core_strides);
1827
 
        }
1828
 
        for (i = 0; i < self->ufunc->nargs; i++) {
1829
 
            Py_XDECREF(self->iters[i]);
1830
 
        }
1831
 
        if (self->buffer[0]) {
1832
 
            PyDataMem_FREE(self->buffer[0]);
1833
 
        }
1834
 
        Py_XDECREF(self->errobj);
1835
 
        Py_DECREF(self->ufunc);
1836
 
    }
1837
 
    _pya_free(self);
1838
 
}
1839
 
 
1840
 
static PyUFuncLoopObject *
1841
 
construct_loop(PyUFuncObject *self, PyObject *args, PyObject *kwds, PyArrayObject **mps)
1842
 
{
1843
 
    PyUFuncLoopObject *loop;
1844
 
    int i;
1845
 
    PyObject *typetup = NULL;
1846
 
    PyObject *extobj = NULL;
1847
 
    char *name;
1848
 
 
1849
 
    if (self == NULL) {
1850
 
        PyErr_SetString(PyExc_ValueError, "function not supported");
1851
 
        return NULL;
1852
 
    }
1853
 
    if ((loop = _pya_malloc(sizeof(PyUFuncLoopObject))) == NULL) {
1854
 
        PyErr_NoMemory();
1855
 
        return loop;
1856
 
    }
1857
 
 
1858
 
    loop->index = 0;
1859
 
    loop->ufunc = self;
1860
 
    Py_INCREF(self);
1861
 
    loop->buffer[0] = NULL;
1862
 
    for (i = 0; i < self->nargs; i++) {
1863
 
        loop->iters[i] = NULL;
1864
 
        loop->cast[i] = NULL;
1865
 
    }
1866
 
    loop->errobj = NULL;
1867
 
    loop->notimplemented = 0;
1868
 
    loop->first = 1;
1869
 
    loop->core_dim_sizes = NULL;
1870
 
    loop->core_strides = NULL;
1871
 
 
1872
 
    if (self->core_enabled) {
1873
 
        int num_dim_ix = 1 + self->core_num_dim_ix;
1874
 
        int nstrides = self->nargs + self->core_offsets[self->nargs - 1]
1875
 
                        + self->core_num_dims[self->nargs - 1];
1876
 
        loop->core_dim_sizes = _pya_malloc(sizeof(npy_intp)*num_dim_ix);
1877
 
        loop->core_strides = _pya_malloc(sizeof(npy_intp)*nstrides);
1878
 
        if (loop->core_dim_sizes == NULL || loop->core_strides == NULL) {
1879
 
            PyErr_NoMemory();
1880
 
            goto fail;
1881
 
        }
1882
 
        memset(loop->core_strides, 0, sizeof(npy_intp) * nstrides);
1883
 
        for (i = 0; i < num_dim_ix; i++) {
1884
 
            loop->core_dim_sizes[i] = 1;
1885
 
        }
1886
 
    }
1887
 
    name = self->name ? self->name : "";
1888
 
 
1889
 
    /*
1890
 
     * Extract sig= keyword and extobj= keyword if present.
 
803
            PyErr_SetString(PyExc_TypeError,
 
804
                            "return arrays must be "
 
805
                            "of ArrayType");
 
806
            return -1;
 
807
        }
 
808
    }
 
809
 
 
810
    /*
 
811
     * Get keyword output and other arguments.
1891
812
     * Raise an error if anything else is present in the
1892
 
     * keyword dictionary
 
813
     * keyword dictionary.
1893
814
     */
1894
815
    if (kwds != NULL) {
1895
816
        PyObject *key, *value;
1896
817
        Py_ssize_t pos = 0;
1897
818
        while (PyDict_Next(kwds, &pos, &key, &value)) {
1898
 
            char *keystring = PyString_AsString(key);
1899
 
 
1900
 
            if (keystring == NULL) {
1901
 
                PyErr_Clear();
1902
 
                PyErr_SetString(PyExc_TypeError, "invalid keyword");
1903
 
                goto fail;
1904
 
            }
1905
 
            if (strncmp(keystring,"extobj",6) == 0) {
1906
 
                extobj = value;
1907
 
            }
1908
 
            else if (strncmp(keystring,"sig",3) == 0) {
1909
 
                typetup = value;
1910
 
            }
1911
 
            else {
1912
 
                char *format = "'%s' is an invalid keyword to %s";
1913
 
                PyErr_Format(PyExc_TypeError,format,keystring, name);
1914
 
                goto fail;
1915
 
            }
1916
 
        }
1917
 
    }
1918
 
 
 
819
            Py_ssize_t length = 0;
 
820
            char *str = NULL;
 
821
            int bad_arg = 1;
 
822
 
 
823
#if defined(NPY_PY3K)
 
824
            Py_XDECREF(str_key_obj);
 
825
            str_key_obj = PyUnicode_AsASCIIString(key);
 
826
            if (str_key_obj != NULL) {
 
827
                key = str_key_obj;
 
828
            }
 
829
#endif
 
830
 
 
831
            if (PyBytes_AsStringAndSize(key, &str, &length) == -1) {
 
832
                PyErr_SetString(PyExc_TypeError, "invalid keyword argument");
 
833
                goto fail;
 
834
            }
 
835
 
 
836
            switch (str[0]) {
 
837
                case 'c':
 
838
                    /* Provides a policy for allowed casting */
 
839
                    if (strncmp(str,"casting",7) == 0) {
 
840
                        if (!PyArray_CastingConverter(value, out_casting)) {
 
841
                            goto fail;
 
842
                        }
 
843
                        bad_arg = 0;
 
844
                    }
 
845
                    break;
 
846
                case 'e':
 
847
                    /*
 
848
                     * Overrides the global parameters buffer size,
 
849
                     * error mask, and error object
 
850
                     */
 
851
                    if (strncmp(str,"extobj",6) == 0) {
 
852
                        *out_extobj = value;
 
853
                        bad_arg = 0;
 
854
                    }
 
855
                    break;
 
856
                case 'o':
 
857
                    /* First output may be specified as a keyword parameter */
 
858
                    if (strncmp(str,"out",3) == 0) {
 
859
                        if (out_op[nin] != NULL) {
 
860
                            PyErr_SetString(PyExc_ValueError,
 
861
                                    "cannot specify 'out' as both a "
 
862
                                    "positional and keyword argument");
 
863
                            goto fail;
 
864
                        }
 
865
 
 
866
                        if (PyArray_Check(value)) {
 
867
                            if (!PyArray_ISWRITEABLE(value)) {
 
868
                                PyErr_SetString(PyExc_ValueError,
 
869
                                        "return array is not writeable");
 
870
                                goto fail;
 
871
                            }
 
872
                            Py_INCREF(value);
 
873
                            out_op[nin] = (PyArrayObject *)value;
 
874
                        }
 
875
                        else {
 
876
                            PyErr_SetString(PyExc_TypeError,
 
877
                                            "return arrays must be "
 
878
                                            "of ArrayType");
 
879
                            goto fail;
 
880
                        }
 
881
                        bad_arg = 0;
 
882
                    }
 
883
                    /* Allows the default output layout to be overridden */
 
884
                    else if (strncmp(str,"order",5) == 0) {
 
885
                        if (!PyArray_OrderConverter(value, out_order)) {
 
886
                            goto fail;
 
887
                        }
 
888
                        bad_arg = 0;
 
889
                    }
 
890
                    break;
 
891
                case 's':
 
892
                    /* Allows a specific function inner loop to be selected */
 
893
                    if (strncmp(str,"sig",3) == 0) {
 
894
                        if (*out_typetup != NULL) {
 
895
                            PyErr_SetString(PyExc_RuntimeError,
 
896
                                    "cannot specify both 'sig' and 'dtype'");
 
897
                            goto fail;
 
898
                        }
 
899
                        *out_typetup = value;
 
900
                        Py_INCREF(value);
 
901
                        bad_arg = 0;
 
902
                    }
 
903
                    else if (strncmp(str,"subok",5) == 0) {
 
904
                        if (!PyBool_Check(value)) {
 
905
                            PyErr_SetString(PyExc_TypeError,
 
906
                                        "'subok' must be a boolean");
 
907
                            goto fail;
 
908
                        }
 
909
                        *out_subok = (value == Py_True);
 
910
                        bad_arg = 0;
 
911
                    }
 
912
                    break;
 
913
                case 'd':
 
914
                    /* Another way to specify 'sig' */
 
915
                    if (strncmp(str,"dtype",5) == 0) {
 
916
                        /* Allow this parameter to be None */
 
917
                        PyArray_Descr *dtype;
 
918
                        if (!PyArray_DescrConverter2(value, &dtype)) {
 
919
                            goto fail;
 
920
                        }
 
921
                        if (dtype != NULL) {
 
922
                            if (*out_typetup != NULL) {
 
923
                                PyErr_SetString(PyExc_RuntimeError,
 
924
                                    "cannot specify both 'sig' and 'dtype'");
 
925
                                goto fail;
 
926
                            }
 
927
                            *out_typetup = Py_BuildValue("(N)", dtype);
 
928
                        }
 
929
                        bad_arg = 0;
 
930
                    }
 
931
            }
 
932
 
 
933
            if (bad_arg) {
 
934
                char *format = "'%s' is an invalid keyword to ufunc '%s'";
 
935
                PyErr_Format(PyExc_TypeError, format, str, ufunc_name);
 
936
                goto fail;
 
937
            }
 
938
        }
 
939
    }
 
940
 
 
941
    *out_any_object = any_object;
 
942
 
 
943
    Py_XDECREF(str_key_obj);
 
944
    return 0;
 
945
 
 
946
fail:
 
947
    Py_XDECREF(str_key_obj);
 
948
    return -1;
 
949
}
 
950
 
 
951
static const char *
 
952
_casting_to_string(NPY_CASTING casting)
 
953
{
 
954
    switch (casting) {
 
955
        case NPY_NO_CASTING:
 
956
            return "no";
 
957
        case NPY_EQUIV_CASTING:
 
958
            return "equiv";
 
959
        case NPY_SAFE_CASTING:
 
960
            return "safe";
 
961
        case NPY_SAME_KIND_CASTING:
 
962
            return "same_kind";
 
963
        case NPY_UNSAFE_CASTING:
 
964
            return "unsafe";
 
965
        default:
 
966
            return "<unknown>";
 
967
    }
 
968
}
 
969
 
 
970
 
 
971
static int
 
972
ufunc_loop_matches(PyUFuncObject *self,
 
973
                    PyArrayObject **op,
 
974
                    NPY_CASTING input_casting,
 
975
                    NPY_CASTING output_casting,
 
976
                    int any_object,
 
977
                    int use_min_scalar,
 
978
                    int *types,
 
979
                    int *out_no_castable_output,
 
980
                    char *out_err_src_typecode,
 
981
                    char *out_err_dst_typecode)
 
982
{
 
983
    npy_intp i, nin = self->nin, nop = nin + self->nout;
 
984
 
 
985
    /*
 
986
     * First check if all the inputs can be safely cast
 
987
     * to the types for this function
 
988
     */
 
989
    for (i = 0; i < nin; ++i) {
 
990
        PyArray_Descr *tmp;
 
991
 
 
992
        /*
 
993
         * If no inputs are objects and there are more than one
 
994
         * loop, don't allow conversion to object.  The rationale
 
995
         * behind this is mostly performance.  Except for custom
 
996
         * ufuncs built with just one object-parametered inner loop,
 
997
         * only the types that are supported are implemented.  Trying
 
998
         * the object version of logical_or on float arguments doesn't
 
999
         * seem right.
 
1000
         */
 
1001
        if (types[i] == NPY_OBJECT && !any_object && self->ntypes > 1) {
 
1002
            return 0;
 
1003
        }
 
1004
 
 
1005
        tmp = PyArray_DescrFromType(types[i]);
 
1006
        if (tmp == NULL) {
 
1007
            return -1;
 
1008
        }
 
1009
 
 
1010
#if NPY_UF_DBG_TRACING
 
1011
        printf("Checking type for op %d, type %d: ", (int)i, (int)types[i]);
 
1012
        PyObject_Print((PyObject *)tmp, stdout, 0);
 
1013
        printf(", operand type: ");
 
1014
        PyObject_Print((PyObject *)PyArray_DESCR(op[i]), stdout, 0);
 
1015
        printf("\n");
 
1016
#endif
 
1017
        /*
 
1018
         * If all the inputs are scalars, use the regular
 
1019
         * promotion rules, not the special value-checking ones.
 
1020
         */
 
1021
        if (!use_min_scalar) {
 
1022
            if (!PyArray_CanCastTypeTo(PyArray_DESCR(op[i]), tmp,
 
1023
                                                    input_casting)) {
 
1024
                Py_DECREF(tmp);
 
1025
                return 0;
 
1026
            }
 
1027
        }
 
1028
        else {
 
1029
            if (!PyArray_CanCastArrayTo(op[i], tmp, input_casting)) {
 
1030
                Py_DECREF(tmp);
 
1031
                return 0;
 
1032
            }
 
1033
        }
 
1034
        Py_DECREF(tmp);
 
1035
    }
 
1036
    NPY_UF_DBG_PRINT("The inputs all worked\n");
 
1037
 
 
1038
    /*
 
1039
     * If all the inputs were ok, then check casting back to the
 
1040
     * outputs.
 
1041
     */
 
1042
    for (i = nin; i < nop; ++i) {
 
1043
        if (op[i] != NULL) {
 
1044
            PyArray_Descr *tmp = PyArray_DescrFromType(types[i]);
 
1045
            if (tmp == NULL) {
 
1046
                return -1;
 
1047
            }
 
1048
            if (!PyArray_CanCastTypeTo(tmp, PyArray_DESCR(op[i]),
 
1049
                                                        output_casting)) {
 
1050
                if (!(*out_no_castable_output)) {
 
1051
                    *out_no_castable_output = 1;
 
1052
                    *out_err_src_typecode = tmp->type;
 
1053
                    *out_err_dst_typecode = PyArray_DESCR(op[i])->type;
 
1054
                }
 
1055
                Py_DECREF(tmp);
 
1056
                return 0;
 
1057
            }
 
1058
            Py_DECREF(tmp);
 
1059
        }
 
1060
    }
 
1061
    NPY_UF_DBG_PRINT("The outputs all worked\n");
 
1062
 
 
1063
    return 1;
 
1064
}
 
1065
 
 
1066
static int
 
1067
set_ufunc_loop_data_types(PyUFuncObject *self, PyArrayObject **op,
 
1068
                    PyArray_Descr **out_dtype,
 
1069
                    int *types,
 
1070
                    npy_intp buffersize, int *out_trivial_loop_ok)
 
1071
{
 
1072
    npy_intp i, nin = self->nin, nop = nin + self->nout;
 
1073
 
 
1074
    *out_trivial_loop_ok = 1;
 
1075
    /* Fill the dtypes array */
 
1076
    for (i = 0; i < nop; ++i) {
 
1077
        out_dtype[i] = PyArray_DescrFromType(types[i]);
 
1078
        if (out_dtype[i] == NULL) {
 
1079
            return -1;
 
1080
        }
 
1081
        /*
 
1082
         * If the dtype doesn't match, or the array isn't aligned,
 
1083
         * indicate that the trivial loop can't be done.
 
1084
         */
 
1085
        if (*out_trivial_loop_ok && op[i] != NULL &&
 
1086
                (!PyArray_ISALIGNED(op[i]) ||
 
1087
                !PyArray_EquivTypes(out_dtype[i], PyArray_DESCR(op[i]))
 
1088
                                        )) {
 
1089
            /*
 
1090
             * If op[j] is a scalar or small one dimensional
 
1091
             * array input, make a copy to keep the opportunity
 
1092
             * for a trivial loop.
 
1093
             */
 
1094
            if (i < nin && (PyArray_NDIM(op[i]) == 0 ||
 
1095
                    (PyArray_NDIM(op[i]) == 1 &&
 
1096
                     PyArray_DIM(op[i],0) <= buffersize))) {
 
1097
                PyArrayObject *tmp;
 
1098
                Py_INCREF(out_dtype[i]);
 
1099
                tmp = (PyArrayObject *)
 
1100
                            PyArray_CastToType(op[i], out_dtype[i], 0);
 
1101
                if (tmp == NULL) {
 
1102
                    return -1;
 
1103
                }
 
1104
                Py_DECREF(op[i]);
 
1105
                op[i] = tmp;
 
1106
            }
 
1107
            else {
 
1108
                *out_trivial_loop_ok = 0;
 
1109
            }
 
1110
        }
 
1111
    }
 
1112
 
 
1113
    return 0;
 
1114
}
 
1115
 
 
1116
/*
 
1117
 * Does a search through the arguments and the loops
 
1118
 */
 
1119
static int
 
1120
find_ufunc_matching_userloop(PyUFuncObject *self,
 
1121
                        PyArrayObject **op,
 
1122
                        NPY_CASTING input_casting,
 
1123
                        NPY_CASTING output_casting,
 
1124
                        npy_intp buffersize,
 
1125
                        int any_object,
 
1126
                        int use_min_scalar,
 
1127
                        PyArray_Descr **out_dtype,
 
1128
                        PyUFuncGenericFunction *out_innerloop,
 
1129
                        void **out_innerloopdata,
 
1130
                        int *out_trivial_loop_ok,
 
1131
                        int *out_no_castable_output,
 
1132
                        char *out_err_src_typecode,
 
1133
                        char *out_err_dst_typecode)
 
1134
{
 
1135
    npy_intp i, nin = self->nin;
 
1136
    PyUFunc_Loop1d *funcdata;
 
1137
 
 
1138
    /* Use this to try to avoid repeating the same userdef loop search */
 
1139
    int last_userdef = -1;
 
1140
 
 
1141
    for (i = 0; i < nin; ++i) {
 
1142
        int type_num = PyArray_DESCR(op[i])->type_num;
 
1143
        if (type_num != last_userdef && PyTypeNum_ISUSERDEF(type_num)) {
 
1144
            PyObject *key, *obj;
 
1145
 
 
1146
            last_userdef = type_num;
 
1147
 
 
1148
            key = PyInt_FromLong(type_num);
 
1149
            if (key == NULL) {
 
1150
                return -1;
 
1151
            }
 
1152
            obj = PyDict_GetItem(self->userloops, key);
 
1153
            Py_DECREF(key);
 
1154
            if (obj == NULL) {
 
1155
                continue;
 
1156
            }
 
1157
            funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
 
1158
            while (funcdata != NULL) {
 
1159
                int *types = funcdata->arg_types;
 
1160
                switch (ufunc_loop_matches(self, op,
 
1161
                            input_casting, output_casting,
 
1162
                            any_object, use_min_scalar,
 
1163
                            types,
 
1164
                            out_no_castable_output, out_err_src_typecode,
 
1165
                            out_err_dst_typecode)) {
 
1166
                    /* Error */
 
1167
                    case -1:
 
1168
                        return -1;
 
1169
                    /* Found a match */
 
1170
                    case 1:
 
1171
                        set_ufunc_loop_data_types(self, op, out_dtype, types,
 
1172
                                            buffersize, out_trivial_loop_ok);
 
1173
 
 
1174
                        /* Save the inner loop and its data */
 
1175
                        *out_innerloop = funcdata->func;
 
1176
                        *out_innerloopdata = funcdata->data;
 
1177
 
 
1178
                        NPY_UF_DBG_PRINT("Returning userdef inner "
 
1179
                                                "loop successfully\n");
 
1180
 
 
1181
                        return 0;
 
1182
                }
 
1183
 
 
1184
                funcdata = funcdata->next;
 
1185
            }
 
1186
        }
 
1187
    }
 
1188
 
 
1189
    /* Didn't find a match */
 
1190
    return 0;
 
1191
}
 
1192
 
 
1193
/*
 
1194
 * Does a search through the arguments and the loops
 
1195
 */
 
1196
static int
 
1197
find_ufunc_specified_userloop(PyUFuncObject *self,
 
1198
                        int n_specified,
 
1199
                        int *specified_types,
 
1200
                        PyArrayObject **op,
 
1201
                        NPY_CASTING casting,
 
1202
                        npy_intp buffersize,
 
1203
                        int any_object,
 
1204
                        int use_min_scalar,
 
1205
                        PyArray_Descr **out_dtype,
 
1206
                        PyUFuncGenericFunction *out_innerloop,
 
1207
                        void **out_innerloopdata,
 
1208
                        int *out_trivial_loop_ok)
 
1209
{
 
1210
    npy_intp i, j, nin = self->nin, nop = nin + self->nout;
 
1211
    PyUFunc_Loop1d *funcdata;
 
1212
 
 
1213
    /* Use this to try to avoid repeating the same userdef loop search */
 
1214
    int last_userdef = -1;
 
1215
 
 
1216
    int no_castable_output = 0;
 
1217
    char err_src_typecode = '-', err_dst_typecode = '-';
 
1218
 
 
1219
    for (i = 0; i < nin; ++i) {
 
1220
        int type_num = PyArray_DESCR(op[i])->type_num;
 
1221
        if (type_num != last_userdef && PyTypeNum_ISUSERDEF(type_num)) {
 
1222
            PyObject *key, *obj;
 
1223
 
 
1224
            last_userdef = type_num;
 
1225
 
 
1226
            key = PyInt_FromLong(type_num);
 
1227
            if (key == NULL) {
 
1228
                return -1;
 
1229
            }
 
1230
            obj = PyDict_GetItem(self->userloops, key);
 
1231
            Py_DECREF(key);
 
1232
            if (obj == NULL) {
 
1233
                continue;
 
1234
            }
 
1235
            funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
 
1236
            while (funcdata != NULL) {
 
1237
                int *types = funcdata->arg_types;
 
1238
                int matched = 1;
 
1239
 
 
1240
                if (n_specified == nop) {
 
1241
                    for (j = 0; j < nop; ++j) {
 
1242
                        if (types[j] != specified_types[j]) {
 
1243
                            matched = 0;
 
1244
                            break;
 
1245
                        }
 
1246
                    }
 
1247
                } else {
 
1248
                    if (types[nin] != specified_types[0]) {
 
1249
                        matched = 0;
 
1250
                    }
 
1251
                }
 
1252
                if (!matched) {
 
1253
                    continue;
 
1254
                }
 
1255
 
 
1256
                switch (ufunc_loop_matches(self, op,
 
1257
                            casting, casting,
 
1258
                            any_object, use_min_scalar,
 
1259
                            types,
 
1260
                            &no_castable_output, &err_src_typecode,
 
1261
                            &err_dst_typecode)) {
 
1262
                    /* It works */
 
1263
                    case 1:
 
1264
                        set_ufunc_loop_data_types(self, op, out_dtype, types,
 
1265
                                            buffersize, out_trivial_loop_ok);
 
1266
 
 
1267
                        /* Save the inner loop and its data */
 
1268
                        *out_innerloop = funcdata->func;
 
1269
                        *out_innerloopdata = funcdata->data;
 
1270
 
 
1271
                        NPY_UF_DBG_PRINT("Returning userdef inner "
 
1272
                                                "loop successfully\n");
 
1273
 
 
1274
                        return 0;
 
1275
                    /* Didn't match */
 
1276
                    case 0:
 
1277
                        PyErr_Format(PyExc_TypeError,
 
1278
                             "found a user loop for ufunc '%s' "
 
1279
                             "matching the type-tuple, "
 
1280
                             "but the inputs and/or outputs could not be "
 
1281
                             "cast according to the casting rule",
 
1282
                             self->name ? self->name : "(unknown)");
 
1283
                        return -1;
 
1284
                    /* Error */
 
1285
                    case -1:
 
1286
                        return -1;
 
1287
                }
 
1288
 
 
1289
                funcdata = funcdata->next;
 
1290
            }
 
1291
        }
 
1292
    }
 
1293
 
 
1294
    /* Didn't find a match */
 
1295
    return 0;
 
1296
}
 
1297
 
 
1298
/*
 
1299
 * Provides an ordering for the dtype 'kind' character codes, to help
 
1300
 * determine when to use the min_scalar_type function. This groups
 
1301
 * 'kind' into boolean, integer, floating point, and everything else.
 
1302
 */
 
1303
 
 
1304
static int
 
1305
dtype_kind_to_simplified_ordering(char kind)
 
1306
{
 
1307
    switch (kind) {
 
1308
        /* Boolean kind */
 
1309
        case 'b':
 
1310
            return 0;
 
1311
        /* Unsigned int kind */
 
1312
        case 'u':
 
1313
        /* Signed int kind */
 
1314
        case 'i':
 
1315
            return 1;
 
1316
        /* Float kind */
 
1317
        case 'f':
 
1318
        /* Complex kind */
 
1319
        case 'c':
 
1320
            return 2;
 
1321
        /* Anything else */
 
1322
        default:
 
1323
            return 3;
 
1324
    }
 
1325
}
 
1326
 
 
1327
static int
 
1328
should_use_min_scalar(PyArrayObject **op, int nop)
 
1329
{
 
1330
    int i, use_min_scalar, kind;
 
1331
    int all_scalars = 1, max_scalar_kind = -1, max_array_kind = -1;
 
1332
 
 
1333
    /*
 
1334
     * Determine if there are any scalars, and if so, whether
 
1335
     * the maximum "kind" of the scalars surpasses the maximum
 
1336
     * "kind" of the arrays
 
1337
     */
 
1338
    use_min_scalar = 0;
 
1339
    if (nop > 1) {
 
1340
        for(i = 0; i < nop; ++i) {
 
1341
            kind = dtype_kind_to_simplified_ordering(
 
1342
                                PyArray_DESCR(op[i])->kind);
 
1343
            if (PyArray_NDIM(op[i]) == 0) {
 
1344
                if (kind > max_scalar_kind) {
 
1345
                    max_scalar_kind = kind;
 
1346
                }
 
1347
            }
 
1348
            else {
 
1349
                all_scalars = 0;
 
1350
                if (kind > max_array_kind) {
 
1351
                    max_array_kind = kind;
 
1352
                }
 
1353
 
 
1354
            }
 
1355
        }
 
1356
 
 
1357
        /* Indicate whether to use the min_scalar_type function */
 
1358
        if (!all_scalars && max_array_kind >= max_scalar_kind) {
 
1359
            use_min_scalar = 1;
 
1360
        }
 
1361
    }
 
1362
 
 
1363
    return use_min_scalar;
 
1364
}
 
1365
 
 
1366
/*
 
1367
 * Does a linear search for the best inner loop of the ufunc.
 
1368
 * When op[i] is a scalar or a one dimensional array smaller than
 
1369
 * the buffersize, and needs a dtype conversion, this function
 
1370
 * may substitute op[i] with a version cast to the correct type.  This way,
 
1371
 * the later trivial loop detection has a higher chance of being triggered.
 
1372
 *
 
1373
 * Note that if an error is returned, the caller must free the non-zero
 
1374
 * references in out_dtype.  This function does not do its own clean-up.
 
1375
 */
 
1376
static int
 
1377
find_best_ufunc_inner_loop(PyUFuncObject *self,
 
1378
                        PyArrayObject **op,
 
1379
                        NPY_CASTING input_casting,
 
1380
                        NPY_CASTING output_casting,
 
1381
                        npy_intp buffersize,
 
1382
                        int any_object,
 
1383
                        PyArray_Descr **out_dtype,
 
1384
                        PyUFuncGenericFunction *out_innerloop,
 
1385
                        void **out_innerloopdata,
 
1386
                        int *out_trivial_loop_ok)
 
1387
{
 
1388
    npy_intp i, j, nin = self->nin, nop = nin + self->nout;
 
1389
    int types[NPY_MAXARGS];
 
1390
    char *ufunc_name;
 
1391
    int no_castable_output, use_min_scalar;
 
1392
 
 
1393
    /* For making a better error message on coercion error */
 
1394
    char err_dst_typecode = '-', err_src_typecode = '-';
 
1395
 
 
1396
    ufunc_name = self->name ? self->name : "(unknown)";
 
1397
 
 
1398
    use_min_scalar = should_use_min_scalar(op, nin);
 
1399
 
 
1400
    /* If the ufunc has userloops, search for them. */
 
1401
    if (self->userloops) {
 
1402
        switch (find_ufunc_matching_userloop(self, op,
 
1403
                                input_casting, output_casting,
 
1404
                                buffersize, any_object, use_min_scalar,
 
1405
                                out_dtype, out_innerloop, out_innerloopdata,
 
1406
                                out_trivial_loop_ok,
 
1407
                                &no_castable_output, &err_src_typecode,
 
1408
                                &err_dst_typecode)) {
 
1409
            /* Error */
 
1410
            case -1:
 
1411
                return -1;
 
1412
            /* A loop was found */
 
1413
            case 1:
 
1414
                return 0;
 
1415
        }
 
1416
    }
 
1417
 
 
1418
    /*
 
1419
     * Determine the UFunc loop.  This could in general be *much* faster,
 
1420
     * and a better way to implement it might be for the ufunc to
 
1421
     * provide a function which gives back the result type and inner
 
1422
     * loop function.
 
1423
     *
 
1424
     * A default fast mechanism could be provided for functions which
 
1425
     * follow the most typical pattern, when all functions have signatures
 
1426
     * "xx...x -> x" for some built-in data type x, as follows.
 
1427
     *  - Use PyArray_ResultType to get the output type
 
1428
     *  - Look up the inner loop in a table based on the output type_num
 
1429
     *
 
1430
     * The method for finding the loop in the previous code did not
 
1431
     * appear consistent (as noted by some asymmetry in the generated
 
1432
     * coercion tables for np.add).
 
1433
     */
 
1434
    no_castable_output = 0;
 
1435
    for (i = 0; i < self->ntypes; ++i) {
 
1436
        char *orig_types = self->types + i*self->nargs;
 
1437
 
 
1438
        /* Copy the types into an int array for matching */
 
1439
        for (j = 0; j < nop; ++j) {
 
1440
            types[j] = orig_types[j];
 
1441
        }
 
1442
 
 
1443
        NPY_UF_DBG_PRINT1("Trying function loop %d\n", (int)i);
 
1444
        switch (ufunc_loop_matches(self, op,
 
1445
                    input_casting, output_casting,
 
1446
                    any_object, use_min_scalar,
 
1447
                    types,
 
1448
                    &no_castable_output, &err_src_typecode,
 
1449
                    &err_dst_typecode)) {
 
1450
            /* Error */
 
1451
            case -1:
 
1452
                return -1;
 
1453
            /* Found a match */
 
1454
            case 1:
 
1455
                set_ufunc_loop_data_types(self, op, out_dtype, types,
 
1456
                                    buffersize, out_trivial_loop_ok);
 
1457
 
 
1458
                /* Save the inner loop and its data */
 
1459
                *out_innerloop = self->functions[i];
 
1460
                *out_innerloopdata = self->data[i];
 
1461
 
 
1462
                NPY_UF_DBG_PRINT("Returning inner loop successfully\n");
 
1463
 
 
1464
                return 0;
 
1465
        }
 
1466
 
 
1467
    }
 
1468
 
 
1469
    /* If no function was found, throw an error */
 
1470
    NPY_UF_DBG_PRINT("No loop was found\n");
 
1471
    if (no_castable_output) {
 
1472
        PyErr_Format(PyExc_TypeError,
 
1473
                "ufunc '%s' output (typecode '%c') could not be coerced to "
 
1474
                "provided output parameter (typecode '%c') according "
 
1475
                "to the casting rule '%s'",
 
1476
                ufunc_name, err_src_typecode, err_dst_typecode,
 
1477
                _casting_to_string(output_casting));
 
1478
    }
 
1479
    else {
 
1480
        /*
 
1481
         * TODO: We should try again if the casting rule is same_kind
 
1482
         *       or unsafe, and look for a function more liberally.
 
1483
         */
 
1484
        PyErr_Format(PyExc_TypeError,
 
1485
                "ufunc '%s' not supported for the input types, and the "
 
1486
                "inputs could not be safely coerced to any supported "
 
1487
                "types according to the casting rule '%s'",
 
1488
                ufunc_name,
 
1489
                _casting_to_string(input_casting));
 
1490
    }
 
1491
 
 
1492
    return -1;
 
1493
}
 
1494
 
 
1495
/*
 
1496
 * Does a linear search for the inner loop of the ufunc specified by type_tup.
 
1497
 * When op[i] is a scalar or a one dimensional array smaller than
 
1498
 * the buffersize, and needs a dtype conversion, this function
 
1499
 * may substitute op[i] with a version cast to the correct type.  This way,
 
1500
 * the later trivial loop detection has a higher chance of being triggered.
 
1501
 *
 
1502
 * Note that if an error is returned, the caller must free the non-zero
 
1503
 * references in out_dtype.  This function does not do its own clean-up.
 
1504
 */
 
1505
static int
 
1506
find_specified_ufunc_inner_loop(PyUFuncObject *self,
 
1507
                        PyObject *type_tup,
 
1508
                        PyArrayObject **op,
 
1509
                        NPY_CASTING casting,
 
1510
                        npy_intp buffersize,
 
1511
                        int any_object,
 
1512
                        PyArray_Descr **out_dtype,
 
1513
                        PyUFuncGenericFunction *out_innerloop,
 
1514
                        void **out_innerloopdata,
 
1515
                        int *out_trivial_loop_ok)
 
1516
{
 
1517
    npy_intp i, j, n, nin = self->nin, nop = nin + self->nout;
 
1518
    int n_specified = 0;
 
1519
    int specified_types[NPY_MAXARGS], types[NPY_MAXARGS];
 
1520
    char *ufunc_name;
 
1521
    int no_castable_output, use_min_scalar;
 
1522
 
 
1523
    /* For making a better error message on coercion error */
 
1524
    char err_dst_typecode = '-', err_src_typecode = '-';
 
1525
 
 
1526
    ufunc_name = self->name ? self->name : "(unknown)";
 
1527
 
 
1528
    use_min_scalar = should_use_min_scalar(op, nin);
 
1529
 
 
1530
    /* Fill in specified_types from the tuple or string */
 
1531
    if (PyTuple_Check(type_tup)) {
 
1532
        n = PyTuple_GET_SIZE(type_tup);
 
1533
        if (n != 1 && n != nop) {
 
1534
            PyErr_Format(PyExc_ValueError,
 
1535
                         "a type-tuple must be specified " \
 
1536
                         "of length 1 or %d for ufunc '%s'", (int)nop,
 
1537
                         self->name ? self->name : "(unknown)");
 
1538
            return -1;
 
1539
        }
 
1540
 
 
1541
        for (i = 0; i < n; ++i) {
 
1542
            PyArray_Descr *dtype = NULL;
 
1543
            if (!PyArray_DescrConverter(PyTuple_GET_ITEM(type_tup, i),
 
1544
                                                                &dtype)) {
 
1545
                return -1;
 
1546
            }
 
1547
            specified_types[i] = dtype->type_num;
 
1548
            Py_DECREF(dtype);
 
1549
        }
 
1550
 
 
1551
        n_specified = n;
 
1552
    }
 
1553
    else if (PyBytes_Check(type_tup) || PyUnicode_Check(type_tup)) {
 
1554
        Py_ssize_t length;
 
1555
        char *str;
 
1556
        PyObject *str_obj = NULL;
 
1557
 
 
1558
        if (PyUnicode_Check(type_tup)) {
 
1559
            str_obj = PyUnicode_AsASCIIString(type_tup);
 
1560
            if (str_obj == NULL) {
 
1561
                return -1;
 
1562
            }
 
1563
            type_tup = str_obj;
 
1564
        }
 
1565
 
 
1566
        if (!PyBytes_AsStringAndSize(type_tup, &str, &length) < 0) {
 
1567
            Py_XDECREF(str_obj);
 
1568
            return -1;
 
1569
        }
 
1570
        if (length != 1 && (length != nop + 2 ||
 
1571
                                str[nin] != '-' || str[nin+1] != '>')) {
 
1572
            PyErr_Format(PyExc_ValueError,
 
1573
                                 "a type-string for %s, "   \
 
1574
                                 "requires 1 typecode, or "
 
1575
                                 "%d typecode(s) before " \
 
1576
                                 "and %d after the -> sign",
 
1577
                                 self->name ? self->name : "(unknown)",
 
1578
                                 self->nin, self->nout);
 
1579
            Py_XDECREF(str_obj);
 
1580
            return -1;
 
1581
        }
 
1582
        if (length == 1) {
 
1583
            PyArray_Descr *dtype;
 
1584
            n_specified = 1;
 
1585
            dtype = PyArray_DescrFromType(str[0]);
 
1586
            if (dtype == NULL) {
 
1587
                Py_XDECREF(str_obj);
 
1588
                return -1;
 
1589
            }
 
1590
            NPY_UF_DBG_PRINT2("signature character '%c', type num %d\n",
 
1591
                                str[0], dtype->type_num);
 
1592
            specified_types[0] = dtype->type_num;
 
1593
            Py_DECREF(dtype);
 
1594
        }
 
1595
        else {
 
1596
            PyArray_Descr *dtype;
 
1597
            n_specified = (int)nop;
 
1598
 
 
1599
            for (i = 0; i < nop; ++i) {
 
1600
                npy_intp istr = i < nin ? i : i+2;
 
1601
 
 
1602
                dtype = PyArray_DescrFromType(str[istr]);
 
1603
                if (dtype == NULL) {
 
1604
                    Py_XDECREF(str_obj);
 
1605
                    return -1;
 
1606
                }
 
1607
                NPY_UF_DBG_PRINT2("signature character '%c', type num %d\n",
 
1608
                                    str[istr], dtype->type_num);
 
1609
                specified_types[i] = dtype->type_num;
 
1610
                Py_DECREF(dtype);
 
1611
            }
 
1612
        }
 
1613
        Py_XDECREF(str_obj);
 
1614
    }
 
1615
 
 
1616
    /* If the ufunc has userloops, search for them. */
 
1617
    if (self->userloops) {
 
1618
        NPY_UF_DBG_PRINT("Searching user loops for specified sig\n");
 
1619
        switch (find_ufunc_specified_userloop(self,
 
1620
                        n_specified, specified_types,
 
1621
                        op, casting,
 
1622
                        buffersize, any_object, use_min_scalar,
 
1623
                        out_dtype, out_innerloop, out_innerloopdata,
 
1624
                        out_trivial_loop_ok)) {
 
1625
            /* Error */
 
1626
            case -1:
 
1627
                return -1;
 
1628
            /* Found matching loop */
 
1629
            case 1:
 
1630
                return 0;
 
1631
        }
 
1632
    }
 
1633
 
 
1634
    NPY_UF_DBG_PRINT("Searching loops for specified sig\n");
 
1635
    for (i = 0; i < self->ntypes; ++i) {
 
1636
        char *orig_types = self->types + i*self->nargs;
 
1637
        int matched = 1;
 
1638
 
 
1639
        NPY_UF_DBG_PRINT1("Trying function loop %d\n", (int)i);
 
1640
 
 
1641
        /* Copy the types into an int array for matching */
 
1642
        for (j = 0; j < nop; ++j) {
 
1643
            types[j] = orig_types[j];
 
1644
        }
 
1645
 
 
1646
        if (n_specified == nop) {
 
1647
            for (j = 0; j < nop; ++j) {
 
1648
                if (types[j] != specified_types[j]) {
 
1649
                    matched = 0;
 
1650
                    break;
 
1651
                }
 
1652
            }
 
1653
        } else {
 
1654
            NPY_UF_DBG_PRINT2("Specified type: %d, first output type: %d\n",
 
1655
                                        specified_types[0], types[nin]);
 
1656
            if (types[nin] != specified_types[0]) {
 
1657
                matched = 0;
 
1658
            }
 
1659
        }
 
1660
        if (!matched) {
 
1661
            continue;
 
1662
        }
 
1663
 
 
1664
        NPY_UF_DBG_PRINT("It matches, confirming type casting\n");
 
1665
        switch (ufunc_loop_matches(self, op,
 
1666
                    casting, casting,
 
1667
                    any_object, use_min_scalar,
 
1668
                    types,
 
1669
                    &no_castable_output, &err_src_typecode,
 
1670
                    &err_dst_typecode)) {
 
1671
            /* Error */
 
1672
            case -1:
 
1673
                return -1;
 
1674
            /* It worked */
 
1675
            case 1:
 
1676
                set_ufunc_loop_data_types(self, op, out_dtype, types,
 
1677
                                    buffersize, out_trivial_loop_ok);
 
1678
 
 
1679
                /* Save the inner loop and its data */
 
1680
                *out_innerloop = self->functions[i];
 
1681
                *out_innerloopdata = self->data[i];
 
1682
 
 
1683
                NPY_UF_DBG_PRINT("Returning specified inner loop successfully\n");
 
1684
 
 
1685
                return 0;
 
1686
            /* Didn't work */
 
1687
            case 0:
 
1688
                PyErr_Format(PyExc_TypeError,
 
1689
                     "found a loop for ufunc '%s' "
 
1690
                     "matching the type-tuple, "
 
1691
                     "but the inputs and/or outputs could not be "
 
1692
                     "cast according to the casting rule",
 
1693
                     ufunc_name);
 
1694
                return -1;
 
1695
        }
 
1696
 
 
1697
    }
 
1698
 
 
1699
    /* If no function was found, throw an error */
 
1700
    NPY_UF_DBG_PRINT("No specified loop was found\n");
 
1701
 
 
1702
    PyErr_Format(PyExc_TypeError,
 
1703
            "No loop matching the specified signature was found "
 
1704
            "for ufunc %s", ufunc_name);
 
1705
 
 
1706
    return -1;
 
1707
}
 
1708
 
 
1709
static void
 
1710
trivial_two_operand_loop(PyArrayObject **op,
 
1711
                    PyUFuncGenericFunction innerloop,
 
1712
                    void *innerloopdata)
 
1713
{
 
1714
    char *data[2];
 
1715
    npy_intp count[2], stride[2];
 
1716
    int needs_api;
 
1717
    NPY_BEGIN_THREADS_DEF;
 
1718
 
 
1719
    needs_api = PyDataType_REFCHK(PyArray_DESCR(op[0])) ||
 
1720
                PyDataType_REFCHK(PyArray_DESCR(op[1]));
 
1721
 
 
1722
    PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(op[0], op[1],
 
1723
                                            count[0],
 
1724
                                            data[0], data[1],
 
1725
                                            stride[0], stride[1]);
 
1726
    count[1] = count[0];
 
1727
    NPY_UF_DBG_PRINT1("two operand loop count %d\n", (int)count[0]);
 
1728
 
 
1729
    if (!needs_api) {
 
1730
        NPY_BEGIN_THREADS;
 
1731
    }
 
1732
 
 
1733
    innerloop(data, count, stride, innerloopdata);
 
1734
 
 
1735
    if (!needs_api) {
 
1736
        NPY_END_THREADS;
 
1737
    }
 
1738
}
 
1739
 
 
1740
static void
 
1741
trivial_three_operand_loop(PyArrayObject **op,
 
1742
                    PyUFuncGenericFunction innerloop,
 
1743
                    void *innerloopdata)
 
1744
{
 
1745
    char *data[3];
 
1746
    npy_intp count[3], stride[3];
 
1747
    int needs_api;
 
1748
    NPY_BEGIN_THREADS_DEF;
 
1749
 
 
1750
    needs_api = PyDataType_REFCHK(PyArray_DESCR(op[0])) ||
 
1751
                PyDataType_REFCHK(PyArray_DESCR(op[1])) ||
 
1752
                PyDataType_REFCHK(PyArray_DESCR(op[2]));
 
1753
 
 
1754
    PyArray_PREPARE_TRIVIAL_TRIPLE_ITERATION(op[0], op[1], op[2],
 
1755
                                            count[0],
 
1756
                                            data[0], data[1], data[2],
 
1757
                                            stride[0], stride[1], stride[2]);
 
1758
    count[1] = count[0];
 
1759
    count[2] = count[0];
 
1760
    NPY_UF_DBG_PRINT1("three operand loop count %d\n", (int)count[0]);
 
1761
 
 
1762
    if (!needs_api) {
 
1763
        NPY_BEGIN_THREADS;
 
1764
    }
 
1765
 
 
1766
    innerloop(data, count, stride, innerloopdata);
 
1767
 
 
1768
    if (!needs_api) {
 
1769
        NPY_END_THREADS;
 
1770
    }
 
1771
}
 
1772
 
 
1773
/*
 
1774
 * Calls the given __array_prepare__ function on the operand *op,
 
1775
 * substituting it in place if a new array is returned and matches
 
1776
 * the old one.
 
1777
 *
 
1778
 * This requires that the dimensions, strides and data type remain
 
1779
 * exactly the same, which may be more strict than before.
 
1780
 */
 
1781
static int
 
1782
prepare_ufunc_output(PyUFuncObject *self,
 
1783
                    PyArrayObject **op,
 
1784
                    PyObject *arr_prep,
 
1785
                    PyObject *arr_prep_args,
 
1786
                    int i)
 
1787
{
 
1788
    if (arr_prep != NULL && arr_prep != Py_None) {
 
1789
        PyObject *res;
 
1790
 
 
1791
        res = PyObject_CallFunction(arr_prep, "O(OOi)",
 
1792
                    *op, self, arr_prep_args, i);
 
1793
        if ((res == NULL) || (res == Py_None) || !PyArray_Check(res)) {
 
1794
            if (!PyErr_Occurred()){
 
1795
                PyErr_SetString(PyExc_TypeError,
 
1796
                        "__array_prepare__ must return an "
 
1797
                        "ndarray or subclass thereof");
 
1798
            }
 
1799
            Py_XDECREF(res);
 
1800
            return -1;
 
1801
        }
 
1802
 
 
1803
        /* If the same object was returned, nothing to do */
 
1804
        if (res == (PyObject *)*op) {
 
1805
            Py_DECREF(res);
 
1806
        }
 
1807
        /* If the result doesn't match, throw an error */
 
1808
        else if (PyArray_NDIM(res) != PyArray_NDIM(*op) ||
 
1809
                !PyArray_CompareLists(PyArray_DIMS(res),
 
1810
                                      PyArray_DIMS(*op),
 
1811
                                      PyArray_NDIM(res)) ||
 
1812
                !PyArray_CompareLists(PyArray_STRIDES(res),
 
1813
                                      PyArray_STRIDES(*op),
 
1814
                                      PyArray_NDIM(res)) ||
 
1815
                !PyArray_EquivTypes(PyArray_DESCR(res),
 
1816
                                    PyArray_DESCR(*op))) {
 
1817
            PyErr_SetString(PyExc_TypeError,
 
1818
                    "__array_prepare__ must return an "
 
1819
                    "ndarray or subclass thereof which is "
 
1820
                    "otherwise identical to its input");
 
1821
            Py_DECREF(res);
 
1822
            return -1;
 
1823
        }
 
1824
        /* Replace the op value */
 
1825
        else {
 
1826
            Py_DECREF(*op);
 
1827
            *op = (PyArrayObject *)res;
 
1828
        }
 
1829
    }
 
1830
 
 
1831
    return 0;
 
1832
}
 
1833
 
 
1834
static int
 
1835
iterator_loop(PyUFuncObject *self,
 
1836
                    PyArrayObject **op,
 
1837
                    PyArray_Descr **dtype,
 
1838
                    NPY_ORDER order,
 
1839
                    npy_intp buffersize,
 
1840
                    PyObject **arr_prep,
 
1841
                    PyObject *arr_prep_args,
 
1842
                    PyUFuncGenericFunction innerloop,
 
1843
                    void *innerloopdata)
 
1844
{
 
1845
    npy_intp i, nin = self->nin, nout = self->nout;
 
1846
    npy_intp nop = nin + nout;
 
1847
    npy_uint32 op_flags[NPY_MAXARGS];
 
1848
    NpyIter *iter;
 
1849
    char *baseptrs[NPY_MAXARGS];
 
1850
    int needs_api;
 
1851
 
 
1852
    NpyIter_IterNextFunc *iternext;
 
1853
    char **dataptr;
 
1854
    npy_intp *stride;
 
1855
    npy_intp *count_ptr;
 
1856
 
 
1857
    PyArrayObject **op_it;
 
1858
 
 
1859
    NPY_BEGIN_THREADS_DEF;
 
1860
 
 
1861
    /* Set up the flags */
 
1862
    for (i = 0; i < nin; ++i) {
 
1863
        op_flags[i] = NPY_ITER_READONLY|
 
1864
                      NPY_ITER_ALIGNED;
 
1865
    }
 
1866
    for (i = nin; i < nop; ++i) {
 
1867
        op_flags[i] = NPY_ITER_WRITEONLY|
 
1868
                      NPY_ITER_ALIGNED|
 
1869
                      NPY_ITER_ALLOCATE|
 
1870
                      NPY_ITER_NO_BROADCAST|
 
1871
                      NPY_ITER_NO_SUBTYPE;
 
1872
    }
 
1873
 
 
1874
    /*
 
1875
     * Allocate the iterator.  Because the types of the inputs
 
1876
     * were already checked, we use the casting rule 'unsafe' which
 
1877
     * is faster to calculate.
 
1878
     */
 
1879
    iter = NpyIter_AdvancedNew(nop, op,
 
1880
                        NPY_ITER_EXTERNAL_LOOP|
 
1881
                        NPY_ITER_REFS_OK|
 
1882
                        NPY_ITER_ZEROSIZE_OK|
 
1883
                        NPY_ITER_BUFFERED|
 
1884
                        NPY_ITER_GROWINNER|
 
1885
                        NPY_ITER_DELAY_BUFALLOC,
 
1886
                        order, NPY_UNSAFE_CASTING,
 
1887
                        op_flags, dtype,
 
1888
                        0, NULL, NULL, buffersize);
 
1889
    if (iter == NULL) {
 
1890
        return -1;
 
1891
    }
 
1892
 
 
1893
    needs_api = NpyIter_IterationNeedsAPI(iter);
 
1894
 
 
1895
    /* Copy any allocated outputs */
 
1896
    op_it = NpyIter_GetOperandArray(iter);
 
1897
    for (i = nin; i < nop; ++i) {
 
1898
        if (op[i] == NULL) {
 
1899
            op[i] = op_it[i];
 
1900
            Py_INCREF(op[i]);
 
1901
        }
 
1902
    }
 
1903
 
 
1904
    /* Call the __array_prepare__ functions where necessary */
 
1905
    for (i = 0; i < nout; ++i) {
 
1906
        if (prepare_ufunc_output(self, &op[nin+i],
 
1907
                            arr_prep[i], arr_prep_args, i) < 0) {
 
1908
            NpyIter_Deallocate(iter);
 
1909
            return -1;
 
1910
        }
 
1911
    }
 
1912
 
 
1913
    /* Only do the loop if the iteration size is non-zero */
 
1914
    if (NpyIter_GetIterSize(iter) != 0) {
 
1915
 
 
1916
        /* Reset the iterator with the base pointers from the wrapped outputs */
 
1917
        for (i = 0; i < nin; ++i) {
 
1918
            baseptrs[i] = PyArray_BYTES(op_it[i]);
 
1919
        }
 
1920
        for (i = nin; i < nop; ++i) {
 
1921
            baseptrs[i] = PyArray_BYTES(op[i]);
 
1922
        }
 
1923
        if (NpyIter_ResetBasePointers(iter, baseptrs, NULL) != NPY_SUCCEED) {
 
1924
            NpyIter_Deallocate(iter);
 
1925
            return -1;
 
1926
        }
 
1927
 
 
1928
        /* Get the variables needed for the loop */
 
1929
        iternext = NpyIter_GetIterNext(iter, NULL);
 
1930
        if (iternext == NULL) {
 
1931
            NpyIter_Deallocate(iter);
 
1932
            return -1;
 
1933
        }
 
1934
        dataptr = NpyIter_GetDataPtrArray(iter);
 
1935
        stride = NpyIter_GetInnerStrideArray(iter);
 
1936
        count_ptr = NpyIter_GetInnerLoopSizePtr(iter);
 
1937
 
 
1938
        if (!needs_api) {
 
1939
            NPY_BEGIN_THREADS;
 
1940
        }
 
1941
 
 
1942
        /* Execute the loop */
 
1943
        do {
 
1944
            NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)*count_ptr);
 
1945
            innerloop(dataptr, count_ptr, stride, innerloopdata);
 
1946
        } while (iternext(iter));
 
1947
 
 
1948
        if (!needs_api) {
 
1949
            NPY_END_THREADS;
 
1950
        }
 
1951
    }
 
1952
 
 
1953
    NpyIter_Deallocate(iter);
 
1954
    return 0;
 
1955
}
 
1956
 
 
1957
/*
 
1958
 * trivial_loop_ok - 1 if no alignment, data conversion, etc required
 
1959
 * nin             - number of inputs
 
1960
 * nout            - number of outputs
 
1961
 * op              - the operands (nin + nout of them)
 
1962
 * order           - the loop execution order/output memory order
 
1963
 * buffersize      - how big of a buffer to use
 
1964
 * arr_prep        - the __array_prepare__ functions for the outputs
 
1965
 * innerloop       - the inner loop function
 
1966
 * innerloopdata   - data to pass to the inner loop
 
1967
 */
 
1968
static int
 
1969
execute_ufunc_loop(PyUFuncObject *self,
 
1970
                    int trivial_loop_ok,
 
1971
                    PyArrayObject **op,
 
1972
                    PyArray_Descr **dtype,
 
1973
                    NPY_ORDER order,
 
1974
                    npy_intp buffersize,
 
1975
                    PyObject **arr_prep,
 
1976
                    PyObject *arr_prep_args,
 
1977
                    PyUFuncGenericFunction innerloop,
 
1978
                    void *innerloopdata)
 
1979
{
 
1980
    npy_intp nin = self->nin, nout = self->nout;
 
1981
 
 
1982
    /* First check for the trivial cases that don't need an iterator */
 
1983
    if (trivial_loop_ok) {
 
1984
        if (nin == 1 && nout == 1) {
 
1985
            if (op[1] == NULL &&
 
1986
                        (order == NPY_ANYORDER || order == NPY_KEEPORDER) &&
 
1987
                        PyArray_TRIVIALLY_ITERABLE(op[0])) {
 
1988
                Py_INCREF(dtype[1]);
 
1989
                op[1] = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
 
1990
                             dtype[1],
 
1991
                             PyArray_NDIM(op[0]),
 
1992
                             PyArray_DIMS(op[0]),
 
1993
                             NULL, NULL,
 
1994
                             PyArray_ISFORTRAN(op[0]) ? NPY_F_CONTIGUOUS : 0,
 
1995
                             NULL);
 
1996
 
 
1997
                /* Call the __prepare_array__ if necessary */
 
1998
                if (prepare_ufunc_output(self, &op[1],
 
1999
                                    arr_prep[0], arr_prep_args, 0) < 0) {
 
2000
                    return -1;
 
2001
                }
 
2002
 
 
2003
                NPY_UF_DBG_PRINT("trivial 1 input with allocated output\n");
 
2004
                trivial_two_operand_loop(op, innerloop, innerloopdata);
 
2005
 
 
2006
                return 0;
 
2007
            }
 
2008
            else if (op[1] != NULL &&
 
2009
                        PyArray_NDIM(op[1]) >= PyArray_NDIM(op[0]) &&
 
2010
                        PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1])) {
 
2011
 
 
2012
                /* Call the __prepare_array__ if necessary */
 
2013
                if (prepare_ufunc_output(self, &op[1],
 
2014
                                    arr_prep[0], arr_prep_args, 0) < 0) {
 
2015
                    return -1;
 
2016
                }
 
2017
 
 
2018
                NPY_UF_DBG_PRINT("trivial 1 input\n");
 
2019
                trivial_two_operand_loop(op, innerloop, innerloopdata);
 
2020
 
 
2021
                return 0;
 
2022
            }
 
2023
        }
 
2024
        else if (nin == 2 && nout == 1) {
 
2025
            if (op[2] == NULL &&
 
2026
                        (order == NPY_ANYORDER || order == NPY_KEEPORDER) &&
 
2027
                        PyArray_TRIVIALLY_ITERABLE_PAIR(op[0], op[1])) {
 
2028
                PyArrayObject *tmp;
 
2029
                /*
 
2030
                 * Have to choose the input with more dimensions to clone, as
 
2031
                 * one of them could be a scalar.
 
2032
                 */
 
2033
                if (PyArray_NDIM(op[0]) >= PyArray_NDIM(op[1])) {
 
2034
                    tmp = op[0];
 
2035
                }
 
2036
                else {
 
2037
                    tmp = op[1];
 
2038
                }
 
2039
                Py_INCREF(dtype[2]);
 
2040
                op[2] = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
 
2041
                                 dtype[2],
 
2042
                                 PyArray_NDIM(tmp),
 
2043
                                 PyArray_DIMS(tmp),
 
2044
                                 NULL, NULL,
 
2045
                                 PyArray_ISFORTRAN(tmp) ? NPY_F_CONTIGUOUS : 0,
 
2046
                                 NULL);
 
2047
 
 
2048
                /* Call the __prepare_array__ if necessary */
 
2049
                if (prepare_ufunc_output(self, &op[2],
 
2050
                                    arr_prep[0], arr_prep_args, 0) < 0) {
 
2051
                    return -1;
 
2052
                }
 
2053
 
 
2054
                NPY_UF_DBG_PRINT("trivial 2 input with allocated output\n");
 
2055
                trivial_three_operand_loop(op, innerloop, innerloopdata);
 
2056
 
 
2057
                return 0;
 
2058
            }
 
2059
            else if (op[2] != NULL &&
 
2060
                    PyArray_NDIM(op[2]) >= PyArray_NDIM(op[0]) &&
 
2061
                    PyArray_NDIM(op[2]) >= PyArray_NDIM(op[1]) &&
 
2062
                    PyArray_TRIVIALLY_ITERABLE_TRIPLE(op[0], op[1], op[2])) {
 
2063
 
 
2064
                /* Call the __prepare_array__ if necessary */
 
2065
                if (prepare_ufunc_output(self, &op[2],
 
2066
                                    arr_prep[0], arr_prep_args, 0) < 0) {
 
2067
                    return -1;
 
2068
                }
 
2069
 
 
2070
                NPY_UF_DBG_PRINT("trivial 2 input\n");
 
2071
                trivial_three_operand_loop(op, innerloop, innerloopdata);
 
2072
 
 
2073
                return 0;
 
2074
            }
 
2075
        }
 
2076
    }
 
2077
 
 
2078
    /*
 
2079
     * If no trivial loop matched, an iterator is required to
 
2080
     * resolve broadcasting, etc
 
2081
     */
 
2082
 
 
2083
    NPY_UF_DBG_PRINT("iterator loop\n");
 
2084
    if (iterator_loop(self, op, dtype, order,
 
2085
                    buffersize, arr_prep, arr_prep_args,
 
2086
                    innerloop, innerloopdata) < 0) {
 
2087
        return -1;
 
2088
    }
 
2089
 
 
2090
    return 0;
 
2091
}
 
2092
 
 
2093
static PyObject *
 
2094
make_arr_prep_args(npy_intp nin, PyObject *args, PyObject *kwds)
 
2095
{
 
2096
    PyObject *out = kwds ? PyDict_GetItemString(kwds, "out") : NULL;
 
2097
    PyObject *arr_prep_args;
 
2098
 
 
2099
    if (out == NULL) {
 
2100
        Py_INCREF(args);
 
2101
        return args;
 
2102
    }
 
2103
    else {
 
2104
        npy_intp i, nargs = PyTuple_GET_SIZE(args), n;
 
2105
        n = nargs;
 
2106
        if (n < nin + 1) {
 
2107
            n = nin + 1;
 
2108
        }
 
2109
        arr_prep_args = PyTuple_New(n);
 
2110
        if (arr_prep_args == NULL) {
 
2111
            return NULL;
 
2112
        }
 
2113
        /* Copy the tuple, but set the nin-th item to the keyword arg */
 
2114
        for (i = 0; i < nin; ++i) {
 
2115
            PyObject *item = PyTuple_GET_ITEM(args, i);
 
2116
            Py_INCREF(item);
 
2117
            PyTuple_SET_ITEM(arr_prep_args, i, item);
 
2118
        }
 
2119
        Py_INCREF(out);
 
2120
        PyTuple_SET_ITEM(arr_prep_args, nin, out);
 
2121
        for (i = nin+1; i < n; ++i) {
 
2122
            PyObject *item = PyTuple_GET_ITEM(args, i);
 
2123
            Py_INCREF(item);
 
2124
            PyTuple_SET_ITEM(arr_prep_args, i, item);
 
2125
        }
 
2126
 
 
2127
        return arr_prep_args;
 
2128
    }
 
2129
}
 
2130
 
 
2131
static int
 
2132
PyUFunc_GeneralizedFunction(PyUFuncObject *self,
 
2133
                        PyObject *args, PyObject *kwds,
 
2134
                        PyArrayObject **op)
 
2135
{
 
2136
    int nin, nout;
 
2137
    int i, idim, nop;
 
2138
    char *ufunc_name;
 
2139
    int retval = -1, any_object = 0, subok = 1;
 
2140
    NPY_CASTING input_casting;
 
2141
 
 
2142
    PyArray_Descr *dtype[NPY_MAXARGS];
 
2143
 
 
2144
    /* Use remapped axes for generalized ufunc */
 
2145
    int broadcast_ndim, op_ndim;
 
2146
    int op_axes_arrays[NPY_MAXARGS][NPY_MAXDIMS];
 
2147
    int *op_axes[NPY_MAXARGS];
 
2148
 
 
2149
    npy_uint32 op_flags[NPY_MAXARGS];
 
2150
 
 
2151
    NpyIter *iter = NULL;
 
2152
 
 
2153
    /* These parameters come from extobj= or from a TLS global */
 
2154
    int buffersize = 0, errormask = 0;
 
2155
    PyObject *errobj = NULL;
 
2156
    int first_error = 1;
 
2157
 
 
2158
    /* The selected inner loop */
 
2159
    PyUFuncGenericFunction innerloop = NULL;
 
2160
    void *innerloopdata = NULL;
 
2161
    /* The dimensions which get passed to the inner loop */
 
2162
    npy_intp inner_dimensions[NPY_MAXDIMS+1];
 
2163
    /* The strides which get passed to the inner loop */
 
2164
    npy_intp *inner_strides = NULL;
 
2165
 
 
2166
    npy_intp *inner_strides_tmp, *ax_strides_tmp[NPY_MAXDIMS];
 
2167
    int core_dim_ixs_size, *core_dim_ixs;
 
2168
 
 
2169
    /* The __array_prepare__ function to call for each output */
 
2170
    PyObject *arr_prep[NPY_MAXARGS];
 
2171
    /*
 
2172
     * This is either args, or args with the out= parameter from
 
2173
     * kwds added appropriately.
 
2174
     */
 
2175
    PyObject *arr_prep_args = NULL;
 
2176
 
 
2177
    int trivial_loop_ok = 0;
 
2178
 
 
2179
    NPY_ORDER order = NPY_KEEPORDER;
 
2180
    /*
 
2181
     * Many things in NumPy do unsafe casting (doing int += float, etc).
 
2182
     * The strictness should probably become a state parameter, similar
 
2183
     * to the seterr/geterr.
 
2184
     */
 
2185
    NPY_CASTING casting = NPY_UNSAFE_CASTING;
 
2186
    /* When provided, extobj and typetup contain borrowed references */
 
2187
    PyObject *extobj = NULL, *type_tup = NULL;
 
2188
 
 
2189
    if (self == NULL) {
 
2190
        PyErr_SetString(PyExc_ValueError, "function not supported");
 
2191
        return -1;
 
2192
    }
 
2193
 
 
2194
    nin = self->nin;
 
2195
    nout = self->nout;
 
2196
    nop = nin + nout;
 
2197
 
 
2198
    ufunc_name = self->name ? self->name : "<unnamed ufunc>";
 
2199
 
 
2200
    NPY_UF_DBG_PRINT1("\nEvaluating ufunc %s\n", ufunc_name);
 
2201
 
 
2202
    /* Initialize all the operands and dtypes to NULL */
 
2203
    for (i = 0; i < nop; ++i) {
 
2204
        op[i] = NULL;
 
2205
        dtype[i] = NULL;
 
2206
        arr_prep[i] = NULL;
 
2207
    }
 
2208
 
 
2209
    NPY_UF_DBG_PRINT("Getting arguments\n");
 
2210
 
 
2211
    /* Get all the arguments */
 
2212
    retval = get_ufunc_arguments(self, args, kwds,
 
2213
                op, &order, &casting, &extobj, &type_tup, &subok, &any_object);
 
2214
    if (retval < 0) {
 
2215
        goto fail;
 
2216
    }
 
2217
 
 
2218
    /* Figure out the number of dimensions needed by the iterator */
 
2219
    broadcast_ndim = 0;
 
2220
    for (i = 0; i < nin; ++i) {
 
2221
        int n = PyArray_NDIM(op[i]) - self->core_num_dims[i];
 
2222
        if (n > broadcast_ndim) {
 
2223
            broadcast_ndim = n;
 
2224
        }
 
2225
    }
 
2226
    op_ndim = broadcast_ndim + self->core_num_dim_ix;
 
2227
    if (op_ndim > NPY_MAXDIMS) {
 
2228
        PyErr_Format(PyExc_ValueError,
 
2229
                    "too many dimensions for generalized ufunc %s",
 
2230
                    ufunc_name);
 
2231
        retval = -1;
 
2232
        goto fail;
 
2233
    }
 
2234
 
 
2235
    /* Fill in op_axes for all the operands */
 
2236
    core_dim_ixs_size = 0;
 
2237
    core_dim_ixs = self->core_dim_ixs;
 
2238
    for (i = 0; i < nop; ++i) {
 
2239
        int n;
 
2240
        if (op[i]) {
 
2241
            /*
 
2242
             * Note that n may be negative if broadcasting
 
2243
             * extends into the core dimensions.
 
2244
             */
 
2245
            n = PyArray_NDIM(op[i]) - self->core_num_dims[i];
 
2246
        }
 
2247
        else {
 
2248
            n = broadcast_ndim;
 
2249
        }
 
2250
        /* Broadcast all the unspecified dimensions normally */
 
2251
        for (idim = 0; idim < broadcast_ndim; ++idim) {
 
2252
            if (idim >= broadcast_ndim - n) {
 
2253
                op_axes_arrays[i][idim] = idim - (broadcast_ndim - n);
 
2254
            }
 
2255
            else {
 
2256
                op_axes_arrays[i][idim] = -1;
 
2257
            }
 
2258
        }
 
2259
        /* Use the signature information for the rest */
 
2260
        for (idim = broadcast_ndim; idim < op_ndim; ++idim) {
 
2261
            op_axes_arrays[i][idim] = -1;
 
2262
        }
 
2263
        for (idim = 0; idim < self->core_num_dims[i]; ++idim) {
 
2264
            if (n + idim >= 0) {
 
2265
                op_axes_arrays[i][broadcast_ndim + core_dim_ixs[idim]] =
 
2266
                                                                    n + idim;
 
2267
            }
 
2268
            else {
 
2269
                op_axes_arrays[i][broadcast_ndim + core_dim_ixs[idim]] = -1;
 
2270
            }
 
2271
        }
 
2272
        core_dim_ixs_size += self->core_num_dims[i];
 
2273
        core_dim_ixs += self->core_num_dims[i];
 
2274
        op_axes[i] = op_axes_arrays[i];
 
2275
    }
 
2276
 
 
2277
    /* Get the buffersize, errormask, and error object globals */
1919
2278
    if (extobj == NULL) {
1920
 
        if (PyUFunc_GetPyValues(name,
1921
 
                                &(loop->bufsize), &(loop->errormask),
1922
 
                                &(loop->errobj)) < 0) {
 
2279
        if (PyUFunc_GetPyValues(ufunc_name,
 
2280
                                &buffersize, &errormask, &errobj) < 0) {
 
2281
            retval = -1;
1923
2282
            goto fail;
1924
2283
        }
1925
2284
    }
1926
2285
    else {
1927
 
        if (_extract_pyvals(extobj, name,
1928
 
                            &(loop->bufsize), &(loop->errormask),
1929
 
                            &(loop->errobj)) < 0) {
1930
 
            goto fail;
1931
 
        }
1932
 
    }
1933
 
 
1934
 
    /* Setup the arrays */
1935
 
    if (construct_arrays(loop, args, mps, typetup) < 0) {
1936
 
        goto fail;
1937
 
    }
 
2286
        if (_extract_pyvals(extobj, ufunc_name,
 
2287
                                &buffersize, &errormask, &errobj) < 0) {
 
2288
            retval = -1;
 
2289
            goto fail;
 
2290
        }
 
2291
    }
 
2292
 
 
2293
    NPY_UF_DBG_PRINT("Finding inner loop\n");
 
2294
 
 
2295
    /*
 
2296
     * Decide the casting rules for inputs and outputs.  We want
 
2297
     * NPY_SAFE_CASTING or stricter, so that the loop selection code
 
2298
     * doesn't choose an integer loop for float inputs, for example.
 
2299
     */
 
2300
    input_casting = (casting > NPY_SAFE_CASTING) ? NPY_SAFE_CASTING : casting;
 
2301
 
 
2302
    if (type_tup == NULL) {
 
2303
        /* Find the best ufunc inner loop, and fill in the dtypes */
 
2304
        retval = find_best_ufunc_inner_loop(self, op, input_casting, casting,
 
2305
                        buffersize, any_object, dtype,
 
2306
                        &innerloop, &innerloopdata, &trivial_loop_ok);
 
2307
    } else {
 
2308
        /* Find the specified ufunc inner loop, and fill in the dtypes */
 
2309
        retval = find_specified_ufunc_inner_loop(self, type_tup,
 
2310
                        op, casting,
 
2311
                        buffersize, any_object, dtype,
 
2312
                        &innerloop, &innerloopdata, &trivial_loop_ok);
 
2313
    }
 
2314
    if (retval < 0) {
 
2315
        goto fail;
 
2316
    }
 
2317
 
 
2318
    /*
 
2319
     * FAIL with NotImplemented if the other object has
 
2320
     * the __r<op>__ method and has __array_priority__ as
 
2321
     * an attribute (signalling it can handle ndarray's)
 
2322
     * and is not already an ndarray or a subtype of the same type.
 
2323
    */
 
2324
    if (nin == 2 && nout == 1 && dtype[1]->type_num == NPY_OBJECT) {
 
2325
        PyObject *_obj = PyTuple_GET_ITEM(args, 1);
 
2326
        if (!PyArray_CheckExact(_obj)
 
2327
               /* If both are same subtype of object arrays, then proceed */
 
2328
                && !(Py_TYPE(_obj) == Py_TYPE(PyTuple_GET_ITEM(args, 0)))
 
2329
                && PyObject_HasAttrString(_obj, "__array_priority__")
 
2330
                && _has_reflected_op(_obj, ufunc_name)) {
 
2331
            retval = -2;
 
2332
            goto fail;
 
2333
        }
 
2334
    }
 
2335
 
 
2336
#if NPY_UF_DBG_TRACING
 
2337
    printf("input types:\n");
 
2338
    for (i = 0; i < nin; ++i) {
 
2339
        PyObject_Print((PyObject *)dtype[i], stdout, 0);
 
2340
        printf(" ");
 
2341
    }
 
2342
    printf("\noutput types:\n");
 
2343
    for (i = nin; i < nop; ++i) {
 
2344
        PyObject_Print((PyObject *)dtype[i], stdout, 0);
 
2345
        printf(" ");
 
2346
    }
 
2347
    printf("\n");
 
2348
#endif
 
2349
 
 
2350
    if (subok) {
 
2351
        /*
 
2352
         * Get the appropriate __array_prepare__ function to call
 
2353
         * for each output
 
2354
         */
 
2355
        _find_array_prepare(args, kwds, arr_prep, nin, nout);
 
2356
 
 
2357
        /* Set up arr_prep_args if a prep function was needed */
 
2358
        for (i = 0; i < nout; ++i) {
 
2359
            if (arr_prep[i] != NULL && arr_prep[i] != Py_None) {
 
2360
                arr_prep_args = make_arr_prep_args(nin, args, kwds);
 
2361
                break;
 
2362
            }
 
2363
        }
 
2364
    }
 
2365
 
 
2366
    /* If the loop wants the arrays, provide them */
 
2367
    if (_does_loop_use_arrays(innerloopdata)) {
 
2368
        innerloopdata = (void*)op;
 
2369
    }
 
2370
 
 
2371
    /*
 
2372
     * Set up the iterator per-op flags.  For generalized ufuncs, we
 
2373
     * can't do buffering, so must COPY or UPDATEIFCOPY.
 
2374
     */
 
2375
    for (i = 0; i < nin; ++i) {
 
2376
        op_flags[i] = NPY_ITER_READONLY|
 
2377
                      NPY_ITER_COPY|
 
2378
                      NPY_ITER_ALIGNED;
 
2379
    }
 
2380
    for (i = nin; i < nop; ++i) {
 
2381
        op_flags[i] = NPY_ITER_READWRITE|
 
2382
                      NPY_ITER_UPDATEIFCOPY|
 
2383
                      NPY_ITER_ALIGNED|
 
2384
                      NPY_ITER_ALLOCATE|
 
2385
                      NPY_ITER_NO_BROADCAST;
 
2386
    }
 
2387
 
 
2388
    /* Create the iterator */
 
2389
    iter = NpyIter_AdvancedNew(nop, op, NPY_ITER_MULTI_INDEX|
 
2390
                                      NPY_ITER_REFS_OK|
 
2391
                                      NPY_ITER_REDUCE_OK,
 
2392
                           order, NPY_UNSAFE_CASTING, op_flags,
 
2393
                           dtype, op_ndim, op_axes, NULL, 0);
 
2394
    if (iter == NULL) {
 
2395
        retval = -1;
 
2396
        goto fail;
 
2397
    }
 
2398
 
 
2399
    /* Fill in any allocated outputs */
 
2400
    for (i = nin; i < nop; ++i) {
 
2401
        if (op[i] == NULL) {
 
2402
            op[i] = NpyIter_GetOperandArray(iter)[i];
 
2403
            Py_INCREF(op[i]);
 
2404
        }
 
2405
    }
 
2406
 
 
2407
    /*
 
2408
     * Set up the inner strides array. Because we're not doing
 
2409
     * buffering, the strides are fixed throughout the looping.
 
2410
     */
 
2411
    inner_strides = (npy_intp *)_pya_malloc(
 
2412
                        NPY_SIZEOF_INTP * (nop+core_dim_ixs_size));
 
2413
    /* The strides after the first nop match core_dim_ixs */
 
2414
    core_dim_ixs = self->core_dim_ixs;
 
2415
    inner_strides_tmp = inner_strides + nop;
 
2416
    for (idim = 0; idim < self->core_num_dim_ix; ++idim) {
 
2417
        ax_strides_tmp[idim] = NpyIter_GetAxisStrideArray(iter,
 
2418
                                                broadcast_ndim+idim);
 
2419
        if (ax_strides_tmp[idim] == NULL) {
 
2420
            retval = -1;
 
2421
            goto fail;
 
2422
        }
 
2423
    }
 
2424
    for (i = 0; i < nop; ++i) {
 
2425
        for (idim = 0; idim < self->core_num_dims[i]; ++idim) {
 
2426
            inner_strides_tmp[idim] = ax_strides_tmp[core_dim_ixs[idim]][i];
 
2427
        }
 
2428
 
 
2429
        core_dim_ixs += self->core_num_dims[i];
 
2430
        inner_strides_tmp += self->core_num_dims[i];
 
2431
    }
 
2432
 
 
2433
    /* Set up the inner dimensions array */
 
2434
    if (NpyIter_GetShape(iter, inner_dimensions) != NPY_SUCCEED) {
 
2435
        retval = -1;
 
2436
        goto fail;
 
2437
    }
 
2438
    /* Move the core dimensions to start at the second element */
 
2439
    memmove(&inner_dimensions[1], &inner_dimensions[broadcast_ndim],
 
2440
                        NPY_SIZEOF_INTP * self->core_num_dim_ix);
 
2441
 
 
2442
    /* Remove all the core dimensions from the iterator */
 
2443
    for (i = 0; i < self->core_num_dim_ix; ++i) {
 
2444
        if (NpyIter_RemoveAxis(iter, broadcast_ndim) != NPY_SUCCEED) {
 
2445
            retval = -1;
 
2446
            goto fail;
 
2447
        }
 
2448
    }
 
2449
    if (NpyIter_RemoveMultiIndex(iter) != NPY_SUCCEED) {
 
2450
        retval = -1;
 
2451
        goto fail;
 
2452
    }
 
2453
    if (NpyIter_EnableExternalLoop(iter) != NPY_SUCCEED) {
 
2454
        retval = -1;
 
2455
        goto fail;
 
2456
    }
 
2457
 
 
2458
    /*
 
2459
     * The first nop strides are for the inner loop (but only can
 
2460
     * copy them after removing the core axes
 
2461
     */
 
2462
    memcpy(inner_strides, NpyIter_GetInnerStrideArray(iter),
 
2463
                                    NPY_SIZEOF_INTP * nop);
 
2464
 
 
2465
#if 0
 
2466
    printf("strides: ");
 
2467
    for (i = 0; i < nop+core_dim_ixs_size; ++i) {
 
2468
        printf("%d ", (int)inner_strides[i]);
 
2469
    }
 
2470
    printf("\n");
 
2471
#endif
 
2472
 
 
2473
    /* Start with the floating-point exception flags cleared */
1938
2474
    PyUFunc_clearfperr();
1939
 
    return loop;
 
2475
 
 
2476
    NPY_UF_DBG_PRINT("Executing inner loop\n");
 
2477
 
 
2478
    /* Do the ufunc loop */
 
2479
    if (NpyIter_GetIterSize(iter) != 0) {
 
2480
        NpyIter_IterNextFunc *iternext;
 
2481
        char **dataptr;
 
2482
        npy_intp *count_ptr;
 
2483
 
 
2484
        /* Get the variables needed for the loop */
 
2485
        iternext = NpyIter_GetIterNext(iter, NULL);
 
2486
        if (iternext == NULL) {
 
2487
            NpyIter_Deallocate(iter);
 
2488
            retval = -1;
 
2489
            goto fail;
 
2490
        }
 
2491
        dataptr = NpyIter_GetDataPtrArray(iter);
 
2492
        count_ptr = NpyIter_GetInnerLoopSizePtr(iter);
 
2493
 
 
2494
        do {
 
2495
            inner_dimensions[0] = *count_ptr;
 
2496
            innerloop(dataptr, inner_dimensions, inner_strides, innerloopdata);
 
2497
        } while (iternext(iter));
 
2498
    }
 
2499
 
 
2500
    /* Check whether any errors occurred during the loop */
 
2501
    if (PyErr_Occurred() || (errormask &&
 
2502
            PyUFunc_checkfperr(errormask, errobj, &first_error))) {
 
2503
        retval = -1;
 
2504
        goto fail;
 
2505
    }
 
2506
 
 
2507
    _pya_free(inner_strides);
 
2508
    NpyIter_Deallocate(iter);
 
2509
    /* The caller takes ownership of all the references in op */
 
2510
    for (i = 0; i < nop; ++i) {
 
2511
        Py_XDECREF(dtype[i]);
 
2512
        Py_XDECREF(arr_prep[i]);
 
2513
    }
 
2514
    Py_XDECREF(errobj);
 
2515
    Py_XDECREF(type_tup);
 
2516
    Py_XDECREF(arr_prep_args);
 
2517
 
 
2518
    NPY_UF_DBG_PRINT("Returning Success\n");
 
2519
 
 
2520
    return 0;
1940
2521
 
1941
2522
fail:
1942
 
    ufuncloop_dealloc(loop);
1943
 
    return NULL;
 
2523
    NPY_UF_DBG_PRINT1("Returning failure code %d\n", retval);
 
2524
    if (inner_strides) {
 
2525
        _pya_free(inner_strides);
 
2526
    }
 
2527
    if (iter != NULL) {
 
2528
        NpyIter_Deallocate(iter);
 
2529
    }
 
2530
    for (i = 0; i < nop; ++i) {
 
2531
        Py_XDECREF(op[i]);
 
2532
        op[i] = NULL;
 
2533
        Py_XDECREF(dtype[i]);
 
2534
        Py_XDECREF(arr_prep[i]);
 
2535
    }
 
2536
    Py_XDECREF(errobj);
 
2537
    Py_XDECREF(type_tup);
 
2538
    Py_XDECREF(arr_prep_args);
 
2539
 
 
2540
    return retval;
1944
2541
}
1945
2542
 
1946
 
 
1947
 
/*
1948
 
  static void
1949
 
  _printbytebuf(PyUFuncLoopObject *loop, int bufnum)
1950
 
  {
1951
 
  int i;
1952
 
 
1953
 
  fprintf(stderr, "Printing byte buffer %d\n", bufnum);
1954
 
  for(i=0; i<loop->bufcnt; i++) {
1955
 
  fprintf(stderr, "  %d\n", *(((byte *)(loop->buffer[bufnum]))+i));
1956
 
  }
1957
 
  }
1958
 
 
1959
 
  static void
1960
 
  _printlongbuf(PyUFuncLoopObject *loop, int bufnum)
1961
 
  {
1962
 
  int i;
1963
 
 
1964
 
  fprintf(stderr, "Printing long buffer %d\n", bufnum);
1965
 
  for(i=0; i<loop->bufcnt; i++) {
1966
 
  fprintf(stderr, "  %ld\n", *(((long *)(loop->buffer[bufnum]))+i));
1967
 
  }
1968
 
  }
1969
 
 
1970
 
  static void
1971
 
  _printlongbufptr(PyUFuncLoopObject *loop, int bufnum)
1972
 
  {
1973
 
  int i;
1974
 
 
1975
 
  fprintf(stderr, "Printing long buffer %d\n", bufnum);
1976
 
  for(i=0; i<loop->bufcnt; i++) {
1977
 
  fprintf(stderr, "  %ld\n", *(((long *)(loop->bufptr[bufnum]))+i));
1978
 
  }
1979
 
  }
1980
 
 
1981
 
 
1982
 
 
1983
 
  static void
1984
 
  _printcastbuf(PyUFuncLoopObject *loop, int bufnum)
1985
 
  {
1986
 
  int i;
1987
 
 
1988
 
  fprintf(stderr, "Printing long buffer %d\n", bufnum);
1989
 
  for(i=0; i<loop->bufcnt; i++) {
1990
 
  fprintf(stderr, "  %ld\n", *(((long *)(loop->castbuf[bufnum]))+i));
1991
 
  }
1992
 
  }
1993
 
 
1994
 
*/
1995
 
 
1996
 
 
1997
 
 
1998
 
 
1999
 
/*
2000
 
 * currently generic ufuncs cannot be built for use on flexible arrays.
2001
 
 *
2002
 
 * The cast functions in the generic loop would need to be fixed to pass
2003
 
 * in something besides NULL, NULL.
2004
 
 *
2005
 
 * Also the underlying ufunc loops would not know the element-size unless
2006
 
 * that was passed in as data (which could be arranged).
2007
 
 *
2008
 
 */
2009
 
 
2010
2543
/*UFUNC_API
2011
2544
 *
2012
2545
 * This generic function is called with the ufunc object, the arguments to it,
2013
 
 * and an array of (pointers to) PyArrayObjects which are NULL.  The
2014
 
 * arguments are parsed and placed in mps in construct_loop (construct_arrays)
 
2546
 * and an array of (pointers to) PyArrayObjects which are NULL.
2015
2547
 */
2016
2548
NPY_NO_EXPORT int
2017
 
PyUFunc_GenericFunction(PyUFuncObject *self, PyObject *args, PyObject *kwds,
2018
 
                        PyArrayObject **mps)
2019
 
{
2020
 
    PyUFuncLoopObject *loop;
 
2549
PyUFunc_GenericFunction(PyUFuncObject *self,
 
2550
                        PyObject *args, PyObject *kwds,
 
2551
                        PyArrayObject **op)
 
2552
{
 
2553
    int nin, nout;
 
2554
    int i, nop;
 
2555
    char *ufunc_name;
 
2556
    int retval = -1, any_object = 0, subok = 1;
 
2557
    NPY_CASTING input_casting;
 
2558
 
 
2559
    PyArray_Descr *dtype[NPY_MAXARGS];
 
2560
 
 
2561
    /* These parameters come from extobj= or from a TLS global */
 
2562
    int buffersize = 0, errormask = 0;
 
2563
    PyObject *errobj = NULL;
 
2564
    int first_error = 1;
 
2565
 
 
2566
    /* The selected inner loop */
 
2567
    PyUFuncGenericFunction innerloop = NULL;
 
2568
    void *innerloopdata = NULL;
 
2569
 
 
2570
    /* The __array_prepare__ function to call for each output */
 
2571
    PyObject *arr_prep[NPY_MAXARGS];
 
2572
    /*
 
2573
     * This is either args, or args with the out= parameter from
 
2574
     * kwds added appropriately.
 
2575
     */
 
2576
    PyObject *arr_prep_args = NULL;
 
2577
 
 
2578
    int trivial_loop_ok = 0;
 
2579
 
 
2580
    /* TODO: For 1.6, the default should probably be NPY_CORDER */
 
2581
    NPY_ORDER order = NPY_KEEPORDER;
 
2582
    /*
 
2583
     * Many things in NumPy do unsafe casting (doing int += float, etc).
 
2584
     * The strictness should probably become a state parameter, similar
 
2585
     * to the seterr/geterr.
 
2586
     */
 
2587
    NPY_CASTING casting = NPY_UNSAFE_CASTING;
 
2588
    /* When provided, extobj and typetup contain borrowed references */
 
2589
    PyObject *extobj = NULL, *type_tup = NULL;
 
2590
 
 
2591
    if (self == NULL) {
 
2592
        PyErr_SetString(PyExc_ValueError, "function not supported");
 
2593
        return -1;
 
2594
    }
 
2595
 
 
2596
    /* TODO: support generalized ufunc */
 
2597
    if (self->core_enabled) {
 
2598
        return PyUFunc_GeneralizedFunction(self, args, kwds, op);
 
2599
    }
 
2600
 
 
2601
    nin = self->nin;
 
2602
    nout = self->nout;
 
2603
    nop = nin + nout;
 
2604
 
 
2605
    ufunc_name = self->name ? self->name : "<unnamed ufunc>";
 
2606
 
 
2607
    NPY_UF_DBG_PRINT1("\nEvaluating ufunc %s\n", ufunc_name);
 
2608
 
 
2609
    /* Initialize all the operands and dtypes to NULL */
 
2610
    for (i = 0; i < nop; ++i) {
 
2611
        op[i] = NULL;
 
2612
        dtype[i] = NULL;
 
2613
        arr_prep[i] = NULL;
 
2614
    }
 
2615
 
 
2616
    NPY_UF_DBG_PRINT("Getting arguments\n");
 
2617
 
 
2618
    /* Get all the arguments */
 
2619
    retval = get_ufunc_arguments(self, args, kwds,
 
2620
                op, &order, &casting, &extobj, &type_tup, &subok, &any_object);
 
2621
    if (retval < 0) {
 
2622
        goto fail;
 
2623
    }
 
2624
 
 
2625
    /* Get the buffersize, errormask, and error object globals */
 
2626
    if (extobj == NULL) {
 
2627
        if (PyUFunc_GetPyValues(ufunc_name,
 
2628
                                &buffersize, &errormask, &errobj) < 0) {
 
2629
            retval = -1;
 
2630
            goto fail;
 
2631
        }
 
2632
    }
 
2633
    else {
 
2634
        if (_extract_pyvals(extobj, ufunc_name,
 
2635
                                &buffersize, &errormask, &errobj) < 0) {
 
2636
            retval = -1;
 
2637
            goto fail;
 
2638
        }
 
2639
    }
 
2640
 
 
2641
    NPY_UF_DBG_PRINT("Finding inner loop\n");
 
2642
 
 
2643
    /*
 
2644
     * Decide the casting rules for inputs and outputs.  We want
 
2645
     * NPY_SAFE_CASTING or stricter, so that the loop selection code
 
2646
     * doesn't choose an integer loop for float inputs, for example.
 
2647
     */
 
2648
    input_casting = (casting > NPY_SAFE_CASTING) ? NPY_SAFE_CASTING : casting;
 
2649
 
 
2650
    if (type_tup == NULL) {
 
2651
        /* Find the best ufunc inner loop, and fill in the dtypes */
 
2652
        retval = find_best_ufunc_inner_loop(self, op, input_casting, casting,
 
2653
                        buffersize, any_object, dtype,
 
2654
                        &innerloop, &innerloopdata, &trivial_loop_ok);
 
2655
    } else {
 
2656
        /* Find the specified ufunc inner loop, and fill in the dtypes */
 
2657
        retval = find_specified_ufunc_inner_loop(self, type_tup,
 
2658
                        op, casting,
 
2659
                        buffersize, any_object, dtype,
 
2660
                        &innerloop, &innerloopdata, &trivial_loop_ok);
 
2661
    }
 
2662
    if (retval < 0) {
 
2663
        goto fail;
 
2664
    }
 
2665
 
 
2666
    /*
 
2667
     * FAIL with NotImplemented if the other object has
 
2668
     * the __r<op>__ method and has __array_priority__ as
 
2669
     * an attribute (signalling it can handle ndarray's)
 
2670
     * and is not already an ndarray or a subtype of the same type.
 
2671
    */
 
2672
    if (nin == 2 && nout == 1 && dtype[1]->type_num == NPY_OBJECT) {
 
2673
        PyObject *_obj = PyTuple_GET_ITEM(args, 1);
 
2674
        if (!PyArray_CheckExact(_obj)
 
2675
               /* If both are same subtype of object arrays, then proceed */
 
2676
                && !(Py_TYPE(_obj) == Py_TYPE(PyTuple_GET_ITEM(args, 0)))
 
2677
                && PyObject_HasAttrString(_obj, "__array_priority__")
 
2678
                && _has_reflected_op(_obj, ufunc_name)) {
 
2679
            retval = -2;
 
2680
            goto fail;
 
2681
        }
 
2682
    }
 
2683
 
 
2684
#if NPY_UF_DBG_TRACING
 
2685
    printf("input types:\n");
 
2686
    for (i = 0; i < nin; ++i) {
 
2687
        PyObject_Print((PyObject *)dtype[i], stdout, 0);
 
2688
        printf(" ");
 
2689
    }
 
2690
    printf("\noutput types:\n");
 
2691
    for (i = nin; i < nop; ++i) {
 
2692
        PyObject_Print((PyObject *)dtype[i], stdout, 0);
 
2693
        printf(" ");
 
2694
    }
 
2695
    printf("\n");
 
2696
#endif
 
2697
 
 
2698
    if (subok) {
 
2699
        /*
 
2700
         * Get the appropriate __array_prepare__ function to call
 
2701
         * for each output
 
2702
         */
 
2703
        _find_array_prepare(args, kwds, arr_prep, nin, nout);
 
2704
 
 
2705
        /* Set up arr_prep_args if a prep function was needed */
 
2706
        for (i = 0; i < nout; ++i) {
 
2707
            if (arr_prep[i] != NULL && arr_prep[i] != Py_None) {
 
2708
                arr_prep_args = make_arr_prep_args(nin, args, kwds);
 
2709
                break;
 
2710
            }
 
2711
        }
 
2712
    }
 
2713
 
 
2714
    /* If the loop wants the arrays, provide them */
 
2715
    if (_does_loop_use_arrays(innerloopdata)) {
 
2716
        innerloopdata = (void*)op;
 
2717
    }
 
2718
 
 
2719
    /* Start with the floating-point exception flags cleared */
 
2720
    PyUFunc_clearfperr();
 
2721
 
 
2722
    NPY_UF_DBG_PRINT("Executing inner loop\n");
 
2723
 
 
2724
    /* Do the ufunc loop */
 
2725
    retval = execute_ufunc_loop(self, trivial_loop_ok, op, dtype, order,
 
2726
                        buffersize, arr_prep, arr_prep_args,
 
2727
                        innerloop, innerloopdata);
 
2728
    if (retval < 0) {
 
2729
        goto fail;
 
2730
    }
 
2731
 
 
2732
    /* Check whether any errors occurred during the loop */
 
2733
    if (PyErr_Occurred() || (errormask &&
 
2734
            PyUFunc_checkfperr(errormask, errobj, &first_error))) {
 
2735
        retval = -1;
 
2736
        goto fail;
 
2737
    }
 
2738
 
 
2739
    /* The caller takes ownership of all the references in op */
 
2740
    for (i = 0; i < nop; ++i) {
 
2741
        Py_XDECREF(dtype[i]);
 
2742
        Py_XDECREF(arr_prep[i]);
 
2743
    }
 
2744
    Py_XDECREF(errobj);
 
2745
    Py_XDECREF(type_tup);
 
2746
    Py_XDECREF(arr_prep_args);
 
2747
 
 
2748
    NPY_UF_DBG_PRINT("Returning Success\n");
 
2749
 
 
2750
    return 0;
 
2751
 
 
2752
fail:
 
2753
    NPY_UF_DBG_PRINT1("Returning failure code %d\n", retval);
 
2754
    for (i = 0; i < nop; ++i) {
 
2755
        Py_XDECREF(op[i]);
 
2756
        op[i] = NULL;
 
2757
        Py_XDECREF(dtype[i]);
 
2758
        Py_XDECREF(arr_prep[i]);
 
2759
    }
 
2760
    Py_XDECREF(errobj);
 
2761
    Py_XDECREF(type_tup);
 
2762
    Py_XDECREF(arr_prep_args);
 
2763
 
 
2764
    return retval;
 
2765
}
 
2766
 
 
2767
/*
 
2768
 * Given the output type, finds the specified binary op.  The
 
2769
 * ufunc must have nin==2 and nout==1.  The function may modify
 
2770
 * otype if the given type isn't found.
 
2771
 *
 
2772
 * Returns 0 on success, -1 on failure.
 
2773
 */
 
2774
static int
 
2775
get_binary_op_function(PyUFuncObject *self, int *otype,
 
2776
                        PyUFuncGenericFunction *out_innerloop,
 
2777
                        void **out_innerloopdata)
 
2778
{
2021
2779
    int i;
2022
 
    NPY_BEGIN_THREADS_DEF;
2023
 
 
2024
 
    if (!(loop = construct_loop(self, args, kwds, mps))) {
2025
 
        return -1;
2026
 
    }
2027
 
    if (loop->notimplemented) {
2028
 
        ufuncloop_dealloc(loop);
2029
 
        return -2;
2030
 
    }
2031
 
    if (self->core_enabled && loop->meth != SIGNATURE_NOBUFFER_UFUNCLOOP) {
2032
 
        PyErr_SetString(PyExc_RuntimeError,
2033
 
                        "illegal loop method for ufunc with signature");
2034
 
        goto fail;
2035
 
    }
2036
 
 
2037
 
    NPY_LOOP_BEGIN_THREADS;
2038
 
    switch(loop->meth) {
2039
 
    case ONE_UFUNCLOOP:
2040
 
        /*
2041
 
         * Everything is contiguous, notswapped, aligned,
2042
 
         * and of the right type.  -- Fastest.
2043
 
         * Or if not contiguous, then a single-stride
2044
 
         * increment moves through the entire array.
2045
 
         */
2046
 
        /*fprintf(stderr, "ONE...%d\n", loop->size);*/
2047
 
        loop->function((char **)loop->bufptr, &(loop->size),
2048
 
                loop->steps, loop->funcdata);
2049
 
        UFUNC_CHECK_ERROR(loop);
2050
 
        break;
2051
 
    case NOBUFFER_UFUNCLOOP:
2052
 
        /*
2053
 
         * Everything is notswapped, aligned and of the
2054
 
         * right type but not contiguous. -- Almost as fast.
2055
 
         */
2056
 
        /*fprintf(stderr, "NOBUFFER...%d\n", loop->size);*/
2057
 
        while (loop->index < loop->size) {
2058
 
            for (i = 0; i < self->nargs; i++) {
2059
 
                loop->bufptr[i] = loop->iters[i]->dataptr;
2060
 
            }
2061
 
            loop->function((char **)loop->bufptr, &(loop->bufcnt),
2062
 
                    loop->steps, loop->funcdata);
2063
 
            UFUNC_CHECK_ERROR(loop);
2064
 
 
2065
 
            /* Adjust loop pointers */
2066
 
            for (i = 0; i < self->nargs; i++) {
2067
 
                PyArray_ITER_NEXT(loop->iters[i]);
2068
 
            }
2069
 
            loop->index++;
2070
 
        }
2071
 
        break;
2072
 
    case SIGNATURE_NOBUFFER_UFUNCLOOP:
2073
 
        while (loop->index < loop->size) {
2074
 
            for (i = 0; i < self->nargs; i++) {
2075
 
                loop->bufptr[i] = loop->iters[i]->dataptr;
2076
 
            }
2077
 
            loop->function((char **)loop->bufptr, loop->core_dim_sizes,
2078
 
                    loop->core_strides, loop->funcdata);
2079
 
            UFUNC_CHECK_ERROR(loop);
2080
 
 
2081
 
            /* Adjust loop pointers */
2082
 
            for (i = 0; i < self->nargs; i++) {
2083
 
                PyArray_ITER_NEXT(loop->iters[i]);
2084
 
            }
2085
 
            loop->index++;
2086
 
        }
2087
 
        break;
2088
 
    case BUFFER_UFUNCLOOP: {
2089
 
        /* This should be a function */
2090
 
        PyArray_CopySwapNFunc *copyswapn[NPY_MAXARGS];
2091
 
        PyArrayIterObject **iters=loop->iters;
2092
 
        int *swap=loop->swap;
2093
 
        char **dptr=loop->dptr;
2094
 
        int mpselsize[NPY_MAXARGS];
2095
 
        intp laststrides[NPY_MAXARGS];
2096
 
        int fastmemcpy[NPY_MAXARGS];
2097
 
        int *needbuffer = loop->needbuffer;
2098
 
        intp index=loop->index, size=loop->size;
2099
 
        int bufsize;
2100
 
        intp bufcnt;
2101
 
        int copysizes[NPY_MAXARGS];
2102
 
        char **bufptr = loop->bufptr;
2103
 
        char **buffer = loop->buffer;
2104
 
        char **castbuf = loop->castbuf;
2105
 
        intp *steps = loop->steps;
2106
 
        char *tptr[NPY_MAXARGS];
2107
 
        int ninnerloops = loop->ninnerloops;
2108
 
        Bool pyobject[NPY_MAXARGS];
2109
 
        int datasize[NPY_MAXARGS];
2110
 
        int j, k, stopcondition;
2111
 
        char *myptr1, *myptr2;
2112
 
 
2113
 
        for (i = 0; i <self->nargs; i++) {
2114
 
            copyswapn[i] = mps[i]->descr->f->copyswapn;
2115
 
            mpselsize[i] = mps[i]->descr->elsize;
2116
 
            pyobject[i] = ((loop->obj & UFUNC_OBJ_ISOBJECT)
2117
 
                    && (mps[i]->descr->type_num == PyArray_OBJECT));
2118
 
            laststrides[i] = iters[i]->strides[loop->lastdim];
2119
 
            if (steps[i] && laststrides[i] != mpselsize[i]) {
2120
 
                fastmemcpy[i] = 0;
2121
 
            }
 
2780
    PyUFunc_Loop1d *funcdata;
 
2781
 
 
2782
    NPY_UF_DBG_PRINT1("Getting binary op function for type number %d\n",
 
2783
                                *otype);
 
2784
 
 
2785
    /* If the type is custom and there are userloops, search for it here */
 
2786
    if (self->userloops != NULL && PyTypeNum_ISUSERDEF(*otype)) {
 
2787
        PyObject *key, *obj;
 
2788
        key = PyInt_FromLong(*otype);
 
2789
        if (key == NULL) {
 
2790
            return -1;
 
2791
        }
 
2792
        obj = PyDict_GetItem(self->userloops, key);
 
2793
        Py_DECREF(key);
 
2794
        if (obj != NULL) {
 
2795
            funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
 
2796
            while (funcdata != NULL) {
 
2797
                int *types = funcdata->arg_types;
 
2798
 
 
2799
                if (types[0] == *otype && types[1] == *otype &&
 
2800
                                                types[2] == *otype) {
 
2801
                    *out_innerloop = funcdata->func;
 
2802
                    *out_innerloopdata = funcdata->data;
 
2803
                    return 0;
 
2804
                }
 
2805
 
 
2806
                funcdata = funcdata->next;
 
2807
            }
 
2808
        }
 
2809
    }
 
2810
 
 
2811
    /* Search for a function with compatible inputs */
 
2812
    for (i = 0; i < self->ntypes; ++i) {
 
2813
        char *types = self->types + i*self->nargs;
 
2814
 
 
2815
        NPY_UF_DBG_PRINT3("Trying loop with signature %d %d -> %d\n",
 
2816
                                types[0], types[1], types[2]);
 
2817
 
 
2818
        if (PyArray_CanCastSafely(*otype, types[0]) &&
 
2819
                    types[0] == types[1] &&
 
2820
                    (*otype == NPY_OBJECT || types[0] != NPY_OBJECT)) {
 
2821
            /* If the signature is "xx->x", we found the loop */
 
2822
            if (types[2] == types[0]) {
 
2823
                *out_innerloop = self->functions[i];
 
2824
                *out_innerloopdata = self->data[i];
 
2825
                *otype = types[0];
 
2826
                return 0;
 
2827
            }
 
2828
            /*
 
2829
             * Otherwise, we found the natural type of the reduction,
 
2830
             * replace otype and search again
 
2831
             */
2122
2832
            else {
2123
 
                fastmemcpy[i] = 1;
2124
 
            }
2125
 
        }
2126
 
        /* Do generic buffered looping here (works for any kind of
2127
 
         * arrays -- some need buffers, some don't.
2128
 
         *
2129
 
         *
2130
 
         * New algorithm: N is the largest dimension.  B is the buffer-size.
2131
 
         * quotient is loop->ninnerloops-1
2132
 
         * remainder is loop->leftover
2133
 
         *
2134
 
         * Compute N = quotient * B + remainder.
2135
 
         * quotient = N / B  # integer math
2136
 
         * (store quotient + 1) as the number of innerloops
2137
 
         * remainder = N % B # integer remainder
2138
 
         *
2139
 
         * On the inner-dimension we will have (quotient + 1) loops where
2140
 
         * the size of the inner function is B for all but the last when the niter size is
2141
 
         * remainder.
2142
 
         *
2143
 
         * So, the code looks very similar to NOBUFFER_LOOP except the inner-most loop is
2144
 
         * replaced with...
2145
 
         *
2146
 
         * for(i=0; i<quotient+1; i++) {
2147
 
         * if (i==quotient+1) make itersize remainder size
2148
 
         * copy only needed items to buffer.
2149
 
         * swap input buffers if needed
2150
 
         * cast input buffers if needed
2151
 
         * call loop_function()
2152
 
         * cast outputs in buffers if needed
2153
 
         * swap outputs in buffers if needed
2154
 
         * copy only needed items back to output arrays.
2155
 
         * update all data-pointers by strides*niter
2156
 
         * }
2157
 
         */
2158
 
 
2159
 
 
2160
 
        /*
2161
 
         * fprintf(stderr, "BUFFER...%d,%d,%d\n", loop->size,
2162
 
         * loop->ninnerloops, loop->leftover);
2163
 
         */
2164
 
        /*
2165
 
         * for(i=0; i<self->nargs; i++) {
2166
 
         * fprintf(stderr, "iters[%d]->dataptr = %p, %p of size %d\n", i,
2167
 
         * iters[i], iters[i]->ao->data, PyArray_NBYTES(iters[i]->ao));
2168
 
         * }
2169
 
         */
2170
 
        stopcondition = ninnerloops;
2171
 
        if (loop->leftover == 0) {
2172
 
            stopcondition--;
2173
 
        }
2174
 
        while (index < size) {
2175
 
            bufsize=loop->bufsize;
2176
 
            for(i = 0; i<self->nargs; i++) {
2177
 
                tptr[i] = loop->iters[i]->dataptr;
2178
 
                if (needbuffer[i]) {
2179
 
                    dptr[i] = bufptr[i];
2180
 
                    datasize[i] = (steps[i] ? bufsize : 1);
2181
 
                    copysizes[i] = datasize[i] * mpselsize[i];
2182
 
                }
2183
 
                else {
2184
 
                    dptr[i] = tptr[i];
2185
 
                }
2186
 
            }
2187
 
 
2188
 
            /* This is the inner function over the last dimension */
2189
 
            for (k = 1; k<=stopcondition; k++) {
2190
 
                if (k == ninnerloops) {
2191
 
                    bufsize = loop->leftover;
2192
 
                    for (i=0; i<self->nargs;i++) {
2193
 
                        if (!needbuffer[i]) {
2194
 
                            continue;
2195
 
                        }
2196
 
                        datasize[i] = (steps[i] ? bufsize : 1);
2197
 
                        copysizes[i] = datasize[i] * mpselsize[i];
2198
 
                    }
2199
 
                }
2200
 
                for (i = 0; i < self->nin; i++) {
2201
 
                    if (!needbuffer[i]) {
2202
 
                        continue;
2203
 
                    }
2204
 
                    if (fastmemcpy[i]) {
2205
 
                        memcpy(buffer[i], tptr[i], copysizes[i]);
2206
 
                    }
2207
 
                    else {
2208
 
                        myptr1 = buffer[i];
2209
 
                        myptr2 = tptr[i];
2210
 
                        for (j = 0; j < bufsize; j++) {
2211
 
                            memcpy(myptr1, myptr2, mpselsize[i]);
2212
 
                            myptr1 += mpselsize[i];
2213
 
                            myptr2 += laststrides[i];
2214
 
                        }
2215
 
                    }
2216
 
 
2217
 
                    /* swap the buffer if necessary */
2218
 
                    if (swap[i]) {
2219
 
                        /* fprintf(stderr, "swapping...\n");*/
2220
 
                        copyswapn[i](buffer[i], mpselsize[i], NULL, -1,
2221
 
                                (intp) datasize[i], 1,
2222
 
                                mps[i]);
2223
 
                    }
2224
 
                    /* cast to the other buffer if necessary */
2225
 
                    if (loop->cast[i]) {
2226
 
                        /* fprintf(stderr, "casting... %d, %p %p\n", i, buffer[i]); */
2227
 
                        loop->cast[i](buffer[i], castbuf[i],
2228
 
                                (intp) datasize[i],
2229
 
                                NULL, NULL);
2230
 
                    }
2231
 
                }
2232
 
 
2233
 
                bufcnt = (intp) bufsize;
2234
 
                loop->function((char **)dptr, &bufcnt, steps, loop->funcdata);
2235
 
                UFUNC_CHECK_ERROR(loop);
2236
 
 
2237
 
                for (i = self->nin; i < self->nargs; i++) {
2238
 
                    if (!needbuffer[i]) {
2239
 
                        continue;
2240
 
                    }
2241
 
                    if (loop->cast[i]) {
2242
 
                        /* fprintf(stderr, "casting back... %d, %p", i, castbuf[i]); */
2243
 
                        loop->cast[i](castbuf[i],
2244
 
                                buffer[i],
2245
 
                                (intp) datasize[i],
2246
 
                                NULL, NULL);
2247
 
                    }
2248
 
                    if (swap[i]) {
2249
 
                        copyswapn[i](buffer[i], mpselsize[i], NULL, -1,
2250
 
                                (intp) datasize[i], 1,
2251
 
                                mps[i]);
2252
 
                    }
2253
 
                    /*
2254
 
                     * copy back to output arrays
2255
 
                     * decref what's already there for object arrays
2256
 
                     */
2257
 
                    if (pyobject[i]) {
2258
 
                        myptr1 = tptr[i];
2259
 
                        for (j = 0; j < datasize[i]; j++) {
2260
 
                            Py_XDECREF(*((PyObject **)myptr1));
2261
 
                            myptr1 += laststrides[i];
2262
 
                        }
2263
 
                    }
2264
 
                    if (fastmemcpy[i]) {
2265
 
                        memcpy(tptr[i], buffer[i], copysizes[i]);
2266
 
                    }
2267
 
                    else {
2268
 
                        myptr2 = buffer[i];
2269
 
                        myptr1 = tptr[i];
2270
 
                        for (j = 0; j < bufsize; j++) {
2271
 
                            memcpy(myptr1, myptr2, mpselsize[i]);
2272
 
                            myptr1 += laststrides[i];
2273
 
                            myptr2 += mpselsize[i];
2274
 
                        }
2275
 
                    }
2276
 
                }
2277
 
                if (k == stopcondition) {
2278
 
                    continue;
2279
 
                }
2280
 
                for (i = 0; i < self->nargs; i++) {
2281
 
                    tptr[i] += bufsize * laststrides[i];
2282
 
                    if (!needbuffer[i]) {
2283
 
                        dptr[i] = tptr[i];
2284
 
                    }
2285
 
                }
2286
 
            }
2287
 
            /* end inner function over last dimension */
2288
 
 
2289
 
            if (loop->objfunc) {
2290
 
                /*
2291
 
                 * DECREF castbuf when underlying function used
2292
 
                 * object arrays and casting was needed to get
2293
 
                 * to object arrays
2294
 
                 */
2295
 
                for (i = 0; i < self->nargs; i++) {
2296
 
                    if (loop->cast[i]) {
2297
 
                        if (steps[i] == 0) {
2298
 
                            Py_XDECREF(*((PyObject **)castbuf[i]));
2299
 
                        }
2300
 
                        else {
2301
 
                            int size = loop->bufsize;
2302
 
 
2303
 
                            PyObject **objptr = (PyObject **)castbuf[i];
2304
 
                            /*
2305
 
                             * size is loop->bufsize unless there
2306
 
                             * was only one loop
2307
 
                             */
2308
 
                            if (ninnerloops == 1) {
2309
 
                                size = loop->leftover;
2310
 
                            }
2311
 
                            for (j = 0; j < size; j++) {
2312
 
                                Py_XDECREF(*objptr);
2313
 
                                *objptr = NULL;
2314
 
                                objptr += 1;
2315
 
                            }
2316
 
                        }
2317
 
                    }
2318
 
                }
2319
 
            }
2320
 
            /* fixme -- probably not needed here*/
2321
 
            UFUNC_CHECK_ERROR(loop);
2322
 
 
2323
 
            for (i = 0; i < self->nargs; i++) {
2324
 
                PyArray_ITER_NEXT(loop->iters[i]);
2325
 
            }
2326
 
            index++;
2327
 
        }
2328
 
    } /* end of last case statement */
2329
 
    }
2330
 
 
2331
 
    NPY_LOOP_END_THREADS;
2332
 
    ufuncloop_dealloc(loop);
2333
 
    return 0;
2334
 
 
2335
 
fail:
2336
 
    NPY_LOOP_END_THREADS;
2337
 
    if (loop) {
2338
 
        ufuncloop_dealloc(loop);
2339
 
    }
 
2833
                *otype = types[2];
 
2834
                break;
 
2835
            }
 
2836
        }
 
2837
    }
 
2838
 
 
2839
    /* Search for the exact function */
 
2840
    for (i = 0; i < self->ntypes; ++i) {
 
2841
        char *types = self->types + i*self->nargs;
 
2842
 
 
2843
        if (PyArray_CanCastSafely(*otype, types[0]) &&
 
2844
                    types[0] == types[1] &&
 
2845
                    types[1] == types[2] &&
 
2846
                    (*otype == NPY_OBJECT || types[0] != NPY_OBJECT)) {
 
2847
            /* Since the signature is "xx->x", we found the loop */
 
2848
            *out_innerloop = self->functions[i];
 
2849
            *out_innerloopdata = self->data[i];
 
2850
            *otype = types[0];
 
2851
            return 0;
 
2852
        }
 
2853
    }
 
2854
 
2340
2855
    return -1;
2341
2856
}
2342
2857
 
2343
 
static PyArrayObject *
2344
 
_getidentity(PyUFuncObject *self, int otype, char *str)
 
2858
/*
 
2859
 * The implementation of the reduction operators with the new iterator
 
2860
 * turned into a bit of a long function here, but I think the design
 
2861
 * of this part needs to be changed to be more like einsum, so it may
 
2862
 * not be worth refactoring it too much.  Consider this timing:
 
2863
 *
 
2864
 * >>> a = arange(10000)
 
2865
 *
 
2866
 * >>> timeit sum(a)
 
2867
 * 10000 loops, best of 3: 17 us per loop
 
2868
 *
 
2869
 * >>> timeit einsum("i->",a)
 
2870
 * 100000 loops, best of 3: 13.5 us per loop
 
2871
 *
 
2872
 */
 
2873
static PyObject *
 
2874
PyUFunc_ReductionOp(PyUFuncObject *self, PyArrayObject *arr,
 
2875
                    PyArrayObject *out,
 
2876
                    int axis, int otype, int operation, char *opname)
2345
2877
{
2346
 
    PyObject *obj, *arr;
2347
 
    PyArray_Descr *typecode;
2348
 
 
2349
 
    if (self->identity == PyUFunc_None) {
 
2878
    PyArrayObject *op[2];
 
2879
    PyArray_Descr *op_dtypes[2] = {NULL, NULL};
 
2880
    int op_axes_arrays[2][NPY_MAXDIMS];
 
2881
    int *op_axes[2] = {op_axes_arrays[0], op_axes_arrays[1]};
 
2882
    npy_uint32 op_flags[2];
 
2883
    int i, idim, ndim, otype_final;
 
2884
    int needs_api, need_outer_iterator;
 
2885
 
 
2886
    NpyIter *iter = NULL, *iter_inner = NULL;
 
2887
 
 
2888
    /* The selected inner loop */
 
2889
    PyUFuncGenericFunction innerloop = NULL;
 
2890
    void *innerloopdata = NULL;
 
2891
 
 
2892
    char *ufunc_name = self->name ? self->name : "(unknown)";
 
2893
 
 
2894
    /* These parameters come from extobj= or from a TLS global */
 
2895
    int buffersize = 0, errormask = 0;
 
2896
    PyObject *errobj = NULL;
 
2897
 
 
2898
    NPY_BEGIN_THREADS_DEF;
 
2899
 
 
2900
    NPY_UF_DBG_PRINT2("\nEvaluating ufunc %s.%s\n", ufunc_name, opname);
 
2901
 
 
2902
#if 0
 
2903
    printf("Doing %s.%s on array with dtype :  ", ufunc_name, opname);
 
2904
    PyObject_Print((PyObject *)PyArray_DESCR(arr), stdout, 0);
 
2905
    printf("\n");
 
2906
#endif
 
2907
 
 
2908
    if (PyUFunc_GetPyValues(opname, &buffersize, &errormask, &errobj) < 0) {
 
2909
        return NULL;
 
2910
    }
 
2911
 
 
2912
    /* Take a reference to out for later returning */
 
2913
    Py_XINCREF(out);
 
2914
 
 
2915
    otype_final = otype;
 
2916
    if (get_binary_op_function(self, &otype_final,
 
2917
                                &innerloop, &innerloopdata) < 0) {
 
2918
        PyArray_Descr *dtype = PyArray_DescrFromType(otype);
2350
2919
        PyErr_Format(PyExc_ValueError,
2351
 
                     "zero-size array to ufunc.%s "      \
2352
 
                     "without identity", str);
2353
 
        return NULL;
2354
 
    }
2355
 
    if (self->identity == PyUFunc_One) {
2356
 
        obj = PyInt_FromLong((long) 1);
2357
 
    } else {
2358
 
        obj = PyInt_FromLong((long) 0);
2359
 
    }
2360
 
 
2361
 
    typecode = PyArray_DescrFromType(otype);
2362
 
    arr = PyArray_FromAny(obj, typecode, 0, 0, CARRAY, NULL);
2363
 
    Py_DECREF(obj);
2364
 
    return (PyArrayObject *)arr;
2365
 
}
2366
 
 
2367
 
static int
2368
 
_create_reduce_copy(PyUFuncReduceObject *loop, PyArrayObject **arr, int rtype)
2369
 
{
2370
 
    intp maxsize;
2371
 
    PyObject *new;
2372
 
    PyArray_Descr *ntype;
2373
 
 
2374
 
    maxsize = PyArray_SIZE(*arr);
2375
 
 
2376
 
    if (maxsize < loop->bufsize) {
2377
 
        if (!(PyArray_ISBEHAVED_RO(*arr))
2378
 
            || PyArray_TYPE(*arr) != rtype) {
2379
 
            ntype = PyArray_DescrFromType(rtype);
2380
 
            new = PyArray_FromAny((PyObject *)(*arr),
2381
 
                                  ntype, 0, 0,
2382
 
                                  FORCECAST | ALIGNED, NULL);
2383
 
            if (new == NULL) {
2384
 
                return -1;
2385
 
            }
2386
 
            *arr = (PyArrayObject *)new;
2387
 
            loop->decref = new;
2388
 
        }
2389
 
    }
2390
 
 
2391
 
    /*
2392
 
     * Don't decref *arr before re-assigning
2393
 
     * because it was not going to be DECREF'd anyway.
2394
 
     *
2395
 
     * If a copy is made, then the copy will be removed
2396
 
     * on deallocation of the loop structure by setting
2397
 
     * loop->decref.
2398
 
     */
2399
 
    return 0;
2400
 
}
2401
 
 
2402
 
static PyUFuncReduceObject *
2403
 
construct_reduce(PyUFuncObject *self, PyArrayObject **arr, PyArrayObject *out,
2404
 
                 int axis, int otype, int operation, intp ind_size, char *str)
2405
 
{
2406
 
    PyUFuncReduceObject *loop;
2407
 
    PyArrayObject *idarr;
2408
 
    PyArrayObject *aar;
2409
 
    intp loop_i[MAX_DIMS], outsize = 0;
2410
 
    int arg_types[3];
2411
 
    PyArray_SCALARKIND scalars[3] = {PyArray_NOSCALAR, PyArray_NOSCALAR,
2412
 
                                     PyArray_NOSCALAR};
2413
 
    int i, j, nd;
2414
 
    int flags;
2415
 
 
2416
 
    /* Reduce type is the type requested of the input during reduction */
2417
 
    if (self->core_enabled) {
2418
 
        PyErr_Format(PyExc_RuntimeError,
2419
 
                     "construct_reduce not allowed on ufunc with signature");
2420
 
        return NULL;
2421
 
    }
2422
 
    nd = (*arr)->nd;
2423
 
    arg_types[0] = otype;
2424
 
    arg_types[1] = otype;
2425
 
    arg_types[2] = otype;
2426
 
    if ((loop = _pya_malloc(sizeof(PyUFuncReduceObject))) == NULL) {
2427
 
        PyErr_NoMemory();
2428
 
        return loop;
2429
 
    }
2430
 
 
2431
 
    loop->retbase = 0;
2432
 
    loop->swap = 0;
2433
 
    loop->index = 0;
2434
 
    loop->ufunc = self;
2435
 
    Py_INCREF(self);
2436
 
    loop->cast = NULL;
2437
 
    loop->buffer = NULL;
2438
 
    loop->ret = NULL;
2439
 
    loop->it = NULL;
2440
 
    loop->rit = NULL;
2441
 
    loop->errobj = NULL;
2442
 
    loop->first = 1;
2443
 
    loop->decref = NULL;
2444
 
    loop->N = (*arr)->dimensions[axis];
2445
 
    loop->instrides = (*arr)->strides[axis];
2446
 
    if (select_types(loop->ufunc, arg_types, &(loop->function),
2447
 
                     &(loop->funcdata), scalars, NULL) == -1) {
2448
 
        goto fail;
2449
 
    }
2450
 
    /*
2451
 
     * output type may change -- if it does
2452
 
     * reduction is forced into that type
2453
 
     * and we need to select the reduction function again
2454
 
     */
2455
 
    if (otype != arg_types[2]) {
2456
 
        otype = arg_types[2];
2457
 
        arg_types[0] = otype;
2458
 
        arg_types[1] = otype;
2459
 
        if (select_types(loop->ufunc, arg_types, &(loop->function),
2460
 
                         &(loop->funcdata), scalars, NULL) == -1) {
2461
 
            goto fail;
2462
 
        }
2463
 
    }
2464
 
 
2465
 
    /* get looping parameters from Python */
2466
 
    if (PyUFunc_GetPyValues(str, &(loop->bufsize), &(loop->errormask),
2467
 
                            &(loop->errobj)) < 0) {
2468
 
        goto fail;
2469
 
    }
2470
 
    /* Make copy if misbehaved or not otype for small arrays */
2471
 
    if (_create_reduce_copy(loop, arr, otype) < 0) {
2472
 
        goto fail;
2473
 
    }
2474
 
    aar = *arr;
2475
 
 
2476
 
    if (loop->N == 0) {
2477
 
        loop->meth = ZERO_EL_REDUCELOOP;
2478
 
    }
2479
 
    else if (PyArray_ISBEHAVED_RO(aar) && (otype == (aar)->descr->type_num)) {
2480
 
        if (loop->N == 1) {
2481
 
            loop->meth = ONE_EL_REDUCELOOP;
2482
 
        }
2483
 
        else {
2484
 
            loop->meth = NOBUFFER_UFUNCLOOP;
2485
 
            loop->steps[1] = (aar)->strides[axis];
2486
 
            loop->N -= 1;
2487
 
        }
2488
 
    }
2489
 
    else {
2490
 
        loop->meth = BUFFER_UFUNCLOOP;
2491
 
        loop->swap = !(PyArray_ISNOTSWAPPED(aar));
2492
 
    }
2493
 
 
2494
 
    /* Determine if object arrays are involved */
2495
 
    if (otype == PyArray_OBJECT || aar->descr->type_num == PyArray_OBJECT) {
2496
 
        loop->obj = UFUNC_OBJ_ISOBJECT | UFUNC_OBJ_NEEDS_API;
2497
 
    }
2498
 
    else {
2499
 
        loop->obj = 0;
2500
 
    }
2501
 
    if ((loop->meth == ZERO_EL_REDUCELOOP)
2502
 
            || ((operation == UFUNC_REDUCEAT)
2503
 
                && (loop->meth == BUFFER_UFUNCLOOP))) {
2504
 
        idarr = _getidentity(self, otype, str);
2505
 
        if (idarr == NULL) {
2506
 
            goto fail;
2507
 
        }
2508
 
        if (idarr->descr->elsize > UFUNC_MAXIDENTITY) {
2509
 
            PyErr_Format(PyExc_RuntimeError,
2510
 
                    "UFUNC_MAXIDENTITY (%d) is too small"\
2511
 
                    "(needs to be at least %d)",
2512
 
                    UFUNC_MAXIDENTITY, idarr->descr->elsize);
2513
 
            Py_DECREF(idarr);
2514
 
            goto fail;
2515
 
        }
2516
 
        memcpy(loop->idptr, idarr->data, idarr->descr->elsize);
2517
 
        Py_DECREF(idarr);
2518
 
    }
2519
 
 
2520
 
    /* Construct return array */
2521
 
    flags = NPY_CARRAY | NPY_UPDATEIFCOPY | NPY_FORCECAST;
2522
 
    switch(operation) {
2523
 
    case UFUNC_REDUCE:
2524
 
        for (j = 0, i = 0; i < nd; i++) {
2525
 
            if (i != axis) {
2526
 
                loop_i[j++] = (aar)->dimensions[i];
2527
 
            }
2528
 
        }
2529
 
        if (out == NULL) {
2530
 
            loop->ret = (PyArrayObject *)
2531
 
                PyArray_New(Py_TYPE(aar), aar->nd-1, loop_i,
2532
 
                            otype, NULL, NULL, 0, 0,
2533
 
                            (PyObject *)aar);
2534
 
        }
2535
 
        else {
2536
 
            outsize = PyArray_MultiplyList(loop_i, aar->nd - 1);
2537
 
        }
2538
 
        break;
2539
 
    case UFUNC_ACCUMULATE:
2540
 
        if (out == NULL) {
2541
 
            loop->ret = (PyArrayObject *)
2542
 
                PyArray_New(Py_TYPE(aar), aar->nd, aar->dimensions,
2543
 
                        otype, NULL, NULL, 0, 0, (PyObject *)aar);
2544
 
        }
2545
 
        else {
2546
 
            outsize = PyArray_MultiplyList(aar->dimensions, aar->nd);
2547
 
        }
2548
 
        break;
2549
 
    case UFUNC_REDUCEAT:
2550
 
        memcpy(loop_i, aar->dimensions, nd*sizeof(intp));
2551
 
        /* Index is 1-d array */
2552
 
        loop_i[axis] = ind_size;
2553
 
        if (out == NULL) {
2554
 
            loop->ret = (PyArrayObject *)
2555
 
                PyArray_New(Py_TYPE(aar), aar->nd, loop_i, otype,
2556
 
                        NULL, NULL, 0, 0, (PyObject *)aar);
2557
 
        }
2558
 
        else {
2559
 
            outsize = PyArray_MultiplyList(loop_i, aar->nd);
2560
 
        }
2561
 
        if (ind_size == 0) {
2562
 
            loop->meth = ZERO_EL_REDUCELOOP;
2563
 
            return loop;
2564
 
        }
2565
 
        if (loop->meth == ONE_EL_REDUCELOOP) {
2566
 
            loop->meth = NOBUFFER_REDUCELOOP;
2567
 
        }
2568
 
        break;
2569
 
    }
2570
 
    if (out) {
2571
 
        if (PyArray_SIZE(out) != outsize) {
2572
 
            PyErr_SetString(PyExc_ValueError,
2573
 
                    "wrong shape for output");
2574
 
            goto fail;
2575
 
        }
2576
 
        loop->ret = (PyArrayObject *)
2577
 
            PyArray_FromArray(out, PyArray_DescrFromType(otype), flags);
2578
 
        if (loop->ret && loop->ret != out) {
2579
 
            loop->retbase = 1;
2580
 
        }
2581
 
    }
2582
 
    if (loop->ret == NULL) {
2583
 
        goto fail;
2584
 
    }
2585
 
    loop->insize = aar->descr->elsize;
2586
 
    loop->outsize = loop->ret->descr->elsize;
2587
 
    loop->bufptr[0] = loop->ret->data;
2588
 
 
2589
 
    if (loop->meth == ZERO_EL_REDUCELOOP) {
2590
 
        loop->size = PyArray_SIZE(loop->ret);
2591
 
        return loop;
2592
 
    }
2593
 
 
2594
 
    loop->it = (PyArrayIterObject *)PyArray_IterNew((PyObject *)aar);
2595
 
    if (loop->it == NULL) {
2596
 
        return NULL;
2597
 
    }
2598
 
    if (loop->meth == ONE_EL_REDUCELOOP) {
2599
 
        loop->size = loop->it->size;
2600
 
        return loop;
2601
 
    }
2602
 
 
2603
 
    /*
2604
 
     * Fix iterator to loop over correct dimension
2605
 
     * Set size in axis dimension to 1
2606
 
     */
2607
 
    loop->it->contiguous = 0;
2608
 
    loop->it->size /= (loop->it->dims_m1[axis]+1);
2609
 
    loop->it->dims_m1[axis] = 0;
2610
 
    loop->it->backstrides[axis] = 0;
2611
 
    loop->size = loop->it->size;
 
2920
                     "could not find a matching type for %s.%s, "
 
2921
                     "requested type has type code '%c'",
 
2922
                            ufunc_name, opname, dtype ? dtype->type : '-');
 
2923
        Py_XDECREF(dtype);
 
2924
        goto fail;
 
2925
    }
 
2926
 
 
2927
    ndim = PyArray_NDIM(arr);
 
2928
 
 
2929
    /* Set up the output data type */
 
2930
    op_dtypes[0] = PyArray_DescrFromType(otype_final);
 
2931
    if (op_dtypes[0] == NULL) {
 
2932
        goto fail;
 
2933
    }
 
2934
 
 
2935
#if NPY_UF_DBG_TRACING
 
2936
    printf("Found %s.%s inner loop with dtype :  ", ufunc_name, opname);
 
2937
    PyObject_Print((PyObject *)op_dtypes[0], stdout, 0);
 
2938
    printf("\n");
 
2939
#endif
 
2940
 
 
2941
    /* Set up the op_axes for the outer loop */
2612
2942
    if (operation == UFUNC_REDUCE) {
2613
 
        loop->steps[0] = 0;
 
2943
        for (i = 0, idim = 0; idim < ndim; ++idim) {
 
2944
            if (idim != axis) {
 
2945
                op_axes_arrays[0][i] = i;
 
2946
                op_axes_arrays[1][i] = idim;
 
2947
                i++;
 
2948
            }
 
2949
        }
 
2950
    }
 
2951
    else if (operation == UFUNC_ACCUMULATE) {
 
2952
        for (idim = 0; idim < ndim; ++idim) {
 
2953
            op_axes_arrays[0][idim] = idim;
 
2954
            op_axes_arrays[1][idim] = idim;
 
2955
        }
2614
2956
    }
2615
2957
    else {
2616
 
        loop->rit = (PyArrayIterObject *)                       \
2617
 
            PyArray_IterNew((PyObject *)(loop->ret));
2618
 
        if (loop->rit == NULL) {
2619
 
            return NULL;
2620
 
        }
2621
 
        /*
2622
 
         * Fix iterator to loop over correct dimension
2623
 
         * Set size in axis dimension to 1
2624
 
         */
2625
 
        loop->rit->contiguous = 0;
2626
 
        loop->rit->size /= (loop->rit->dims_m1[axis] + 1);
2627
 
        loop->rit->dims_m1[axis] = 0;
2628
 
        loop->rit->backstrides[axis] = 0;
 
2958
        PyErr_Format(PyExc_RuntimeError,
 
2959
                    "invalid reduction operation %s.%s", ufunc_name, opname);
 
2960
        goto fail;
 
2961
    }
 
2962
 
 
2963
    /* The per-operand flags for the outer loop */
 
2964
    op_flags[0] = NPY_ITER_READWRITE|
 
2965
                  NPY_ITER_NO_BROADCAST|
 
2966
                  NPY_ITER_ALLOCATE|
 
2967
                  NPY_ITER_NO_SUBTYPE;
 
2968
    op_flags[1] = NPY_ITER_READONLY;
 
2969
 
 
2970
    op[0] = out;
 
2971
    op[1] = arr;
 
2972
 
 
2973
    need_outer_iterator = (ndim > 1);
 
2974
    if (operation == UFUNC_ACCUMULATE) {
 
2975
        /* This is because we can't buffer, so must do UPDATEIFCOPY */
 
2976
        if (!PyArray_ISALIGNED(arr) || (out && !PyArray_ISALIGNED(out)) ||
 
2977
                !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(arr)) ||
 
2978
                (out &&
 
2979
                 !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(out)))) {
 
2980
            need_outer_iterator = 1;
 
2981
        }
 
2982
    }
 
2983
 
 
2984
    if (need_outer_iterator) {
 
2985
        int ndim_iter = 0;
 
2986
        npy_uint32 flags = NPY_ITER_ZEROSIZE_OK|
 
2987
                           NPY_ITER_REFS_OK;
 
2988
        PyArray_Descr **op_dtypes_param = NULL;
 
2989
 
 
2990
        if (operation == UFUNC_REDUCE) {
 
2991
            ndim_iter = ndim - 1;
 
2992
            if (out == NULL) {
 
2993
                op_dtypes_param = op_dtypes;
 
2994
            }
 
2995
        }
 
2996
        else if (operation == UFUNC_ACCUMULATE) {
 
2997
            /*
 
2998
             * The way accumulate is set up, we can't do buffering,
 
2999
             * so make a copy instead when necessary.
 
3000
             */
 
3001
            ndim_iter = ndim;
 
3002
            flags |= NPY_ITER_MULTI_INDEX;
 
3003
            /* Add some more flags */
 
3004
            op_flags[0] |= NPY_ITER_UPDATEIFCOPY|NPY_ITER_ALIGNED;
 
3005
            op_flags[1] |= NPY_ITER_COPY|NPY_ITER_ALIGNED;
 
3006
            op_dtypes_param = op_dtypes;
 
3007
            op_dtypes[1] = op_dtypes[0];
 
3008
        }
 
3009
        NPY_UF_DBG_PRINT("Allocating outer iterator\n");
 
3010
        iter = NpyIter_AdvancedNew(2, op, flags,
 
3011
                                   NPY_KEEPORDER, NPY_UNSAFE_CASTING,
 
3012
                                   op_flags,
 
3013
                                   op_dtypes_param,
 
3014
                                   ndim_iter, op_axes, NULL, 0);
 
3015
        if (iter == NULL) {
 
3016
            goto fail;
 
3017
        }
2629
3018
 
2630
3019
        if (operation == UFUNC_ACCUMULATE) {
2631
 
            loop->steps[0] = loop->ret->strides[axis];
2632
 
        }
2633
 
        else {
2634
 
            loop->steps[0] = 0;
2635
 
        }
2636
 
    }
2637
 
    loop->steps[2] = loop->steps[0];
2638
 
    loop->bufptr[2] = loop->bufptr[0] + loop->steps[2];
2639
 
    if (loop->meth == BUFFER_UFUNCLOOP) {
2640
 
        int _size;
2641
 
 
2642
 
        loop->steps[1] = loop->outsize;
2643
 
        if (otype != aar->descr->type_num) {
2644
 
            _size=loop->bufsize*(loop->outsize + aar->descr->elsize);
2645
 
            loop->buffer = PyDataMem_NEW(_size);
2646
 
            if (loop->buffer == NULL) {
2647
 
                goto fail;
2648
 
            }
2649
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2650
 
                memset(loop->buffer, 0, _size);
2651
 
            }
2652
 
            loop->castbuf = loop->buffer + loop->bufsize*aar->descr->elsize;
2653
 
            loop->bufptr[1] = loop->castbuf;
2654
 
            loop->cast = PyArray_GetCastFunc(aar->descr, otype);
2655
 
            if (loop->cast == NULL) {
2656
 
                goto fail;
2657
 
            }
2658
 
        }
2659
 
        else {
2660
 
            _size = loop->bufsize * loop->outsize;
2661
 
            loop->buffer = PyDataMem_NEW(_size);
2662
 
            if (loop->buffer == NULL) {
2663
 
                goto fail;
2664
 
            }
2665
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2666
 
                memset(loop->buffer, 0, _size);
2667
 
            }
2668
 
            loop->bufptr[1] = loop->buffer;
2669
 
        }
2670
 
    }
2671
 
    PyUFunc_clearfperr();
2672
 
    return loop;
2673
 
 
2674
 
 fail:
2675
 
    ufuncreduce_dealloc(loop);
 
3020
            /* In case COPY or UPDATEIFCOPY occurred */
 
3021
            op[0] = NpyIter_GetOperandArray(iter)[0];
 
3022
            op[1] = NpyIter_GetOperandArray(iter)[1];
 
3023
 
 
3024
            if (PyArray_SIZE(op[0]) == 0) {
 
3025
                if (out == NULL) {
 
3026
                    out = op[0];
 
3027
                    Py_INCREF(out);
 
3028
                }
 
3029
                goto finish;
 
3030
            }
 
3031
 
 
3032
            if (NpyIter_RemoveAxis(iter, axis) != NPY_SUCCEED) {
 
3033
                goto fail;
 
3034
            }
 
3035
            if (NpyIter_RemoveMultiIndex(iter) != NPY_SUCCEED) {
 
3036
                goto fail;
 
3037
            }
 
3038
        }
 
3039
    }
 
3040
 
 
3041
    /* Get the output */
 
3042
    if (out == NULL) {
 
3043
        if (iter) {
 
3044
            op[0] = out = NpyIter_GetOperandArray(iter)[0];
 
3045
            Py_INCREF(out);
 
3046
        }
 
3047
        else {
 
3048
            PyArray_Descr *dtype = op_dtypes[0];
 
3049
            Py_INCREF(dtype);
 
3050
            if (operation == UFUNC_REDUCE) {
 
3051
                op[0] = out = (PyArrayObject *)PyArray_NewFromDescr(
 
3052
                                        &PyArray_Type, dtype,
 
3053
                                        0, NULL, NULL, NULL,
 
3054
                                        0, NULL);
 
3055
            }
 
3056
            else if (operation == UFUNC_ACCUMULATE) {
 
3057
                op[0] = out = (PyArrayObject *)PyArray_NewFromDescr(
 
3058
                                        &PyArray_Type, dtype,
 
3059
                                        ndim, PyArray_DIMS(op[1]), NULL, NULL,
 
3060
                                        0, NULL);
 
3061
            }
 
3062
            if (out == NULL) {
 
3063
                goto fail;
 
3064
            }
 
3065
        }
 
3066
    }
 
3067
 
 
3068
    /*
 
3069
     * If the reduction unit has size zero, either return the reduction
 
3070
     * unit for UFUNC_REDUCE, or return the zero-sized output array
 
3071
     * for UFUNC_ACCUMULATE.
 
3072
     */
 
3073
    if (PyArray_DIM(op[1], axis) == 0) {
 
3074
        if (operation == UFUNC_REDUCE) {
 
3075
            if (self->identity == PyUFunc_None) {
 
3076
                PyErr_Format(PyExc_ValueError,
 
3077
                             "zero-size array to %s.%s "
 
3078
                             "without identity", ufunc_name, opname);
 
3079
                goto fail;
 
3080
            }
 
3081
            if (self->identity == PyUFunc_One) {
 
3082
                PyObject *obj = PyInt_FromLong((long) 1);
 
3083
                if (obj == NULL) {
 
3084
                    goto fail;
 
3085
                }
 
3086
                PyArray_FillWithScalar(op[0], obj);
 
3087
                Py_DECREF(obj);
 
3088
            } else {
 
3089
                PyObject *obj = PyInt_FromLong((long) 0);
 
3090
                if (obj == NULL) {
 
3091
                    goto fail;
 
3092
                }
 
3093
                PyArray_FillWithScalar(op[0], obj);
 
3094
                Py_DECREF(obj);
 
3095
            }
 
3096
        }
 
3097
 
 
3098
        goto finish;
 
3099
    }
 
3100
    else if (PyArray_SIZE(op[0]) == 0) {
 
3101
        goto finish;
 
3102
    }
 
3103
 
 
3104
    /* Only allocate an inner iterator if it's necessary */
 
3105
    if (!PyArray_ISALIGNED(op[1]) || !PyArray_ISALIGNED(op[0]) ||
 
3106
                !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(op[1])) ||
 
3107
                !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(op[0]))) {
 
3108
        /* Also set the dtype for buffering arr */
 
3109
        op_dtypes[1] = op_dtypes[0];
 
3110
 
 
3111
        NPY_UF_DBG_PRINT("Allocating inner iterator\n");
 
3112
        if (operation == UFUNC_REDUCE) {
 
3113
            /* The per-operand flags for the inner loop */
 
3114
            op_flags[0] = NPY_ITER_READWRITE|
 
3115
                          NPY_ITER_ALIGNED;
 
3116
            op_flags[1] = NPY_ITER_READONLY|
 
3117
                          NPY_ITER_ALIGNED;
 
3118
 
 
3119
            op_axes[0][0] = -1;
 
3120
            op_axes[1][0] = axis;
 
3121
 
 
3122
            iter_inner = NpyIter_AdvancedNew(2, op, NPY_ITER_EXTERNAL_LOOP|
 
3123
                                       NPY_ITER_BUFFERED|
 
3124
                                       NPY_ITER_DELAY_BUFALLOC|
 
3125
                                       NPY_ITER_GROWINNER|
 
3126
                                       NPY_ITER_REDUCE_OK|
 
3127
                                       NPY_ITER_REFS_OK,
 
3128
                                       NPY_CORDER, NPY_UNSAFE_CASTING,
 
3129
                                       op_flags, op_dtypes,
 
3130
                                       1, op_axes, NULL, buffersize);
 
3131
        }
 
3132
        /* Should never get an inner iterator for ACCUMULATE */
 
3133
        else {
 
3134
            PyErr_SetString(PyExc_RuntimeError,
 
3135
                "internal ufunc reduce error, should not need inner iterator");
 
3136
            goto fail;
 
3137
        }
 
3138
        if (iter_inner == NULL) {
 
3139
            goto fail;
 
3140
        }
 
3141
    }
 
3142
 
 
3143
    if (iter && NpyIter_GetIterSize(iter) != 0) {
 
3144
        char *dataptr_copy[3];
 
3145
        npy_intp stride_copy[3];
 
3146
 
 
3147
        NpyIter_IterNextFunc *iternext;
 
3148
        char **dataptr;
 
3149
 
 
3150
        int itemsize = op_dtypes[0]->elsize;
 
3151
 
 
3152
        /* Get the variables needed for the loop */
 
3153
        iternext = NpyIter_GetIterNext(iter, NULL);
 
3154
        if (iternext == NULL) {
 
3155
            goto fail;
 
3156
        }
 
3157
        dataptr = NpyIter_GetDataPtrArray(iter);
 
3158
 
 
3159
 
 
3160
        /* Execute the loop with two nested iterators */
 
3161
        if (iter_inner) {
 
3162
            /* Only UFUNC_REDUCE uses iter_inner */
 
3163
            NpyIter_IterNextFunc *iternext_inner;
 
3164
            char **dataptr_inner;
 
3165
            npy_intp *stride_inner;
 
3166
            npy_intp count, *count_ptr_inner;
 
3167
 
 
3168
            NPY_UF_DBG_PRINT("UFunc: Reduce loop with two nested iterators\n");
 
3169
            iternext_inner = NpyIter_GetIterNext(iter_inner, NULL);
 
3170
            if (iternext_inner == NULL) {
 
3171
                goto fail;
 
3172
            }
 
3173
            dataptr_inner = NpyIter_GetDataPtrArray(iter_inner);
 
3174
            stride_inner = NpyIter_GetInnerStrideArray(iter_inner);
 
3175
            count_ptr_inner = NpyIter_GetInnerLoopSizePtr(iter_inner);
 
3176
 
 
3177
            needs_api = NpyIter_IterationNeedsAPI(iter) ||
 
3178
                        NpyIter_IterationNeedsAPI(iter_inner);
 
3179
 
 
3180
            if (!needs_api) {
 
3181
                NPY_BEGIN_THREADS;
 
3182
            }
 
3183
 
 
3184
            do {
 
3185
                int first = 1;
 
3186
 
 
3187
                /* Reset the inner iterator to the outer's data */
 
3188
                if (NpyIter_ResetBasePointers(iter_inner, dataptr, NULL)
 
3189
                                                != NPY_SUCCEED) {
 
3190
                    goto fail;
 
3191
                }
 
3192
 
 
3193
                /* Copy the first element to start the reduction */
 
3194
                if (otype == NPY_OBJECT) {
 
3195
                    Py_XDECREF(*(PyObject **)dataptr_inner[0]);
 
3196
                    *(PyObject **)dataptr_inner[0] =
 
3197
                                        *(PyObject **)dataptr_inner[1];
 
3198
                    Py_XINCREF(*(PyObject **)dataptr_inner[0]);
 
3199
                }
 
3200
                else {
 
3201
                    memcpy(dataptr_inner[0], dataptr_inner[1], itemsize);
 
3202
                }
 
3203
 
 
3204
                stride_copy[0] = 0;
 
3205
                stride_copy[2] = 0;
 
3206
                do {
 
3207
                    count = *count_ptr_inner;
 
3208
                    /* Turn the two items into three for the inner loop */
 
3209
                    dataptr_copy[0] = dataptr_inner[0];
 
3210
                    dataptr_copy[1] = dataptr_inner[1];
 
3211
                    dataptr_copy[2] = dataptr_inner[0];
 
3212
                    if (first) {
 
3213
                        --count;
 
3214
                        dataptr_copy[1] += stride_inner[1];
 
3215
                        first = 0;
 
3216
                    }
 
3217
                    stride_copy[1] = stride_inner[1];
 
3218
                    NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count);
 
3219
                    innerloop(dataptr_copy, &count,
 
3220
                                stride_copy, innerloopdata);
 
3221
                } while(iternext_inner(iter_inner));
 
3222
            } while (iternext(iter));
 
3223
 
 
3224
            if (!needs_api) {
 
3225
                NPY_END_THREADS;
 
3226
            }
 
3227
        }
 
3228
        /* Execute the loop with just the outer iterator */
 
3229
        else {
 
3230
            npy_intp count_m1 = PyArray_DIM(op[1], axis)-1;
 
3231
            npy_intp stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis);
 
3232
 
 
3233
            NPY_UF_DBG_PRINT("UFunc: Reduce loop with just outer iterator\n");
 
3234
 
 
3235
            if (operation == UFUNC_ACCUMULATE) {
 
3236
                stride0 = PyArray_STRIDE(op[0], axis);
 
3237
            }
 
3238
 
 
3239
            stride_copy[0] = stride0;
 
3240
            stride_copy[1] = stride1;
 
3241
            stride_copy[2] = stride0;
 
3242
 
 
3243
            needs_api = NpyIter_IterationNeedsAPI(iter);
 
3244
 
 
3245
            if (!needs_api) {
 
3246
                NPY_BEGIN_THREADS;
 
3247
            }
 
3248
 
 
3249
            do {
 
3250
 
 
3251
                dataptr_copy[0] = dataptr[0];
 
3252
                dataptr_copy[1] = dataptr[1];
 
3253
                dataptr_copy[2] = dataptr[0];
 
3254
 
 
3255
                /* Copy the first element to start the reduction */
 
3256
                if (otype == NPY_OBJECT) {
 
3257
                    Py_XDECREF(*(PyObject **)dataptr_copy[0]);
 
3258
                    *(PyObject **)dataptr_copy[0] =
 
3259
                                        *(PyObject **)dataptr_copy[1];
 
3260
                    Py_XINCREF(*(PyObject **)dataptr_copy[0]);
 
3261
                }
 
3262
                else {
 
3263
                    memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
 
3264
                }
 
3265
 
 
3266
                if (count_m1 > 0) {
 
3267
                    /* Turn the two items into three for the inner loop */
 
3268
                    if (operation == UFUNC_REDUCE) {
 
3269
                        dataptr_copy[1] += stride1;
 
3270
                    }
 
3271
                    else if (operation == UFUNC_ACCUMULATE) {
 
3272
                        dataptr_copy[1] += stride1;
 
3273
                        dataptr_copy[2] += stride0;
 
3274
                    }
 
3275
                    NPY_UF_DBG_PRINT1("iterator loop count %d\n",
 
3276
                                                    (int)count_m1);
 
3277
                    innerloop(dataptr_copy, &count_m1,
 
3278
                                stride_copy, innerloopdata);
 
3279
                }
 
3280
            } while (iternext(iter));
 
3281
 
 
3282
            if (!needs_api) {
 
3283
                NPY_END_THREADS;
 
3284
            }
 
3285
        }
 
3286
    }
 
3287
    else if (iter == NULL) {
 
3288
        char *dataptr_copy[3];
 
3289
        npy_intp stride_copy[3];
 
3290
 
 
3291
        int itemsize = op_dtypes[0]->elsize;
 
3292
 
 
3293
        /* Execute the loop with just the inner iterator */
 
3294
        if (iter_inner) {
 
3295
            /* Only UFUNC_REDUCE uses iter_inner */
 
3296
            NpyIter_IterNextFunc *iternext_inner;
 
3297
            char **dataptr_inner;
 
3298
            npy_intp *stride_inner;
 
3299
            npy_intp count, *count_ptr_inner;
 
3300
            int first = 1;
 
3301
 
 
3302
            NPY_UF_DBG_PRINT("UFunc: Reduce loop with just inner iterator\n");
 
3303
 
 
3304
            iternext_inner = NpyIter_GetIterNext(iter_inner, NULL);
 
3305
            if (iternext_inner == NULL) {
 
3306
                goto fail;
 
3307
            }
 
3308
            dataptr_inner = NpyIter_GetDataPtrArray(iter_inner);
 
3309
            stride_inner = NpyIter_GetInnerStrideArray(iter_inner);
 
3310
            count_ptr_inner = NpyIter_GetInnerLoopSizePtr(iter_inner);
 
3311
 
 
3312
            /* Reset the inner iterator to prepare the buffers */
 
3313
            if (NpyIter_Reset(iter_inner, NULL) != NPY_SUCCEED) {
 
3314
                goto fail;
 
3315
            }
 
3316
 
 
3317
            needs_api = NpyIter_IterationNeedsAPI(iter_inner);
 
3318
 
 
3319
            if (!needs_api) {
 
3320
                NPY_BEGIN_THREADS;
 
3321
            }
 
3322
 
 
3323
            /* Copy the first element to start the reduction */
 
3324
            if (otype == NPY_OBJECT) {
 
3325
                Py_XDECREF(*(PyObject **)dataptr_inner[0]);
 
3326
                *(PyObject **)dataptr_inner[0] =
 
3327
                                    *(PyObject **)dataptr_inner[1];
 
3328
                Py_XINCREF(*(PyObject **)dataptr_inner[0]);
 
3329
            }
 
3330
            else {
 
3331
                memcpy(dataptr_inner[0], dataptr_inner[1], itemsize);
 
3332
            }
 
3333
 
 
3334
            stride_copy[0] = 0;
 
3335
            stride_copy[2] = 0;
 
3336
            do {
 
3337
                count = *count_ptr_inner;
 
3338
                /* Turn the two items into three for the inner loop */
 
3339
                dataptr_copy[0] = dataptr_inner[0];
 
3340
                dataptr_copy[1] = dataptr_inner[1];
 
3341
                dataptr_copy[2] = dataptr_inner[0];
 
3342
                if (first) {
 
3343
                    --count;
 
3344
                    dataptr_copy[1] += stride_inner[1];
 
3345
                    first = 0;
 
3346
                }
 
3347
                stride_copy[1] = stride_inner[1];
 
3348
                NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count);
 
3349
                innerloop(dataptr_copy, &count,
 
3350
                            stride_copy, innerloopdata);
 
3351
            } while(iternext_inner(iter_inner));
 
3352
 
 
3353
            if (!needs_api) {
 
3354
                NPY_END_THREADS;
 
3355
            }
 
3356
        }
 
3357
        /* Execute the loop with no iterators */
 
3358
        else {
 
3359
            npy_intp count = PyArray_DIM(op[1], axis);
 
3360
            npy_intp stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis);
 
3361
 
 
3362
            NPY_UF_DBG_PRINT("UFunc: Reduce loop with no iterators\n");
 
3363
 
 
3364
            if (operation == UFUNC_REDUCE) {
 
3365
                if (PyArray_NDIM(op[0]) != 0) {
 
3366
                    PyErr_SetString(PyExc_ValueError,
 
3367
                            "provided out is the wrong size "
 
3368
                            "for the reduction");
 
3369
                    goto fail;
 
3370
                }
 
3371
            }
 
3372
            else if (operation == UFUNC_ACCUMULATE) {
 
3373
                if (PyArray_NDIM(op[0]) != PyArray_NDIM(op[1]) ||
 
3374
                        !PyArray_CompareLists(PyArray_DIMS(op[0]),
 
3375
                                              PyArray_DIMS(op[1]),
 
3376
                                              PyArray_NDIM(op[0]))) {
 
3377
                    PyErr_SetString(PyExc_ValueError,
 
3378
                            "provided out is the wrong size "
 
3379
                            "for the reduction");
 
3380
                    goto fail;
 
3381
                }
 
3382
                stride0 = PyArray_STRIDE(op[0], axis);
 
3383
            }
 
3384
 
 
3385
            stride_copy[0] = stride0;
 
3386
            stride_copy[1] = stride1;
 
3387
            stride_copy[2] = stride0;
 
3388
 
 
3389
            /* Turn the two items into three for the inner loop */
 
3390
            dataptr_copy[0] = PyArray_BYTES(op[0]);
 
3391
            dataptr_copy[1] = PyArray_BYTES(op[1]);
 
3392
            dataptr_copy[2] = PyArray_BYTES(op[0]);
 
3393
 
 
3394
            /* Copy the first element to start the reduction */
 
3395
            if (otype == NPY_OBJECT) {
 
3396
                Py_XDECREF(*(PyObject **)dataptr_copy[0]);
 
3397
                *(PyObject **)dataptr_copy[0] =
 
3398
                                    *(PyObject **)dataptr_copy[1];
 
3399
                Py_XINCREF(*(PyObject **)dataptr_copy[0]);
 
3400
            }
 
3401
            else {
 
3402
                memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
 
3403
            }
 
3404
 
 
3405
            if (count > 1) {
 
3406
                --count;
 
3407
                if (operation == UFUNC_REDUCE) {
 
3408
                    dataptr_copy[1] += stride1;
 
3409
                }
 
3410
                else if (operation == UFUNC_ACCUMULATE) {
 
3411
                    dataptr_copy[1] += stride1;
 
3412
                    dataptr_copy[2] += stride0;
 
3413
                }
 
3414
 
 
3415
                NPY_UF_DBG_PRINT1("iterator loop count %d\n", (int)count);
 
3416
 
 
3417
                needs_api = PyDataType_REFCHK(op_dtypes[0]);
 
3418
 
 
3419
                if (!needs_api) {
 
3420
                    NPY_BEGIN_THREADS;
 
3421
                }
 
3422
 
 
3423
                innerloop(dataptr_copy, &count,
 
3424
                            stride_copy, innerloopdata);
 
3425
 
 
3426
                if (!needs_api) {
 
3427
                    NPY_END_THREADS;
 
3428
                }
 
3429
            }
 
3430
        }
 
3431
    }
 
3432
 
 
3433
finish:
 
3434
    Py_XDECREF(op_dtypes[0]);
 
3435
    if (iter != NULL) {
 
3436
        NpyIter_Deallocate(iter);
 
3437
    }
 
3438
    if (iter_inner != NULL) {
 
3439
        NpyIter_Deallocate(iter_inner);
 
3440
    }
 
3441
 
 
3442
    Py_XDECREF(errobj);
 
3443
 
 
3444
    return (PyObject *)out;
 
3445
 
 
3446
fail:
 
3447
    Py_XDECREF(out);
 
3448
    Py_XDECREF(op_dtypes[0]);
 
3449
 
 
3450
    if (iter != NULL) {
 
3451
        NpyIter_Deallocate(iter);
 
3452
    }
 
3453
    if (iter_inner != NULL) {
 
3454
        NpyIter_Deallocate(iter_inner);
 
3455
    }
 
3456
 
 
3457
    Py_XDECREF(errobj);
 
3458
 
2676
3459
    return NULL;
2677
3460
}
2678
3461
 
2679
 
 
2680
3462
/*
2681
3463
 * We have two basic kinds of loops. One is used when arr is not-swapped
2682
3464
 * and aligned and output type is the same as input type.  The other uses
2688
3470
PyUFunc_Reduce(PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out,
2689
3471
        int axis, int otype)
2690
3472
{
2691
 
    PyArrayObject *ret = NULL;
2692
 
    PyUFuncReduceObject *loop;
2693
 
    intp i, n;
2694
 
    char *dptr;
2695
 
    NPY_BEGIN_THREADS_DEF;
2696
 
 
2697
 
    /* Construct loop object */
2698
 
    loop = construct_reduce(self, &arr, out, axis, otype, UFUNC_REDUCE, 0,
2699
 
            "reduce");
2700
 
    if (!loop) {
2701
 
        return NULL;
2702
 
    }
2703
 
 
2704
 
    NPY_LOOP_BEGIN_THREADS;
2705
 
    switch(loop->meth) {
2706
 
    case ZERO_EL_REDUCELOOP:
2707
 
        /* fprintf(stderr, "ZERO..%d\n", loop->size); */
2708
 
        for (i = 0; i < loop->size; i++) {
2709
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2710
 
                Py_INCREF(*((PyObject **)loop->idptr));
2711
 
            }
2712
 
            memmove(loop->bufptr[0], loop->idptr, loop->outsize);
2713
 
            loop->bufptr[0] += loop->outsize;
2714
 
        }
2715
 
        break;
2716
 
    case ONE_EL_REDUCELOOP:
2717
 
        /*fprintf(stderr, "ONEDIM..%d\n", loop->size); */
2718
 
        while (loop->index < loop->size) {
2719
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2720
 
                Py_INCREF(*((PyObject **)loop->it->dataptr));
2721
 
            }
2722
 
            memmove(loop->bufptr[0], loop->it->dataptr, loop->outsize);
2723
 
            PyArray_ITER_NEXT(loop->it);
2724
 
            loop->bufptr[0] += loop->outsize;
2725
 
            loop->index++;
2726
 
        }
2727
 
        break;
2728
 
    case NOBUFFER_UFUNCLOOP:
2729
 
        /*fprintf(stderr, "NOBUFFER..%d\n", loop->size); */
2730
 
        while (loop->index < loop->size) {
2731
 
            /* Copy first element to output */
2732
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2733
 
                Py_INCREF(*((PyObject **)loop->it->dataptr));
2734
 
            }
2735
 
            memmove(loop->bufptr[0], loop->it->dataptr, loop->outsize);
2736
 
            /* Adjust input pointer */
2737
 
            loop->bufptr[1] = loop->it->dataptr+loop->steps[1];
2738
 
            loop->function((char **)loop->bufptr, &(loop->N),
2739
 
                    loop->steps, loop->funcdata);
2740
 
            UFUNC_CHECK_ERROR(loop);
2741
 
            PyArray_ITER_NEXT(loop->it);
2742
 
            loop->bufptr[0] += loop->outsize;
2743
 
            loop->bufptr[2] = loop->bufptr[0];
2744
 
            loop->index++;
2745
 
        }
2746
 
        break;
2747
 
    case BUFFER_UFUNCLOOP:
2748
 
        /*
2749
 
         * use buffer for arr
2750
 
         *
2751
 
         * For each row to reduce
2752
 
         * 1. copy first item over to output (casting if necessary)
2753
 
         * 2. Fill inner buffer
2754
 
         * 3. When buffer is filled or end of row
2755
 
         * a. Cast input buffers if needed
2756
 
         * b. Call inner function.
2757
 
         * 4. Repeat 2 until row is done.
2758
 
         */
2759
 
        /* fprintf(stderr, "BUFFERED..%d %d\n", loop->size, loop->swap); */
2760
 
        while(loop->index < loop->size) {
2761
 
            loop->inptr = loop->it->dataptr;
2762
 
            /* Copy (cast) First term over to output */
2763
 
            if (loop->cast) {
2764
 
                /* A little tricky because we need to cast it first */
2765
 
                arr->descr->f->copyswap(loop->buffer, loop->inptr,
2766
 
                        loop->swap, NULL);
2767
 
                loop->cast(loop->buffer, loop->castbuf, 1, NULL, NULL);
2768
 
                if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2769
 
                    Py_XINCREF(*((PyObject **)loop->castbuf));
2770
 
                }
2771
 
                memcpy(loop->bufptr[0], loop->castbuf, loop->outsize);
2772
 
            }
2773
 
            else {
2774
 
                /* Simple copy */
2775
 
                arr->descr->f->copyswap(loop->bufptr[0], loop->inptr,
2776
 
                        loop->swap, NULL);
2777
 
            }
2778
 
            loop->inptr += loop->instrides;
2779
 
            n = 1;
2780
 
            while(n < loop->N) {
2781
 
                /* Copy up to loop->bufsize elements to buffer */
2782
 
                dptr = loop->buffer;
2783
 
                for (i = 0; i < loop->bufsize; i++, n++) {
2784
 
                    if (n == loop->N) {
2785
 
                        break;
2786
 
                    }
2787
 
                    arr->descr->f->copyswap(dptr, loop->inptr,
2788
 
                            loop->swap, NULL);
2789
 
                    loop->inptr += loop->instrides;
2790
 
                    dptr += loop->insize;
2791
 
                }
2792
 
                if (loop->cast) {
2793
 
                    loop->cast(loop->buffer, loop->castbuf, i, NULL, NULL);
2794
 
                }
2795
 
                loop->function((char **)loop->bufptr, &i,
2796
 
                        loop->steps, loop->funcdata);
2797
 
                loop->bufptr[0] += loop->steps[0]*i;
2798
 
                loop->bufptr[2] += loop->steps[2]*i;
2799
 
                UFUNC_CHECK_ERROR(loop);
2800
 
            }
2801
 
            PyArray_ITER_NEXT(loop->it);
2802
 
            loop->bufptr[0] += loop->outsize;
2803
 
            loop->bufptr[2] = loop->bufptr[0];
2804
 
            loop->index++;
2805
 
        }
2806
 
 
2807
 
        /*
2808
 
         * DECREF left-over objects if buffering was used.
2809
 
         * It is needed when casting created new objects in
2810
 
         * castbuf.  Intermediate copying into castbuf (via
2811
 
         * loop->function) decref'd what was already there.
2812
 
 
2813
 
         * It's the final copy into the castbuf that needs a DECREF.
2814
 
         */
2815
 
 
2816
 
        /* Only when casting needed and it is from a non-object array */
2817
 
        if ((loop->obj & UFUNC_OBJ_ISOBJECT) && loop->cast &&
2818
 
            (!PyArray_ISOBJECT(arr))) {
2819
 
            for (i=0; i<loop->bufsize; i++) {
2820
 
                Py_CLEAR(((PyObject **)loop->castbuf)[i]);
2821
 
            }
2822
 
        }
2823
 
 
2824
 
    }
2825
 
    NPY_LOOP_END_THREADS;
2826
 
    /* Hang on to this reference -- will be decref'd with loop */
2827
 
    if (loop->retbase) {
2828
 
        ret = (PyArrayObject *)loop->ret->base;
2829
 
    }
2830
 
    else {
2831
 
        ret = loop->ret;
2832
 
    }
2833
 
    Py_INCREF(ret);
2834
 
    ufuncreduce_dealloc(loop);
2835
 
    return (PyObject *)ret;
2836
 
 
2837
 
fail:
2838
 
    NPY_LOOP_END_THREADS;
2839
 
    if (loop) {
2840
 
        ufuncreduce_dealloc(loop);
2841
 
    }
2842
 
    return NULL;
 
3473
    return PyUFunc_ReductionOp(self, arr, out, axis, otype,
 
3474
                                UFUNC_REDUCE, "reduce");
2843
3475
}
2844
3476
 
2845
3477
 
2847
3479
PyUFunc_Accumulate(PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out,
2848
3480
                   int axis, int otype)
2849
3481
{
2850
 
    PyArrayObject *ret = NULL;
2851
 
    PyUFuncReduceObject *loop;
2852
 
    intp i, n;
2853
 
    char *dptr;
2854
 
    NPY_BEGIN_THREADS_DEF;
2855
 
 
2856
 
    /* Construct loop object */
2857
 
    loop = construct_reduce(self, &arr, out, axis, otype,
2858
 
            UFUNC_ACCUMULATE, 0, "accumulate");
2859
 
    if (!loop) {
2860
 
        return NULL;
2861
 
    }
2862
 
 
2863
 
    NPY_LOOP_BEGIN_THREADS;
2864
 
    switch(loop->meth) {
2865
 
    case ZERO_EL_REDUCELOOP:
2866
 
        /* Accumulate */
2867
 
        /* fprintf(stderr, "ZERO..%d\n", loop->size); */
2868
 
        for (i = 0; i < loop->size; i++) {
2869
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2870
 
                Py_INCREF(*((PyObject **)loop->idptr));
2871
 
            }
2872
 
            memcpy(loop->bufptr[0], loop->idptr, loop->outsize);
2873
 
            loop->bufptr[0] += loop->outsize;
2874
 
        }
2875
 
        break;
2876
 
    case ONE_EL_REDUCELOOP:
2877
 
        /* Accumulate */
2878
 
        /* fprintf(stderr, "ONEDIM..%d\n", loop->size); */
2879
 
        while (loop->index < loop->size) {
2880
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2881
 
                Py_INCREF(*((PyObject **)loop->it->dataptr));
2882
 
            }
2883
 
            memmove(loop->bufptr[0], loop->it->dataptr, loop->outsize);
2884
 
            PyArray_ITER_NEXT(loop->it);
2885
 
            loop->bufptr[0] += loop->outsize;
2886
 
            loop->index++;
2887
 
        }
2888
 
        break;
2889
 
    case NOBUFFER_UFUNCLOOP:
2890
 
        /* Accumulate */
2891
 
        /* fprintf(stderr, "NOBUFFER..%d\n", loop->size); */
2892
 
        while (loop->index < loop->size) {
2893
 
            /* Copy first element to output */
2894
 
            if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2895
 
                Py_INCREF(*((PyObject **)loop->it->dataptr));
2896
 
            }
2897
 
            memmove(loop->bufptr[0], loop->it->dataptr, loop->outsize);
2898
 
            /* Adjust input pointer */
2899
 
            loop->bufptr[1] = loop->it->dataptr + loop->steps[1];
2900
 
            loop->function((char **)loop->bufptr, &(loop->N),
2901
 
                           loop->steps, loop->funcdata);
2902
 
            UFUNC_CHECK_ERROR(loop);
2903
 
            PyArray_ITER_NEXT(loop->it);
2904
 
            PyArray_ITER_NEXT(loop->rit);
2905
 
            loop->bufptr[0] = loop->rit->dataptr;
2906
 
            loop->bufptr[2] = loop->bufptr[0] + loop->steps[0];
2907
 
            loop->index++;
2908
 
        }
2909
 
        break;
2910
 
    case BUFFER_UFUNCLOOP:
2911
 
        /* Accumulate
2912
 
         *
2913
 
         * use buffer for arr
2914
 
         *
2915
 
         * For each row to reduce
2916
 
         * 1. copy identity over to output (casting if necessary)
2917
 
         * 2. Fill inner buffer
2918
 
         * 3. When buffer is filled or end of row
2919
 
         * a. Cast input buffers if needed
2920
 
         * b. Call inner function.
2921
 
         * 4. Repeat 2 until row is done.
2922
 
         */
2923
 
        /* fprintf(stderr, "BUFFERED..%d %p\n", loop->size, loop->cast); */
2924
 
        while (loop->index < loop->size) {
2925
 
            loop->inptr = loop->it->dataptr;
2926
 
            /* Copy (cast) First term over to output */
2927
 
            if (loop->cast) {
2928
 
                /* A little tricky because we need to
2929
 
                   cast it first */
2930
 
                arr->descr->f->copyswap(loop->buffer, loop->inptr,
2931
 
                                        loop->swap, NULL);
2932
 
                loop->cast(loop->buffer, loop->castbuf, 1, NULL, NULL);
2933
 
                if (loop->obj & UFUNC_OBJ_ISOBJECT) {
2934
 
                    Py_XINCREF(*((PyObject **)loop->castbuf));
2935
 
                }
2936
 
                memcpy(loop->bufptr[0], loop->castbuf, loop->outsize);
2937
 
            }
2938
 
            else {
2939
 
                /* Simple copy */
2940
 
                arr->descr->f->copyswap(loop->bufptr[0], loop->inptr,
2941
 
                                        loop->swap, NULL);
2942
 
            }
2943
 
            loop->inptr += loop->instrides;
2944
 
            n = 1;
2945
 
            while (n < loop->N) {
2946
 
                /* Copy up to loop->bufsize elements to buffer */
2947
 
                dptr = loop->buffer;
2948
 
                for (i = 0; i < loop->bufsize; i++, n++) {
2949
 
                    if (n == loop->N) {
2950
 
                        break;
2951
 
                    }
2952
 
                    arr->descr->f->copyswap(dptr, loop->inptr,
2953
 
                                            loop->swap, NULL);
2954
 
                    loop->inptr += loop->instrides;
2955
 
                    dptr += loop->insize;
2956
 
                }
2957
 
                if (loop->cast) {
2958
 
                    loop->cast(loop->buffer, loop->castbuf, i, NULL, NULL);
2959
 
                }
2960
 
                loop->function((char **)loop->bufptr, &i,
2961
 
                               loop->steps, loop->funcdata);
2962
 
                loop->bufptr[0] += loop->steps[0]*i;
2963
 
                loop->bufptr[2] += loop->steps[2]*i;
2964
 
                UFUNC_CHECK_ERROR(loop);
2965
 
            }
2966
 
            PyArray_ITER_NEXT(loop->it);
2967
 
            PyArray_ITER_NEXT(loop->rit);
2968
 
            loop->bufptr[0] = loop->rit->dataptr;
2969
 
            loop->bufptr[2] = loop->bufptr[0] + loop->steps[0];
2970
 
            loop->index++;
2971
 
        }
2972
 
 
2973
 
        /*
2974
 
         * DECREF left-over objects if buffering was used.
2975
 
         * It is needed when casting created new objects in
2976
 
         * castbuf.  Intermediate copying into castbuf (via
2977
 
         * loop->function) decref'd what was already there.
2978
 
 
2979
 
         * It's the final copy into the castbuf that needs a DECREF.
2980
 
         */
2981
 
 
2982
 
        /* Only when casting needed and it is from a non-object array */
2983
 
        if ((loop->obj & UFUNC_OBJ_ISOBJECT) && loop->cast &&
2984
 
            (!PyArray_ISOBJECT(arr))) {
2985
 
            for (i=0; i<loop->bufsize; i++) {
2986
 
                Py_CLEAR(((PyObject **)loop->castbuf)[i]);
2987
 
            }
2988
 
        }
2989
 
 
2990
 
    }
2991
 
    NPY_LOOP_END_THREADS;
2992
 
    /* Hang on to this reference -- will be decref'd with loop */
2993
 
    if (loop->retbase) {
2994
 
        ret = (PyArrayObject *)loop->ret->base;
2995
 
    }
2996
 
    else {
2997
 
        ret = loop->ret;
2998
 
    }
2999
 
    Py_INCREF(ret);
3000
 
    ufuncreduce_dealloc(loop);
3001
 
    return (PyObject *)ret;
3002
 
 
3003
 
 fail:
3004
 
    NPY_LOOP_END_THREADS;
3005
 
    if (loop) {
3006
 
        ufuncreduce_dealloc(loop);
3007
 
    }
3008
 
    return NULL;
 
3482
    return PyUFunc_ReductionOp(self, arr, out, axis, otype,
 
3483
                                UFUNC_ACCUMULATE, "accumulate");
3009
3484
}
3010
3485
 
3011
3486
/*
3031
3506
PyUFunc_Reduceat(PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *ind,
3032
3507
                 PyArrayObject *out, int axis, int otype)
3033
3508
{
3034
 
    PyArrayObject *ret;
3035
 
    PyUFuncReduceObject *loop;
3036
 
    intp *ptr = (intp *)ind->data;
3037
 
    intp nn = ind->dimensions[0];
3038
 
    intp mm = arr->dimensions[axis] - 1;
3039
 
    intp n, i, j;
3040
 
    char *dptr;
 
3509
    PyArrayObject *op[3];
 
3510
    PyArray_Descr *op_dtypes[3] = {NULL, NULL, NULL};
 
3511
    int op_axes_arrays[3][NPY_MAXDIMS];
 
3512
    int *op_axes[3] = {op_axes_arrays[0], op_axes_arrays[1],
 
3513
                            op_axes_arrays[2]};
 
3514
    npy_uint32 op_flags[3];
 
3515
    int i, idim, ndim, otype_final;
 
3516
    int needs_api, need_outer_iterator;
 
3517
 
 
3518
    NpyIter *iter = NULL;
 
3519
 
 
3520
    /* The reduceat indices - ind must be validated outside this call */
 
3521
    npy_intp *reduceat_ind;
 
3522
    npy_intp ind_size, red_axis_size;
 
3523
    /* The selected inner loop */
 
3524
    PyUFuncGenericFunction innerloop = NULL;
 
3525
    void *innerloopdata = NULL;
 
3526
 
 
3527
    char *ufunc_name = self->name ? self->name : "(unknown)";
 
3528
    char *opname = "reduceat";
 
3529
 
 
3530
    /* These parameters come from extobj= or from a TLS global */
 
3531
    int buffersize = 0, errormask = 0;
 
3532
    PyObject *errobj = NULL;
 
3533
 
3041
3534
    NPY_BEGIN_THREADS_DEF;
3042
3535
 
 
3536
    reduceat_ind = (npy_intp *)PyArray_DATA(ind);
 
3537
    ind_size = PyArray_DIM(ind, 0);
 
3538
    red_axis_size = PyArray_DIM(arr, axis);
 
3539
 
3043
3540
    /* Check for out-of-bounds values in indices array */
3044
 
    for (i = 0; i<nn; i++) {
3045
 
        if ((*ptr < 0) || (*ptr > mm)) {
 
3541
    for (i = 0; i < ind_size; ++i) {
 
3542
        if (reduceat_ind[i] < 0 || reduceat_ind[i] >= red_axis_size) {
3046
3543
            PyErr_Format(PyExc_IndexError,
3047
 
                    "index out-of-bounds (0, %d)", (int) mm);
 
3544
                "index %d out-of-bounds in %s.%s [0, %d)",
 
3545
                (int)reduceat_ind[i], ufunc_name, opname, (int)red_axis_size);
3048
3546
            return NULL;
3049
3547
        }
3050
 
        ptr++;
3051
3548
    }
3052
3549
 
3053
 
    ptr = (intp *)ind->data;
3054
 
    /* Construct loop object */
3055
 
    loop = construct_reduce(self, &arr, out, axis, otype,
3056
 
            UFUNC_REDUCEAT, nn, "reduceat");
3057
 
    if (!loop) {
 
3550
    NPY_UF_DBG_PRINT2("\nEvaluating ufunc %s.%s\n", ufunc_name, opname);
 
3551
 
 
3552
#if 0
 
3553
    printf("Doing %s.%s on array with dtype :  ", ufunc_name, opname);
 
3554
    PyObject_Print((PyObject *)PyArray_DESCR(arr), stdout, 0);
 
3555
    printf("\n");
 
3556
    printf("Index size is %d\n", (int)ind_size);
 
3557
#endif
 
3558
 
 
3559
    if (PyUFunc_GetPyValues(opname, &buffersize, &errormask, &errobj) < 0) {
3058
3560
        return NULL;
3059
3561
    }
3060
3562
 
3061
 
    NPY_LOOP_BEGIN_THREADS;
3062
 
    switch(loop->meth) {
3063
 
    case ZERO_EL_REDUCELOOP:
3064
 
        /* zero-length index -- return array immediately */
3065
 
        /* fprintf(stderr, "ZERO..\n"); */
3066
 
        break;
3067
 
    case NOBUFFER_UFUNCLOOP:
3068
 
        /* Reduceat
3069
 
         * NOBUFFER -- behaved array and same type
3070
 
         */
3071
 
        /* fprintf(stderr, "NOBUFFER..%d\n", loop->size); */
3072
 
        while (loop->index < loop->size) {
3073
 
            ptr = (intp *)ind->data;
3074
 
            for (i = 0; i < nn; i++) {
3075
 
                loop->bufptr[1] = loop->it->dataptr + (*ptr)*loop->steps[1];
3076
 
                if (loop->obj & UFUNC_OBJ_ISOBJECT) {
3077
 
                    Py_XINCREF(*((PyObject **)loop->bufptr[1]));
3078
 
                }
3079
 
                memcpy(loop->bufptr[0], loop->bufptr[1], loop->outsize);
3080
 
                mm = (i == nn - 1 ? arr->dimensions[axis] - *ptr :
3081
 
                        *(ptr + 1) - *ptr) - 1;
3082
 
                if (mm > 0) {
3083
 
                    loop->bufptr[1] += loop->steps[1];
3084
 
                    loop->bufptr[2] = loop->bufptr[0];
3085
 
                    loop->function((char **)loop->bufptr, &mm,
3086
 
                            loop->steps, loop->funcdata);
3087
 
                    UFUNC_CHECK_ERROR(loop);
3088
 
                }
3089
 
                loop->bufptr[0] += loop->ret->strides[axis];
3090
 
                ptr++;
3091
 
            }
3092
 
            PyArray_ITER_NEXT(loop->it);
3093
 
            PyArray_ITER_NEXT(loop->rit);
3094
 
            loop->bufptr[0] = loop->rit->dataptr;
3095
 
            loop->index++;
3096
 
        }
3097
 
        break;
3098
 
 
3099
 
    case BUFFER_UFUNCLOOP:
3100
 
        /* Reduceat
3101
 
         * BUFFER -- misbehaved array or different types
3102
 
         */
3103
 
        /* fprintf(stderr, "BUFFERED..%d\n", loop->size); */
3104
 
        while (loop->index < loop->size) {
3105
 
            ptr = (intp *)ind->data;
3106
 
            for (i = 0; i < nn; i++) {
3107
 
                if (loop->obj & UFUNC_OBJ_ISOBJECT) {
3108
 
                    Py_XINCREF(*((PyObject **)loop->idptr));
3109
 
                }
3110
 
                memcpy(loop->bufptr[0], loop->idptr, loop->outsize);
3111
 
                n = 0;
3112
 
                mm = (i == nn - 1 ? arr->dimensions[axis] - *ptr :
3113
 
                        *(ptr + 1) - *ptr);
3114
 
                if (mm < 1) {
3115
 
                    mm = 1;
3116
 
                }
3117
 
                loop->inptr = loop->it->dataptr + (*ptr)*loop->instrides;
3118
 
                while (n < mm) {
3119
 
                    /* Copy up to loop->bufsize elements to buffer */
3120
 
                    dptr = loop->buffer;
3121
 
                    for (j = 0; j < loop->bufsize; j++, n++) {
3122
 
                        if (n == mm) {
3123
 
                            break;
3124
 
                        }
3125
 
                        arr->descr->f->copyswap(dptr, loop->inptr,
3126
 
                             loop->swap, NULL);
3127
 
                        loop->inptr += loop->instrides;
3128
 
                        dptr += loop->insize;
3129
 
                    }
3130
 
                    if (loop->cast) {
3131
 
                        loop->cast(loop->buffer, loop->castbuf, j, NULL, NULL);
3132
 
                    }
3133
 
                    loop->bufptr[2] = loop->bufptr[0];
3134
 
                    loop->function((char **)loop->bufptr, &j,
3135
 
                            loop->steps, loop->funcdata);
3136
 
                    UFUNC_CHECK_ERROR(loop);
3137
 
                    loop->bufptr[0] += j*loop->steps[0];
3138
 
                }
3139
 
                loop->bufptr[0] += loop->ret->strides[axis];
3140
 
                ptr++;
3141
 
            }
3142
 
            PyArray_ITER_NEXT(loop->it);
3143
 
            PyArray_ITER_NEXT(loop->rit);
3144
 
            loop->bufptr[0] = loop->rit->dataptr;
3145
 
            loop->index++;
3146
 
        }
 
3563
    /* Take a reference to out for later returning */
 
3564
    Py_XINCREF(out);
 
3565
 
 
3566
    otype_final = otype;
 
3567
    if (get_binary_op_function(self, &otype_final,
 
3568
                                &innerloop, &innerloopdata) < 0) {
 
3569
        PyArray_Descr *dtype = PyArray_DescrFromType(otype);
 
3570
        PyErr_Format(PyExc_ValueError,
 
3571
                     "could not find a matching type for %s.%s, "
 
3572
                     "requested type has type code '%c'",
 
3573
                            ufunc_name, opname, dtype ? dtype->type : '-');
 
3574
        Py_XDECREF(dtype);
 
3575
        goto fail;
 
3576
    }
 
3577
 
 
3578
    ndim = PyArray_NDIM(arr);
 
3579
 
 
3580
    /* Set up the output data type */
 
3581
    op_dtypes[0] = PyArray_DescrFromType(otype_final);
 
3582
    if (op_dtypes[0] == NULL) {
 
3583
        goto fail;
 
3584
    }
 
3585
 
 
3586
#if NPY_UF_DBG_TRACING
 
3587
    printf("Found %s.%s inner loop with dtype :  ", ufunc_name, opname);
 
3588
    PyObject_Print((PyObject *)op_dtypes[0], stdout, 0);
 
3589
    printf("\n");
 
3590
#endif
 
3591
 
 
3592
    /* Set up the op_axes for the outer loop */
 
3593
    for (i = 0, idim = 0; idim < ndim; ++idim) {
 
3594
        /* Use the i-th iteration dimension to match up ind */
 
3595
        if (idim == axis) {
 
3596
            op_axes_arrays[0][idim] = axis;
 
3597
            op_axes_arrays[1][idim] = -1;
 
3598
            op_axes_arrays[2][idim] = 0;
 
3599
        }
 
3600
        else {
 
3601
            op_axes_arrays[0][idim] = idim;
 
3602
            op_axes_arrays[1][idim] = idim;
 
3603
            op_axes_arrays[2][idim] = -1;
 
3604
        }
 
3605
    }
 
3606
 
 
3607
    op[0] = out;
 
3608
    op[1] = arr;
 
3609
    op[2] = ind;
 
3610
 
 
3611
    /* Likewise with accumulate, must do UPDATEIFCOPY */
 
3612
    if (out != NULL || ndim > 1 || !PyArray_ISALIGNED(arr) ||
 
3613
            !PyArray_EquivTypes(op_dtypes[0], PyArray_DESCR(arr))) {
 
3614
        need_outer_iterator = 1;
 
3615
    }
 
3616
 
 
3617
    if (need_outer_iterator) {
 
3618
        npy_uint32 flags = NPY_ITER_ZEROSIZE_OK|
 
3619
                           NPY_ITER_REFS_OK|
 
3620
                           NPY_ITER_MULTI_INDEX;
3147
3621
 
3148
3622
        /*
3149
 
         * DECREF left-over objects if buffering was used.
3150
 
         * It is needed when casting created new objects in
3151
 
         * castbuf.  Intermediate copying into castbuf (via
3152
 
         * loop->function) decref'd what was already there.
3153
 
 
3154
 
         * It's the final copy into the castbuf that needs a DECREF.
 
3623
         * The way reduceat is set up, we can't do buffering,
 
3624
         * so make a copy instead when necessary.
3155
3625
         */
3156
3626
 
3157
 
        /* Only when casting needed and it is from a non-object array */
3158
 
        if ((loop->obj & UFUNC_OBJ_ISOBJECT) && loop->cast &&
3159
 
            (!PyArray_ISOBJECT(arr))) {
3160
 
            for (i=0; i<loop->bufsize; i++) {
3161
 
                Py_CLEAR(((PyObject **)loop->castbuf)[i]);
3162
 
            }
3163
 
        }
3164
 
 
3165
 
        break;
3166
 
    }
3167
 
    NPY_LOOP_END_THREADS;
3168
 
    /* Hang on to this reference -- will be decref'd with loop */
3169
 
    if (loop->retbase) {
3170
 
        ret = (PyArrayObject *)loop->ret->base;
3171
 
    }
3172
 
    else {
3173
 
        ret = loop->ret;
3174
 
    }
3175
 
    Py_INCREF(ret);
3176
 
    ufuncreduce_dealloc(loop);
3177
 
    return (PyObject *)ret;
 
3627
        /* The per-operand flags for the outer loop */
 
3628
        op_flags[0] = NPY_ITER_READWRITE|
 
3629
                      NPY_ITER_NO_BROADCAST|
 
3630
                      NPY_ITER_ALLOCATE|
 
3631
                      NPY_ITER_NO_SUBTYPE|
 
3632
                      NPY_ITER_UPDATEIFCOPY|
 
3633
                      NPY_ITER_ALIGNED;
 
3634
        op_flags[1] = NPY_ITER_READONLY|
 
3635
                      NPY_ITER_COPY|
 
3636
                      NPY_ITER_ALIGNED;
 
3637
        op_flags[2] = NPY_ITER_READONLY;
 
3638
 
 
3639
        op_dtypes[1] = op_dtypes[0];
 
3640
 
 
3641
        NPY_UF_DBG_PRINT("Allocating outer iterator\n");
 
3642
        iter = NpyIter_AdvancedNew(3, op, flags,
 
3643
                                   NPY_KEEPORDER, NPY_UNSAFE_CASTING,
 
3644
                                   op_flags,
 
3645
                                   op_dtypes,
 
3646
                                   ndim, op_axes, NULL, 0);
 
3647
        if (iter == NULL) {
 
3648
            goto fail;
 
3649
        }
 
3650
 
 
3651
        /* Remove the inner loop axis from the outer iterator */
 
3652
        if (NpyIter_RemoveAxis(iter, axis) != NPY_SUCCEED) {
 
3653
            goto fail;
 
3654
        }
 
3655
        if (NpyIter_RemoveMultiIndex(iter) != NPY_SUCCEED) {
 
3656
            goto fail;
 
3657
        }
 
3658
 
 
3659
        /* In case COPY or UPDATEIFCOPY occurred */
 
3660
        op[0] = NpyIter_GetOperandArray(iter)[0];
 
3661
        op[1] = NpyIter_GetOperandArray(iter)[1];
 
3662
 
 
3663
        if (out == NULL) {
 
3664
            out = op[0];
 
3665
            Py_INCREF(out);
 
3666
        }
 
3667
    }
 
3668
    /* Allocate the output for when there's no outer iterator */
 
3669
    else if (out == NULL) {
 
3670
        Py_INCREF(op_dtypes[0]);
 
3671
        op[0] = out = (PyArrayObject *)PyArray_NewFromDescr(
 
3672
                                    &PyArray_Type, op_dtypes[0],
 
3673
                                    1, &ind_size, NULL, NULL,
 
3674
                                    0, NULL);
 
3675
        if (out == NULL) {
 
3676
            goto fail;
 
3677
        }
 
3678
    }
 
3679
 
 
3680
    /*
 
3681
     * If the output has zero elements, return now.
 
3682
     */
 
3683
    if (PyArray_SIZE(op[0]) == 0) {
 
3684
        goto finish;
 
3685
    }
 
3686
 
 
3687
    if (iter && NpyIter_GetIterSize(iter) != 0) {
 
3688
        char *dataptr_copy[3];
 
3689
        npy_intp stride_copy[3];
 
3690
 
 
3691
        NpyIter_IterNextFunc *iternext;
 
3692
        char **dataptr;
 
3693
        npy_intp count_m1;
 
3694
        npy_intp stride0, stride1;
 
3695
        npy_intp stride0_ind = PyArray_STRIDE(op[0], axis);
 
3696
 
 
3697
        int itemsize = op_dtypes[0]->elsize;
 
3698
 
 
3699
        /* Get the variables needed for the loop */
 
3700
        iternext = NpyIter_GetIterNext(iter, NULL);
 
3701
        if (iternext == NULL) {
 
3702
            goto fail;
 
3703
        }
 
3704
        dataptr = NpyIter_GetDataPtrArray(iter);
 
3705
 
 
3706
        /* Execute the loop with just the outer iterator */
 
3707
        count_m1 = PyArray_DIM(op[1], axis)-1;
 
3708
        stride0 = 0;
 
3709
        stride1 = PyArray_STRIDE(op[1], axis);
 
3710
 
 
3711
        NPY_UF_DBG_PRINT("UFunc: Reduce loop with just outer iterator\n");
 
3712
 
 
3713
        stride_copy[0] = stride0;
 
3714
        stride_copy[1] = stride1;
 
3715
        stride_copy[2] = stride0;
 
3716
 
 
3717
        needs_api = NpyIter_IterationNeedsAPI(iter);
 
3718
 
 
3719
        if (!needs_api) {
 
3720
            NPY_BEGIN_THREADS;
 
3721
        }
 
3722
 
 
3723
        do {
 
3724
 
 
3725
            for (i = 0; i < ind_size; ++i) {
 
3726
                npy_intp start = reduceat_ind[i],
 
3727
                        end = (i == ind_size-1) ? count_m1+1 :
 
3728
                                                  reduceat_ind[i+1];
 
3729
                npy_intp count = end - start;
 
3730
 
 
3731
                dataptr_copy[0] = dataptr[0] + stride0_ind*i;
 
3732
                dataptr_copy[1] = dataptr[1] + stride1*start;
 
3733
                dataptr_copy[2] = dataptr[0] + stride0_ind*i;
 
3734
 
 
3735
                /* Copy the first element to start the reduction */
 
3736
                if (otype == NPY_OBJECT) {
 
3737
                    Py_XDECREF(*(PyObject **)dataptr_copy[0]);
 
3738
                    *(PyObject **)dataptr_copy[0] =
 
3739
                                        *(PyObject **)dataptr_copy[1];
 
3740
                    Py_XINCREF(*(PyObject **)dataptr_copy[0]);
 
3741
                }
 
3742
                else {
 
3743
                    memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
 
3744
                }
 
3745
 
 
3746
                if (count > 1) {
 
3747
                    /* Inner loop like REDUCE */
 
3748
                    --count;
 
3749
                    dataptr_copy[1] += stride1;
 
3750
                    NPY_UF_DBG_PRINT1("iterator loop count %d\n",
 
3751
                                                    (int)count);
 
3752
                    innerloop(dataptr_copy, &count,
 
3753
                                stride_copy, innerloopdata);
 
3754
                }
 
3755
            }
 
3756
        } while (iternext(iter));
 
3757
 
 
3758
        if (!needs_api) {
 
3759
            NPY_END_THREADS;
 
3760
        }
 
3761
    }
 
3762
    else if (iter == NULL) {
 
3763
        char *dataptr_copy[3];
 
3764
        npy_intp stride_copy[3];
 
3765
 
 
3766
        int itemsize = op_dtypes[0]->elsize;
 
3767
 
 
3768
        npy_intp stride0_ind = PyArray_STRIDE(op[0], axis);
 
3769
 
 
3770
        /* Execute the loop with no iterators */
 
3771
        npy_intp stride0 = 0, stride1 = PyArray_STRIDE(op[1], axis);
 
3772
 
 
3773
        needs_api = PyDataType_REFCHK(op_dtypes[0]);
 
3774
 
 
3775
        NPY_UF_DBG_PRINT("UFunc: Reduce loop with no iterators\n");
 
3776
 
 
3777
        stride_copy[0] = stride0;
 
3778
        stride_copy[1] = stride1;
 
3779
        stride_copy[2] = stride0;
 
3780
 
 
3781
        if (!needs_api) {
 
3782
            NPY_BEGIN_THREADS;
 
3783
        }
 
3784
 
 
3785
        for (i = 0; i < ind_size; ++i) {
 
3786
            npy_intp start = reduceat_ind[i],
 
3787
                    end = (i == ind_size-1) ? PyArray_DIM(arr,axis) :
 
3788
                                              reduceat_ind[i+1];
 
3789
            npy_intp count = end - start;
 
3790
 
 
3791
            dataptr_copy[0] = PyArray_BYTES(op[0]) + stride0_ind*i;
 
3792
            dataptr_copy[1] = PyArray_BYTES(op[1]) + stride1*start;
 
3793
            dataptr_copy[2] = PyArray_BYTES(op[0]) + stride0_ind*i;
 
3794
 
 
3795
            /* Copy the first element to start the reduction */
 
3796
            if (otype == NPY_OBJECT) {
 
3797
                Py_XDECREF(*(PyObject **)dataptr_copy[0]);
 
3798
                *(PyObject **)dataptr_copy[0] =
 
3799
                                    *(PyObject **)dataptr_copy[1];
 
3800
                Py_XINCREF(*(PyObject **)dataptr_copy[0]);
 
3801
            }
 
3802
            else {
 
3803
                memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
 
3804
            }
 
3805
 
 
3806
            if (count > 1) {
 
3807
                /* Inner loop like REDUCE */
 
3808
                --count;
 
3809
                dataptr_copy[1] += stride1;
 
3810
                NPY_UF_DBG_PRINT1("iterator loop count %d\n",
 
3811
                                                (int)count);
 
3812
                innerloop(dataptr_copy, &count,
 
3813
                            stride_copy, innerloopdata);
 
3814
            }
 
3815
        }
 
3816
 
 
3817
        if (!needs_api) {
 
3818
            NPY_END_THREADS;
 
3819
        }
 
3820
    }
 
3821
 
 
3822
finish:
 
3823
    Py_XDECREF(op_dtypes[0]);
 
3824
    if (iter != NULL) {
 
3825
        NpyIter_Deallocate(iter);
 
3826
    }
 
3827
 
 
3828
    Py_XDECREF(errobj);
 
3829
 
 
3830
    return (PyObject *)out;
3178
3831
 
3179
3832
fail:
3180
 
    NPY_LOOP_END_THREADS;
3181
 
    if (loop) {
3182
 
        ufuncreduce_dealloc(loop);
 
3833
    Py_XDECREF(out);
 
3834
    Py_XDECREF(op_dtypes[0]);
 
3835
 
 
3836
    if (iter != NULL) {
 
3837
        NpyIter_Deallocate(iter);
3183
3838
    }
 
3839
 
 
3840
    Py_XDECREF(errobj);
 
3841
 
3184
3842
    return NULL;
3185
3843
}
3186
3844
 
3233
3891
        indtype = PyArray_DescrFromType(PyArray_INTP);
3234
3892
        if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO|iO&O&", kwlist2,
3235
3893
                                        &op, &obj_ind, &axis,
3236
 
                                        PyArray_DescrConverter2,
3237
 
                                        &otype,
3238
 
                                        PyArray_OutputConverter,
3239
 
                                        &out)) {
 
3894
                                        PyArray_DescrConverter2, &otype,
 
3895
                                        PyArray_OutputConverter, &out)) {
3240
3896
            Py_XDECREF(otype);
3241
3897
            return NULL;
3242
3898
        }
3250
3906
    else {
3251
3907
        if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|iO&O&", kwlist1,
3252
3908
                                        &op, &axis,
3253
 
                                        PyArray_DescrConverter2,
3254
 
                                        &otype,
3255
 
                                        PyArray_OutputConverter,
3256
 
                                        &out)) {
 
3909
                                        PyArray_DescrConverter2, &otype,
 
3910
                                        PyArray_OutputConverter, &out)) {
3257
3911
            Py_XDECREF(otype);
3258
3912
            return NULL;
3259
3913
        }
3312
3966
         * is used for add and multiply reduction to avoid overflow
3313
3967
         */
3314
3968
        int typenum = PyArray_TYPE(mp);
3315
 
        if ((typenum < NPY_FLOAT)
 
3969
        if ((PyTypeNum_ISBOOL(typenum) || PyTypeNum_ISINTEGER(typenum))
3316
3970
            && ((strcmp(self->name,"add") == 0)
3317
3971
                || (strcmp(self->name,"multiply") == 0))) {
3318
3972
            if (PyTypeNum_ISBOOL(typenum)) {
3384
4038
 * should just have PyArray_Return called.
3385
4039
 */
3386
4040
static void
3387
 
_find_array_wrap(PyObject *args, PyObject **output_wrap, int nin, int nout)
 
4041
_find_array_wrap(PyObject *args, PyObject *kwds,
 
4042
                PyObject **output_wrap, int nin, int nout)
3388
4043
{
3389
4044
    Py_ssize_t nargs;
3390
4045
    int i;
3392
4047
    PyObject *with_wrap[NPY_MAXARGS], *wraps[NPY_MAXARGS];
3393
4048
    PyObject *obj, *wrap = NULL;
3394
4049
 
 
4050
    /* If a 'subok' parameter is passed and isn't True, don't wrap */
 
4051
    if (kwds != NULL && (obj = PyDict_GetItemString(kwds, "subok")) != NULL) {
 
4052
        if (obj != Py_True) {
 
4053
            for (i = 0; i < nout; i++) {
 
4054
                output_wrap[i] = NULL;
 
4055
            }
 
4056
            return;
 
4057
        }
 
4058
    }
 
4059
 
3395
4060
    nargs = PyTuple_GET_SIZE(args);
3396
4061
    for (i = 0; i < nin; i++) {
3397
4062
        obj = PyTuple_GET_ITEM(args, i);
3454
4119
        int j = nin + i;
3455
4120
        int incref = 1;
3456
4121
        output_wrap[i] = wrap;
 
4122
        obj = NULL;
3457
4123
        if (j < nargs) {
3458
4124
            obj = PyTuple_GET_ITEM(args, j);
3459
 
            if (obj == Py_None) {
3460
 
                continue;
 
4125
            /* Output argument one may also be in a keyword argument */
 
4126
            if (i == 0 && obj == Py_None && kwds != NULL) {
 
4127
                obj = PyDict_GetItemString(kwds, "out");
3461
4128
            }
 
4129
        }
 
4130
        /* Output argument one may also be in a keyword argument */
 
4131
        else if (i == 0 && kwds != NULL) {
 
4132
            obj = PyDict_GetItemString(kwds, "out");
 
4133
        }
 
4134
 
 
4135
        if (obj != Py_None && obj != NULL) {
3462
4136
            if (PyArray_CheckExact(obj)) {
 
4137
                /* None signals to not call any wrapping */
3463
4138
                output_wrap[i] = Py_None;
3464
4139
            }
3465
4140
            else {
3474
4149
                output_wrap[i] = owrap;
3475
4150
            }
3476
4151
        }
 
4152
 
3477
4153
        if (incref) {
3478
4154
            Py_XINCREF(output_wrap[i]);
3479
4155
        }
3482
4158
    return;
3483
4159
}
3484
4160
 
 
4161
 
3485
4162
static PyObject *
3486
4163
ufunc_generic_call(PyUFuncObject *self, PyObject *args, PyObject *kwds)
3487
4164
{
3514
4191
            return Py_NotImplemented;
3515
4192
        }
3516
4193
        else {
3517
 
            PyErr_SetString(PyExc_NotImplementedError, "Not implemented for this type");
 
4194
            PyErr_SetString(PyExc_NotImplementedError,
 
4195
                                        "Not implemented for this type");
3518
4196
            return NULL;
3519
4197
        }
3520
4198
    }
 
4199
 
 
4200
    /* Free the input references */
3521
4201
    for (i = 0; i < self->nin; i++) {
3522
4202
        Py_DECREF(mps[i]);
3523
4203
    }
 
4204
 
3524
4205
    /*
3525
4206
     * Use __array_wrap__ on all outputs
3526
4207
     * if present on one of the input arguments.
3538
4219
     * None --- array-object passed in don't call PyArray_Return
3539
4220
     * method --- the __array_wrap__ method to call.
3540
4221
     */
3541
 
    _find_array_wrap(args, wraparr, self->nin, self->nout);
 
4222
    _find_array_wrap(args, kwds, wraparr, self->nin, self->nout);
3542
4223
 
3543
4224
    /* wrap outputs */
3544
4225
    for (i = 0; i < self->nout; i++) {
3545
4226
        int j = self->nin+i;
3546
 
        PyObject *wrap;
3547
 
        /*
3548
 
         * check to see if any UPDATEIFCOPY flags are set
3549
 
         * which meant that a temporary output was generated
3550
 
         */
3551
 
        if (mps[j]->flags & UPDATEIFCOPY) {
3552
 
            PyObject *old = mps[j]->base;
3553
 
            /* we want to hang on to this */
3554
 
            Py_INCREF(old);
3555
 
            /* should trigger the copyback into old */
3556
 
            Py_DECREF(mps[j]);
3557
 
            mps[j] = (PyArrayObject *)old;
3558
 
        }
3559
 
        wrap = wraparr[i];
 
4227
        PyObject *wrap = wraparr[i];
 
4228
 
3560
4229
        if (wrap != NULL) {
3561
4230
            if (wrap == Py_None) {
3562
4231
                Py_DECREF(wrap);
3797
4466
    self->core_signature = NULL;
3798
4467
    if (signature != NULL) {
3799
4468
        if (_parse_signature(self, signature) != 0) {
 
4469
            Py_DECREF(self);
3800
4470
            return NULL;
3801
4471
        }
3802
4472
    }