1
/* -*- c -*- */
2
#define PY_SSIZE_T_CLEAN
3
#include "Python.h"
4
#include "structmember.h"
5
#include <limits.h>
6
#include <assert.h>
7

8
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
9
#define _MULTIARRAYMODULE
10
#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */
11

12
#include "numpy/npy_common.h"
13
#include "numpy/arrayobject.h"
14
#include "numpy/arrayscalars.h"
15
#include "npy_pycompat.h"
16
#include "numpy/npy_math.h"
17
#include "numpy/halffloat.h"
18

19
#include "npy_config.h"
20
#include "npy_sort.h"
21
#include "common.h"
22
#include "ctors.h"
23
#include "dtypemeta.h"
24
#include "lowlevel_strided_loops.h"
25
#include "usertypes.h"
26
#include "_datetime.h"
27
#include "arrayobject.h"
28
#include "alloc.h"
29
#include "typeinfo.h"
30
#if defined(__ARM_NEON__) || defined (__ARM_NEON)
31
#include <arm_neon.h>
32
#endif
33
#ifdef NPY_HAVE_SSE2_INTRINSICS
34
#include <emmintrin.h>
35
#endif
36

37
#include "npy_longdouble.h"
38
#include "numpyos.h"
39
#include <string.h>
40

41
#include "cblasfuncs.h"
42
#include "npy_cblas.h"
43
#include "npy_buffer.h"
44

45
/* check for sequences, but ignore the types numpy considers scalars */
46
static NPY_INLINE npy_bool
47 1
PySequence_NoString_Check(PyObject *op) {
48
    return
49 1
        PySequence_Check(op) &&
50 1
        !PyBytes_Check(op) &&
51 1
        !PyUnicode_Check(op) &&
52 1
        !PyArray_IsZeroDim(op);
53
}
54

55
/*
56
 *****************************************************************************
57
 **                        PYTHON TYPES TO C TYPES                          **
58
 *****************************************************************************
59
 */
60

61
static double
62 1
MyPyFloat_AsDouble(PyObject *obj)
63
{
64 1
    double ret = 0;
65
    PyObject *num;
66

67 1
    if (obj == Py_None) {
68
        return NPY_NAN;
69
    }
70 1
    num = PyNumber_Float(obj);
71 1
    if (num == NULL) {
72
        return NPY_NAN;
73
    }
74 1
    ret = PyFloat_AsDouble(num);
75 1
    Py_DECREF(num);
76
    return ret;
77
}
78

79
static npy_half
80
MyPyFloat_AsHalf(PyObject *obj)
81
{
82 1
    return npy_double_to_half(MyPyFloat_AsDouble(obj));
83
}
84

85
static PyObject *
86
MyPyFloat_FromHalf(npy_half h)
87
{
88 1
    return PyFloat_FromDouble(npy_half_to_double(h));
89
}
90

91
/* Handle case of assigning from an array scalar in setitem */
92
static int
93 1
convert_to_scalar_and_retry(PyObject *op, void *ov, void *vap,
94
                      int (*setitem)(PyObject *op, void *ov, void *vap))
95
{
96
    PyObject *temp;
97

98
    assert(PyArray_IsZeroDim(op));
99 1
    temp = PyArray_ToScalar(PyArray_BYTES((PyArrayObject *)op),
100
                                      (PyArrayObject *)op);
101 1
    if (temp == NULL) {
102
        return -1;
103
    }
104
    else {
105 1
        int res = setitem(temp, ov, vap);
106 1
        Py_DECREF(temp);
107
        return res;
108
    }
109
}
110

111

112
/**begin repeat
113
 *
114
 * #Type = Long, LongLong#
115
 * #type = npy_long, npy_longlong#
116
 */
117
static @type@
118 1
MyPyLong_As@Type@ (PyObject *obj)
119
{
120
    @type@ ret;
121 1
    PyObject *num = PyNumber_Long(obj);
122

123 1
    if (num == NULL) {
124
        return -1;
125
    }
126 1
    ret = PyLong_As@Type@(num);
127 1
    Py_DECREF(num);
128
    return ret;
129
}
130

131
/**end repeat**/
132

133
/**begin repeat
134
 *
135
 * #Type = Long, LongLong#
136
 * #type = npy_ulong, npy_ulonglong#
137
 */
138
static @type@
139 1
MyPyLong_AsUnsigned@Type@ (PyObject *obj)
140
{
141
    @type@ ret;
142 1
    PyObject *num = PyNumber_Long(obj);
143

144 1
    if (num == NULL) {
145
        return -1;
146
    }
147 1
    ret = PyLong_AsUnsigned@Type@(num);
148 1
    if (PyErr_Occurred()) {
149 1
        PyErr_Clear();
150 1
        ret = PyLong_As@Type@(num);
151
    }
152 1
    Py_DECREF(num);
153
    return ret;
154
}
155

156
/**end repeat**/
157

158
/*
159
 *****************************************************************************
160
 **                         GETITEM AND SETITEM                             **
161
 *****************************************************************************
162
 */
163

164
#define _ALIGN(type) offsetof(struct {char c; type v;}, v)
165
/*
166
 * Disable harmless compiler warning "4116: unnamed type definition in
167
 * parentheses" which is caused by the _ALIGN macro.
168
 */
169
#if defined(_MSC_VER)
170
#pragma warning(disable:4116)
171
#endif
172

173

174
/**begin repeat
175
 *
176
 * #TYPE = BOOL, BYTE, UBYTE, SHORT, USHORT, INT, LONG, UINT, ULONG,
177
 *         LONGLONG, ULONGLONG, HALF, FLOAT, DOUBLE#
178
 * #func1 = PyBool_FromLong, PyLong_FromLong*6, PyLong_FromUnsignedLong*2,
179
 *          PyLong_FromLongLong, PyLong_FromUnsignedLongLong,
180
 *          MyPyFloat_FromHalf, PyFloat_FromDouble*2#
181
 * #func2 = PyObject_IsTrue, MyPyLong_AsLong*6, MyPyLong_AsUnsignedLong*2,
182
 *          MyPyLong_AsLongLong, MyPyLong_AsUnsignedLongLong,
183
 *          MyPyFloat_AsHalf, MyPyFloat_AsDouble*2#
184
 * #type = npy_bool,
185
 *         npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int,
186
 *         npy_long, npy_uint, npy_ulong, npy_longlong, npy_ulonglong,
187
 *         npy_half, npy_float, npy_double#
188
 * #type1 = long*7, npy_ulong*2, npy_longlong, npy_ulonglong,
189
 *          npy_half, npy_float, npy_double#
190
 * #kind = Bool, Byte, UByte, Short, UShort, Int, Long, UInt, ULong,
191
 *         LongLong, ULongLong, Half, Float, Double#
192
*/
193
static PyObject *
194 1
@TYPE@_getitem(void *input, void *vap)
195
{
196 1
    PyArrayObject *ap = vap;
197 1
    char *ip = input;
198
    @type@ t1;
199

200 1
    if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) {
201 1
        t1 = *((@type@ *)ip);
202 1
        return @func1@((@type1@)t1);
203
    }
204
    else {
205 1
        PyArray_DESCR(ap)->f->copyswap(&t1, ip, PyArray_ISBYTESWAPPED(ap), ap);
206 1
        return @func1@((@type1@)t1);
207
    }
208
}
209

210
static int
211 1
@TYPE@_setitem(PyObject *op, void *ov, void *vap)
212
{
213 1
    PyArrayObject *ap = vap;
214
    @type@ temp;  /* ensures alignment */
215

216 1
    if (PyArray_IsScalar(op, @kind@)) {
217 1
        temp = PyArrayScalar_VAL(op, @kind@);
218
    }
219
    else {
220 1
        temp = (@type@)@func2@(op);
221
    }
222 1
    if (PyErr_Occurred()) {
223
        PyObject *type, *value, *traceback;
224 1
        PyErr_Fetch(&type, &value, &traceback);
225 1
        if (PySequence_NoString_Check(op)) {
226 1
            PyErr_SetString(PyExc_ValueError,
227
                    "setting an array element with a sequence.");
228 1
            npy_PyErr_ChainExceptionsCause(type, value, traceback);
229
        }
230
        else {
231 1
            PyErr_Restore(type, value, traceback);
232
        }
233
        return -1;
234
    }
235 1
    if (ap == NULL || PyArray_ISBEHAVED(ap)) {
236
        assert(npy_is_aligned(ov, _ALIGN(@type@)));
237 1
        *((@type@ *)ov)=temp;
238
    }
239
    else {
240 1
        PyArray_DESCR(ap)->f->copyswap(ov, &temp, PyArray_ISBYTESWAPPED(ap),
241
                                       ap);
242
    }
243
    return 0;
244
}
245

246
/**end repeat**/
247

248
/**begin repeat
249
 *
250
 * #TYPE = CFLOAT, CDOUBLE#
251
 * #type = npy_float, npy_double#
252
 */
253
static PyObject *
254 1
@TYPE@_getitem(void *input, void *vap)
255
{
256 1
    PyArrayObject *ap = vap;
257 1
    char *ip = input;
258
    @type@ t1, t2;
259

260 1
    if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) {
261 1
        return PyComplex_FromDoubles((double)((@type@ *)ip)[0],
262 1
                (double)((@type@ *)ip)[1]);
263
    }
264
    else {
265 0
        int size = sizeof(@type@);
266

267 0
        npy_bool swap = PyArray_ISBYTESWAPPED(ap);
268 0
        copy_and_swap(&t1, ip, size, 1, 0, swap);
269 0
        copy_and_swap(&t2, ip + size, size, 1, 0, swap);
270 0
        return PyComplex_FromDoubles((double)t1, (double)t2);
271
    }
272
}
273

274
/**end repeat**/
275

276

277

278
/**begin repeat
279
 *
280
 * #NAME = CFLOAT, CDOUBLE, CLONGDOUBLE#
281
 * #type = npy_cfloat, npy_cdouble, npy_clongdouble#
282
 * #ftype = npy_float, npy_double, npy_longdouble#
283
 * #kind = CFloat, CDouble, CLongDouble#
284
 */
285
static int
286 1
@NAME@_setitem(PyObject *op, void *ov, void *vap)
287
{
288 1
    PyArrayObject *ap = vap;
289
    Py_complex oop;
290
    @type@ temp;
291
    int rsize;
292

293 1
    if (PyArray_IsZeroDim(op)) {
294 1
        return convert_to_scalar_and_retry(op, ov, vap, @NAME@_setitem);
295
    }
296

297 1
    if (PyArray_IsScalar(op, @kind@)){
298 1
        temp = PyArrayScalar_VAL(op, @kind@);
299
    }
300
    else {
301 1
        if (op == Py_None) {
302
            oop.real = NPY_NAN;
303
            oop.imag = NPY_NAN;
304
        }
305 1
        else if (PyBytes_Check(op) || PyUnicode_Check(op)) {
306
            /*
307
             * Unlike most numeric conversion functions PyComplex_AsCComplex
308
             * does not handle strings, so we have to use its constructor.
309
             */
310
            PyObject *pycomplex, *args;
311 1
            if (PyBytes_Check(op)) {
312
                /* The complex constructor expects unicode */
313
                PyObject *unicode;
314 1
                unicode = PyUnicode_FromEncodedObject(op, NULL, NULL);
315 1
                if (unicode == NULL) {
316
                    return -1;
317
                }
318 1
                args = PyTuple_Pack(1, unicode);
319 1
                Py_DECREF(unicode);
320
            }
321
            else {
322 1
                args = PyTuple_Pack(1, op);
323
            }
324 1
            if (args == NULL) {
325
                return -1;
326
            }
327 1
            pycomplex = PyComplex_Type.tp_new(&PyComplex_Type, args, NULL);
328 1
            Py_DECREF(args);
329 1
            if (pycomplex == NULL) {
330
                return -1;
331
            }
332 1
            oop = PyComplex_AsCComplex(pycomplex);
333 1
            Py_DECREF(pycomplex);
334 1
            if (error_converting(oop.real)) {
335
                return -1;
336
            }
337
        }
338
        else {
339 1
            oop = PyComplex_AsCComplex(op);
340 1
            if (error_converting(oop.real)) {
341
                return -1;
342
            }
343
        }
344 1
        temp.real = (@ftype@) oop.real;
345 1
        temp.imag = (@ftype@) oop.imag;
346
    }
347

348 1
    memcpy(ov, &temp, PyArray_DESCR(ap)->elsize);
349 1
    if (PyArray_ISBYTESWAPPED(ap)) {
350 1
        byte_swap_vector(ov, 2, sizeof(@ftype@));
351
    }
352 1
    rsize = sizeof(@ftype@);
353 1
    copy_and_swap(ov, &temp, rsize, 2, rsize, PyArray_ISBYTESWAPPED(ap));
354 1
    return 0;
355
}
356

357
/**end repeat**/
358

359
static NPY_INLINE npy_longdouble
360 1
string_to_long_double(PyObject*op)
361
{
362
    char *s;
363
    char *end;
364
    npy_longdouble temp;
365
    PyObject* b;
366

367
    /* Convert python long objects to a longdouble, without precision or range
368
     * loss via a double.
369
     */
370 1
    if ((PyLong_Check(op) && !PyBool_Check(op))) {
371 1
        return npy_longdouble_from_PyLong(op);
372
    }
373

374 1
    if (PyUnicode_Check(op)) {
375 1
        b = PyUnicode_AsUTF8String(op);
376 1
        if (!b) {
377
            return 0;
378
        }
379
    }
380
    else {
381 1
        b = op;
382 1
        Py_XINCREF(b);
383
    }
384 1
    s = PyBytes_AsString(b);
385 1
    if (s) {
386 1
        errno = 0;
387 1
        temp = NumPyOS_ascii_strtold(s, &end);
388 1
        if (errno == ERANGE) {
389 1
           if (PyErr_Warn(PyExc_RuntimeWarning,
390
                   "overflow encountered in conversion from string") < 0) {
391 0
               Py_XDECREF(b);
392
               return 0;
393
           }
394
           /* strtold returns INFINITY of the correct sign. */
395
        }
396 1
        else if (errno) {
397 0
            PyErr_Format(PyExc_ValueError,
398
                         "invalid literal for long double: %s (%s)",
399
                         s,
400
                         strerror(errno));
401 0
            Py_XDECREF(b);
402
            return 0;
403
        }
404

405
        /* Extra characters at the end of the string, or nothing parsed */
406 1
        if (end == s || *end) {
407 1
            PyErr_Format(PyExc_ValueError,
408
                         "invalid literal for long double: %s",
409
                         s);
410 1
            Py_XDECREF(b);
411
            return 0;
412
        }
413 1
        Py_XDECREF(b);
414
    }
415
    else {
416
        /* Probably wasn't a string, try converting it via a python double */
417 1
        PyErr_Clear();
418 1
        Py_XDECREF(b);
419 1
        temp = (npy_longdouble) MyPyFloat_AsDouble(op);
420
    }
421
    return temp;
422
}
423

424
/*
425
 * These return array scalars which are different than other date-types.
426
 */
427

428
static PyObject *
429 1
LONGDOUBLE_getitem(void *ip, void *ap)
430
{
431 1
    return PyArray_Scalar(ip, PyArray_DESCR((PyArrayObject *)ap), NULL);
432
}
433

434
static int
435 1
LONGDOUBLE_setitem(PyObject *op, void *ov, void *vap)
436
{
437 1
    PyArrayObject *ap = vap;
438
    /* ensure alignment */
439
    npy_longdouble temp;
440

441 1
    if (PyArray_IsZeroDim(op)) {
442 1
        return convert_to_scalar_and_retry(op, ov, vap, LONGDOUBLE_setitem);
443
    }
444

445 1
    if (PyArray_IsScalar(op, LongDouble)) {
446 1
        temp = PyArrayScalar_VAL(op, LongDouble);
447
    }
448
    else {
449
        /* In case something funny happened in PyArray_IsScalar */
450 1
        if (PyErr_Occurred()) {
451
            return -1;
452
        }
453 1
        temp = string_to_long_double(op);
454
    }
455 1
    if (PyErr_Occurred()) {
456
        return -1;
457
    }
458 1
    if (ap == NULL || PyArray_ISBEHAVED(ap)) {
459 1
        *((npy_longdouble *)ov) = temp;
460
    }
461
    else {
462 1
        copy_and_swap(ov, &temp, PyArray_DESCR(ap)->elsize, 1, 0,
463 1
                      PyArray_ISBYTESWAPPED(ap));
464
    }
465
    return 0;
466
}
467

468
static PyObject *
469 1
CLONGDOUBLE_getitem(void *ip, void *ap)
470
{
471 1
    return PyArray_Scalar(ip, PyArray_DESCR((PyArrayObject *)ap), NULL);
472
}
473

474
/* UNICODE */
475
static PyObject *
476 1
UNICODE_getitem(void *ip, void *vap)
477
{
478 1
    PyArrayObject *ap = vap;
479 1
    Py_ssize_t size = PyArray_ITEMSIZE(ap);
480 1
    int swap = PyArray_ISBYTESWAPPED(ap);
481 1
    int align = !PyArray_ISALIGNED(ap);
482

483 1
    return (PyObject *)PyUnicode_FromUCS4(ip, size, swap, align);
484
}
485

486
static int
487 1
UNICODE_setitem(PyObject *op, void *ov, void *vap)
488
{
489 1
    PyArrayObject *ap = vap;
490

491 1
    if (PyArray_IsZeroDim(op)) {
492 1
        return convert_to_scalar_and_retry(op, ov, vap, UNICODE_setitem);
493
    }
494

495 1
    if (PySequence_NoString_Check(op)) {
496 1
        PyErr_SetString(PyExc_ValueError,
497
                "setting an array element with a sequence");
498 1
        return -1;
499
    }
500

501
    PyObject *temp;
502 1
    if (PyBytes_Check(op)) {
503
        /* Try to decode from ASCII */
504 1
        temp = PyUnicode_FromEncodedObject(op, "ASCII", "strict");
505 1
        if (temp == NULL) {
506
            return -1;
507
        }
508
    }
509 1
    else if ((temp=PyObject_Str(op)) == NULL) {
510
        return -1;
511
    }
512

513
    /* truncate if needed */
514 1
    Py_ssize_t max_len = PyArray_DESCR(ap)->elsize >> 2;
515 1
    Py_ssize_t actual_len = PyUnicode_GetLength(temp);
516 1
    if (actual_len < 0) {
517 0
        Py_DECREF(temp);
518
        return -1;
519
    }
520 1
    if (actual_len > max_len) {
521 1
        Py_SETREF(temp, PyUnicode_Substring(temp, 0, max_len));
522 1
        if (temp == NULL) {
523
            return -1;
524
        }
525
        actual_len = max_len;
526
    }
527

528 1
    Py_ssize_t num_bytes = actual_len * 4;
529

530
    char *buffer;
531 1
    if (!PyArray_ISALIGNED(ap)) {
532 1
        buffer = PyArray_malloc(num_bytes);
533 1
        if (buffer == NULL) {
534 0
            Py_DECREF(temp);
535 0
            PyErr_NoMemory();
536 0
            return -1;
537
        }
538
    }
539
    else {
540
        buffer = ov;
541
    }
542 1
    if (PyUnicode_AsUCS4(temp, (Py_UCS4 *)buffer, actual_len, 0) == NULL) {
543 0
        PyArray_free(buffer);
544 0
        Py_DECREF(temp);
545
        return -1;
546
    }
547

548 1
    if (!PyArray_ISALIGNED(ap)) {
549 1
        memcpy(ov, buffer, num_bytes);
550 1
        PyArray_free(buffer);
551
    }
552

553
    /* Fill in the rest of the space with 0 */
554 1
    if (PyArray_DESCR(ap)->elsize > num_bytes) {
555 1
        memset((char*)ov + num_bytes, 0, (PyArray_DESCR(ap)->elsize - num_bytes));
556
    }
557 1
    if (PyArray_ISBYTESWAPPED(ap)) {
558 1
        byte_swap_vector(ov, actual_len, 4);
559
    }
560 1
    Py_DECREF(temp);
561
    return 0;
562
}
563

564
/* STRING
565
 *
566
 * can handle both NULL-terminated and not NULL-terminated cases
567
 * will truncate all ending NULLs in returned string.
568
 */
569
static PyObject *
570 1
STRING_getitem(void *ip, void *vap)
571
{
572 1
    PyArrayObject *ap = vap;
573
    /* Will eliminate NULLs at the end */
574
    char *ptr;
575 1
    int size = PyArray_DESCR(ap)->elsize;
576

577 1
    ptr = (char *)ip + size - 1;
578 1
    while (size > 0 && *ptr-- == '\0') {
579 1
        size--;
580
    }
581 1
    return PyBytes_FromStringAndSize(ip,size);
582
}
583

584
static int
585 1
STRING_setitem(PyObject *op, void *ov, void *vap)
586
{
587 1
    PyArrayObject *ap = vap;
588
    char *ptr;
589
    Py_ssize_t len;
590 1
    PyObject *temp = NULL;
591

592 1
    if (PyArray_IsZeroDim(op)) {
593 1
        return convert_to_scalar_and_retry(op, ov, vap, STRING_setitem);
594
    }
595

596 1
    if (PySequence_NoString_Check(op)) {
597 1
        PyErr_SetString(PyExc_ValueError,
598
                "setting an array element with a sequence");
599 1
        return -1;
600
    }
601 1
    if (PyUnicode_Check(op)) {
602
        /* Assume ASCII codec -- function similarly as Python 2 */
603 1
        temp = PyUnicode_AsASCIIString(op);
604 1
        if (temp == NULL) {
605
            return -1;
606
        }
607
    }
608 1
    else if (PyBytes_Check(op) || PyMemoryView_Check(op)) {
609 1
        temp = PyObject_Bytes(op);
610 1
        if (temp == NULL) {
611
            return -1;
612
        }
613
    }
614
    else {
615
        /* Emulate similar casting behavior as on Python 2 */
616
        PyObject *str;
617 1
        str = PyObject_Str(op);
618 1
        if (str == NULL) {
619
            return -1;
620
        }
621 1
        temp = PyUnicode_AsASCIIString(str);
622 1
        Py_DECREF(str);
623 1
        if (temp == NULL) {
624
            return -1;
625
        }
626
    }
627 1
    if (PyBytes_AsStringAndSize(temp, &ptr, &len) < 0) {
628 0
        Py_DECREF(temp);
629
        return -1;
630
    }
631 1
    memcpy(ov, ptr, PyArray_MIN(PyArray_DESCR(ap)->elsize,len));
632
    /*
633
     * If string length is smaller than room in array
634
     * Then fill the rest of the element size with NULL
635
     */
636 1
    if (PyArray_DESCR(ap)->elsize > len) {
637 1
        memset((char *)ov + len, 0, (PyArray_DESCR(ap)->elsize - len));
638
    }
639 1
    Py_DECREF(temp);
640
    return 0;
641
}
642

643
/* OBJECT */
644

645
#define __ALIGNED(obj, sz) ((((size_t) obj) % (sz))==0)
646

647
static PyObject *
648 1
OBJECT_getitem(void *ip, void *NPY_UNUSED(ap))
649
{
650
    PyObject *obj;
651 1
    memcpy(&obj, ip, sizeof(obj));
652 1
    if (obj == NULL) {
653 0
        Py_RETURN_NONE;
654
    }
655
    else {
656 1
        Py_INCREF(obj);
657 1
        return obj;
658
    }
659
}
660

661

662
static int
663 1
OBJECT_setitem(PyObject *op, void *ov, void *NPY_UNUSED(ap))
664
{
665
    PyObject *obj;
666

667 1
    memcpy(&obj, ov, sizeof(obj));
668

669 1
    Py_INCREF(op);
670 1
    Py_XDECREF(obj);
671

672 1
    memcpy(ov, &op, sizeof(op));
673

674 1
    return PyErr_Occurred() ? -1 : 0;
675
}
676

677
/* VOID */
678

679
static PyObject *
680 1
VOID_getitem(void *input, void *vap)
681
{
682 1
    PyArrayObject *ap = vap;
683 1
    char *ip = input;
684
    PyArray_Descr* descr;
685

686 1
    descr = PyArray_DESCR(ap);
687 1
    if (PyDataType_HASFIELDS(descr)) {
688
        PyObject *key;
689
        PyObject *names;
690
        int i, n;
691
        PyObject *ret;
692
        PyObject *tup;
693
        int savedflags;
694

695
        /* get the names from the fields dictionary*/
696 1
        names = descr->names;
697 1
        n = PyTuple_GET_SIZE(names);
698 1
        ret = PyTuple_New(n);
699 1
        savedflags = PyArray_FLAGS(ap);
700 1
        for (i = 0; i < n; i++) {
701
            npy_intp offset;
702
            PyArray_Descr *new;
703 1
            key = PyTuple_GET_ITEM(names, i);
704 1
            tup = PyDict_GetItem(descr->fields, key);
705 1
            if (_unpack_field(tup, &new, &offset) < 0) {
706 0
                Py_DECREF(ret);
707 0
                ((PyArrayObject_fields *)ap)->descr = descr;
708 0
                return NULL;
709
            }
710
            /*
711
             * TODO: temporarily modifying the array like this
712
             *       is bad coding style, should be changed.
713
             */
714 1
            ((PyArrayObject_fields *)ap)->descr = new;
715
            /* update alignment based on offset */
716 1
            if ((new->alignment > 1)
717 1
                    && ((((npy_intp)(ip+offset)) % new->alignment) != 0)) {
718
                PyArray_CLEARFLAGS(ap, NPY_ARRAY_ALIGNED);
719
            }
720
            else {
721
                PyArray_ENABLEFLAGS(ap, NPY_ARRAY_ALIGNED);
722
            }
723 1
            PyTuple_SET_ITEM(ret, i, PyArray_GETITEM(ap, ip+offset));
724 1
            ((PyArrayObject_fields *)ap)->flags = savedflags;
725
        }
726 1
        ((PyArrayObject_fields *)ap)->descr = descr;
727 1
        return ret;
728
    }
729

730 1
    if (descr->subarray) {
731
        /* return an array of the basic type */
732 1
        PyArray_Dims shape = {NULL, -1};
733
        PyArrayObject *ret;
734

735 1
        if (!(PyArray_IntpConverter(descr->subarray->shape, &shape))) {
736 0
            npy_free_cache_dim_obj(shape);
737 0
            PyErr_SetString(PyExc_ValueError,
738
                    "invalid shape in fixed-type tuple.");
739 0
            return NULL;
740
        }
741 1
        Py_INCREF(descr->subarray->base);
742 1
        ret = (PyArrayObject *)PyArray_NewFromDescrAndBase(
743
                &PyArray_Type, descr->subarray->base,
744 1
                shape.len, shape.ptr, NULL, ip,
745 1
                PyArray_FLAGS(ap) & ~NPY_ARRAY_F_CONTIGUOUS,
746
                NULL, (PyObject *)ap);
747 1
        npy_free_cache_dim_obj(shape);
748 1
        return (PyObject *)ret;
749
    }
750

751 1
    return PyBytes_FromStringAndSize(ip, descr->elsize);
752
}
753

754

755
NPY_NO_EXPORT int PyArray_CopyObject(PyArrayObject *, PyObject *);
756

757
/* Given a structured PyArrayObject arr, index i and structured datatype descr,
758
 * modify the dtype of arr to contain a single field corresponding to the ith
759
 * field of descr, recompute the alignment flag, and return the offset of the
760
 * field (in offset_p). This is useful in preparation for calling copyswap on
761
 * individual fields of a numpy structure, in VOID_setitem.  Compare to inner
762
 * loops in VOID_getitem and VOID_nonzero.
763
 *
764
 * WARNING: Clobbers arr's dtype and alignment flag.
765
 */
766
NPY_NO_EXPORT int
767 1
_setup_field(int i, PyArray_Descr *descr, PyArrayObject *arr,
768
            npy_intp *offset_p, char *dstdata)
769
{
770
    PyObject *key;
771
    PyObject *tup;
772
    PyArray_Descr *new;
773
    npy_intp offset;
774

775 1
    key = PyTuple_GET_ITEM(descr->names, i);
776 1
    tup = PyDict_GetItem(descr->fields, key);
777 1
    if (_unpack_field(tup, &new, &offset) < 0) {
778
        return -1;
779
    }
780

781 1
    ((PyArrayObject_fields *)(arr))->descr = new;
782 1
    if ((new->alignment > 1) &&
783 1
                ((((uintptr_t)dstdata + offset) % new->alignment) != 0)) {
784
        PyArray_CLEARFLAGS(arr, NPY_ARRAY_ALIGNED);
785
    }
786
    else {
787
        PyArray_ENABLEFLAGS(arr, NPY_ARRAY_ALIGNED);
788
    }
789

790 1
    *offset_p = offset;
791 1
    return 0;
792
}
793

794
/* Helper function for VOID_setitem, which uses the copyswap or casting code to
795
 * copy structured datatypes between numpy arrays or scalars.
796
 */
797
static int
798 1
_copy_and_return_void_setitem(PyArray_Descr *dstdescr, char *dstdata,
799
                              PyArray_Descr *srcdescr, char *srcdata){
800
    PyArrayObject_fields dummy_struct;
801 1
    PyArrayObject *dummy = (PyArrayObject *)&dummy_struct;
802 1
    npy_int names_size = PyTuple_GET_SIZE(dstdescr->names);
803
    npy_intp offset;
804
    npy_int i;
805
    int ret;
806

807
    /* Fast path if dtypes are equal */
808 1
    if (PyArray_EquivTypes(srcdescr, dstdescr)) {
809 1
        for (i = 0; i < names_size; i++) {
810
            /* neither line can ever fail, in principle */
811 1
            if (_setup_field(i, dstdescr, dummy, &offset, dstdata)) {
812
                return -1;
813
            }
814 1
            PyArray_DESCR(dummy)->f->copyswap(dstdata + offset,
815 1
                                              srcdata + offset, 0, dummy);
816
        }
817
        return 0;
818
    }
819

820
    /* Slow path */
821 1
    ret = PyArray_CastRawArrays(1, srcdata, dstdata, 0, 0,
822
                                srcdescr, dstdescr, 0);
823 1
    if (ret != NPY_SUCCEED) {
824
        return -1;
825
    }
826 1
    return 0;
827
}
828

829
static int
830 1
VOID_setitem(PyObject *op, void *input, void *vap)
831
{
832 1
    char *ip = input;
833 1
    PyArrayObject *ap = vap;
834
    PyArray_Descr *descr;
835
    int flags;
836 1
    int itemsize=PyArray_DESCR(ap)->elsize;
837
    int res;
838

839 1
    descr = PyArray_DESCR(ap);
840 1
    flags = PyArray_FLAGS(ap);
841 1
    if (PyDataType_HASFIELDS(descr)) {
842
        PyObject *errmsg;
843
        npy_int i;
844
        npy_intp offset;
845 1
        int failed = 0;
846

847
        /* If op is 0d-ndarray or numpy scalar, directly get dtype & data ptr */
848 1
        if (PyArray_Check(op)) {
849 1
            PyArrayObject *oparr = (PyArrayObject *)op;
850 1
            if (PyArray_SIZE(oparr) != 1) {
851 0
                PyErr_SetString(PyExc_ValueError,
852
                        "setting an array element with a sequence.");
853 0
                return -1;
854
            }
855 1
            return _copy_and_return_void_setitem(descr, ip,
856 1
                                    PyArray_DESCR(oparr), PyArray_DATA(oparr));
857
        }
858 1
        else if (PyArray_IsScalar(op, Void)) {
859 1
            PyArray_Descr *srcdescr = ((PyVoidScalarObject *)op)->descr;
860 1
            char *srcdata = ((PyVoidScalarObject *)op)->obval;
861 1
            return _copy_and_return_void_setitem(descr, ip, srcdescr, srcdata);
862
        }
863 1
        else if (PyTuple_Check(op)) {
864
            /* if it's a tuple, copy field-by-field to ap, */
865 1
            npy_intp names_size = PyTuple_GET_SIZE(descr->names);
866

867 1
            if (names_size != PyTuple_Size(op)) {
868 0
                errmsg = PyUnicode_FromFormat(
869
                        "could not assign tuple of length %zd to structure "
870
                        "with %" NPY_INTP_FMT " fields.",
871
                        PyTuple_Size(op), names_size);
872 0
                PyErr_SetObject(PyExc_ValueError, errmsg);
873 0
                Py_DECREF(errmsg);
874
                return -1;
875
            }
876

877 1
            for (i = 0; i < names_size; i++) {
878
                PyObject *item;
879

880
                /* temporarily make ap have only this field */
881 1
                if (_setup_field(i, descr, ap, &offset, ip) == -1) {
882
                    failed = 1;
883
                    break;
884
                }
885 1
                item = PyTuple_GetItem(op, i);
886 1
                if (item == NULL) {
887
                    failed = 1;
888
                    break;
889
                }
890
                /* use setitem to set this field */
891 1
                if (PyArray_SETITEM(ap, ip + offset, item) < 0) {
892
                    failed = 1;
893
                    break;
894
                }
895
            }
896
        }
897
        else {
898
            /* Otherwise must be non-void scalar. Try to assign to each field */
899 1
            npy_intp names_size = PyTuple_GET_SIZE(descr->names);
900

901 1
            for (i = 0; i < names_size; i++) {
902
                /* temporarily make ap have only this field */
903 1
                if (_setup_field(i, descr, ap, &offset, ip) == -1) {
904
                    failed = 1;
905
                    break;
906
                }
907
                /* use setitem to set this field */
908 1
                if (PyArray_SETITEM(ap, ip + offset, op) < 0) {
909
                    failed = 1;
910
                    break;
911
                }
912
            }
913
        }
914

915
        /* reset clobbered attributes */
916 1
        ((PyArrayObject_fields *)(ap))->descr = descr;
917 1
        ((PyArrayObject_fields *)(ap))->flags = flags;
918

919 1
        if (failed) {
920
            return -1;
921
        }
922 1
        return 0;
923
    }
924 1
    else if (PyDataType_HASSUBARRAY(descr)) {
925
        /* copy into an array of the same basic type */
926 1
        PyArray_Dims shape = {NULL, -1};
927
        PyArrayObject *ret;
928 1
        if (!(PyArray_IntpConverter(descr->subarray->shape, &shape))) {
929 0
            npy_free_cache_dim_obj(shape);
930 0
            PyErr_SetString(PyExc_ValueError,
931
                    "invalid shape in fixed-type tuple.");
932 0
            return -1;
933
        }
934 1
        Py_INCREF(descr->subarray->base);
935 1
        ret = (PyArrayObject *)PyArray_NewFromDescrAndBase(
936
                &PyArray_Type, descr->subarray->base,
937 1
                shape.len, shape.ptr, NULL, ip,
938
                PyArray_FLAGS(ap), NULL, (PyObject *)ap);
939 1
        npy_free_cache_dim_obj(shape);
940 1
        if (!ret) {
941
            return -1;
942
        }
943 1
        res = PyArray_CopyObject(ret, op);
944 1
        Py_DECREF(ret);
945
        return res;
946
    }
947

948
    /*
949
     * Fall through case - non-structured void datatype. This is a very
950
     * undiscerning case: It interprets any object as a buffer
951
     * and reads as many bytes as possible, padding with 0.
952
     */
953
    {
954
        Py_buffer view;
955

956 1
        if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE) < 0) {
957 0
            return -1;
958
        }
959 1
        memcpy(ip, view.buf, PyArray_MIN(view.len, itemsize));
960 1
        if (itemsize > view.len) {
961 1
            memset(ip + view.len, 0, itemsize - view.len);
962
        }
963 1
        PyBuffer_Release(&view);
964
    }
965 1
    return 0;
966
}
967

968
static PyObject *
969 1
DATETIME_getitem(void *ip, void *vap)
970
{
971 1
    PyArrayObject *ap = vap;
972
    npy_datetime dt;
973 1
    PyArray_DatetimeMetaData *meta = NULL;
974

975
    /* Get the datetime units metadata */
976 1
    meta = get_datetime_metadata_from_dtype(PyArray_DESCR(ap));
977 1
    if (meta == NULL) {
978
        return NULL;
979
    }
980

981 1
    if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) {
982 1
        dt = *((npy_datetime *)ip);
983
    }
984
    else {
985 1
        PyArray_DESCR(ap)->f->copyswap(&dt, ip, PyArray_ISBYTESWAPPED(ap), ap);
986
    }
987

988 1
    return convert_datetime_to_pyobject(dt, meta);
989
}
990

991

992
static PyObject *
993 0
TIMEDELTA_getitem(void *ip, void *vap)
994
{
995 0
    PyArrayObject *ap = vap;
996
    npy_timedelta td;
997 0
    PyArray_DatetimeMetaData *meta = NULL;
998

999
    /* Get the datetime units metadata */
1000 0
    meta = get_datetime_metadata_from_dtype(PyArray_DESCR(ap));
1001 0
    if (meta == NULL) {
1002
        return NULL;
1003
    }
1004

1005 0
    if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) {
1006 0
        td = *((npy_timedelta *)ip);
1007
    }
1008
    else {
1009 0
        PyArray_DESCR(ap)->f->copyswap(&td, ip, PyArray_ISBYTESWAPPED(ap), ap);
1010
    }
1011

1012 0
    return convert_timedelta_to_pyobject(td, meta);
1013
}
1014

1015
static int
1016 1
DATETIME_setitem(PyObject *op, void *ov, void *vap)
1017
{
1018 1
    PyArrayObject *ap = vap;
1019
    /* ensure alignment */
1020 1
    npy_datetime temp = 0;
1021 1
    PyArray_DatetimeMetaData *meta = NULL;
1022

1023
    /* Get the datetime units metadata */
1024 1
    meta = get_datetime_metadata_from_dtype(PyArray_DESCR(ap));
1025 1
    if (meta == NULL) {
1026
        return -1;
1027
    }
1028

1029
    /* Convert the object into a NumPy datetime */
1030 1
    if (convert_pyobject_to_datetime(meta, op,
1031
                            NPY_SAME_KIND_CASTING, &temp) < 0) {
1032
        return -1;
1033
    }
1034

1035
    /* Copy the value into the output */
1036 1
    if (ap == NULL || PyArray_ISBEHAVED(ap)) {
1037 1
        *((npy_datetime *)ov)=temp;
1038
    }
1039
    else {
1040 1
        PyArray_DESCR(ap)->f->copyswap(ov, &temp, PyArray_ISBYTESWAPPED(ap),
1041
                                       ap);
1042
    }
1043

1044
    return 0;
1045
}
1046

1047
static int
1048 1
TIMEDELTA_setitem(PyObject *op, void *ov, void *vap)
1049
{
1050 1
    PyArrayObject *ap = vap;
1051
    /* ensure alignment */
1052 1
    npy_timedelta temp = 0;
1053 1
    PyArray_DatetimeMetaData *meta = NULL;
1054

1055
    /* Get the datetime units metadata */
1056 1
    meta = get_datetime_metadata_from_dtype(PyArray_DESCR(ap));
1057 1
    if (meta == NULL) {
1058
        return -1;
1059
    }
1060

1061
    /* Convert the object into a NumPy datetime */
1062 1
    if (convert_pyobject_to_timedelta(meta, op,
1063
                            NPY_SAME_KIND_CASTING, &temp) < 0) {
1064
        return -1;
1065
    }
1066

1067
    /* Copy the value into the output */
1068 1
    if (ap == NULL || PyArray_ISBEHAVED(ap)) {
1069 1
        *((npy_timedelta *)ov)=temp;
1070
    }
1071
    else {
1072 1
        PyArray_DESCR(ap)->f->copyswap(ov, &temp, PyArray_ISBYTESWAPPED(ap),
1073
                                       ap);
1074
    }
1075

1076
    return 0;
1077
}
1078

1079

1080
/*
1081
 *****************************************************************************
1082
 **                       TYPE TO TYPE CONVERSIONS                          **
1083
 *****************************************************************************
1084
 */
1085

1086

1087
/* Assumes contiguous, and aligned, from and to */
1088

1089

1090
/**begin repeat
1091
 *
1092
 * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
1093
 *           LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, DATETIME,
1094
 *           TIMEDELTA#
1095
 * #totype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1096
 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1097
 *           npy_float, npy_double, npy_longdouble,
1098
 *           npy_datetime, npy_timedelta#
1099
 * #supports_nat = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1#
1100
 */
1101

1102
/**begin repeat1
1103
 *
1104
 * #FROMTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
1105
 *             LONGLONG, ULONGLONG, FLOAT, DOUBLE, LONGDOUBLE, DATETIME,
1106
 *             TIMEDELTA#
1107
 * #fromtype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1108
 *             npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1109
 *             npy_float, npy_double, npy_longdouble,
1110
 *             npy_datetime, npy_timedelta#
1111
 * #floatingpoint = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0#
1112
 */
1113
static void
1114 1
@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
1115
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1116
{
1117 1
    const @fromtype@ *ip = input;
1118 1
    @totype@ *op = output;
1119

1120 1
    while (n--) {
1121 1
        @fromtype@ f = *ip++;
1122 1
        @totype@ t = (@totype@)f;
1123
#if @supports_nat@ && @floatingpoint@
1124
        /* Avoid undefined behaviour for NaN -> NaT */
1125 1
        if (npy_isnan(f)) {
1126 1
            t = (@totype@)NPY_DATETIME_NAT;
1127
        }
1128
#endif
1129 1
        *op++ = t;
1130
    }
1131 1
}
1132
/**end repeat1**/
1133

1134
/**begin repeat1
1135
 *
1136
 * #FROMTYPE = CFLOAT, CDOUBLE, CLONGDOUBLE#
1137
 * #fromtype = npy_float, npy_double, npy_longdouble#
1138
 */
1139
static void
1140 1
@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
1141
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1142
{
1143 1
    const @fromtype@ *ip = input;
1144 1
    @totype@ *op = output;
1145

1146 1
    while (n--) {
1147 1
        @fromtype@ f = *ip;
1148 1
        @totype@ t = (@totype@)f;
1149
#if @supports_nat@
1150
        /* Avoid undefined behaviour for NaN -> NaT */
1151 1
        if (npy_isnan(f)) {
1152 1
            t = (@totype@)NPY_DATETIME_NAT;
1153
        }
1154
#endif
1155 1
        *op++ = t;
1156 1
        ip += 2;
1157
    }
1158 1
}
1159
/**end repeat1**/
1160

1161
/**end repeat**/
1162

1163

1164
/**begin repeat
1165
 *
1166
 * #TYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT, LONG, ULONG,
1167
 *         LONGLONG, ULONGLONG, LONGDOUBLE, DATETIME,
1168
 *         TIMEDELTA#
1169
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1170
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1171
 *         npy_longdouble,
1172
 *         npy_datetime, npy_timedelta#
1173
 */
1174

1175
static void
1176 1
@TYPE@_to_HALF(void *input, void *output, npy_intp n,
1177
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1178
{
1179 1
    const @type@ *ip = input;
1180 1
    npy_half *op = output;
1181

1182 1
    while (n--) {
1183 1
        *op++ = npy_float_to_half((float)(*ip++));
1184
    }
1185 1
}
1186

1187
static void
1188 1
HALF_to_@TYPE@(void *input, void *output, npy_intp n,
1189
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1190
{
1191 1
    const npy_half *ip = input;
1192 1
    @type@ *op = output;
1193

1194 1
    while (n--) {
1195 1
        *op++ = (@type@)npy_half_to_float(*ip++);
1196
    }
1197 1
}
1198

1199
/**end repeat**/
1200
#if NPY_SIZEOF_SHORT == 2
1201
#define HALF_to_HALF SHORT_to_SHORT
1202
#elif NPY_SIZEOF_INT == 2
1203
#define HALF_to_HALF INT_to_INT
1204
#endif
1205

1206
/**begin repeat
1207
 *
1208
 * #TYPE = FLOAT, DOUBLE, CFLOAT, CDOUBLE#
1209
 * #name = float, double, float, double#
1210
 * #itype = npy_uint32, npy_uint64, npy_uint32, npy_uint64#
1211
 * #iscomplex = 0, 0, 1, 1#
1212
 */
1213

1214
static void
1215 0
@TYPE@_to_HALF(void *input, void *output, npy_intp n,
1216
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1217
{
1218 0
    const @itype@ *ip = input;
1219 0
    npy_half *op = output;
1220

1221 0
    while (n--) {
1222 0
        *op++ = npy_@name@bits_to_halfbits(*ip);
1223
#if @iscomplex@
1224 0
        ip += 2;
1225
#else
1226 0
        ip++;
1227
#endif
1228
    }
1229 0
}
1230

1231
static void
1232 1
HALF_to_@TYPE@(void *input, void *output, npy_intp n,
1233
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1234
{
1235 1
    const npy_half *ip = input;
1236 1
    @itype@ *op = output;
1237

1238 1
    while (n--) {
1239 1
        *op++ = npy_halfbits_to_@name@bits(*ip++);
1240
#if @iscomplex@
1241 0
        *op++ = 0;
1242
#endif
1243
    }
1244 1
}
1245

1246
/**end repeat**/
1247

1248
static void
1249 0
CLONGDOUBLE_to_HALF(void *input, void *output, npy_intp n,
1250
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1251
{
1252 0
    const npy_longdouble *ip = input;
1253 0
    npy_half *op = output;
1254

1255 0
    while (n--) {
1256 0
        *op++ = npy_double_to_half((double) (*ip++));
1257 0
        ip += 2;
1258
    }
1259 0
}
1260

1261
static void
1262 0
HALF_to_CLONGDOUBLE(void *input, void *output, npy_intp n,
1263
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1264
{
1265 0
    const npy_half *ip = input;
1266 0
    npy_longdouble *op = output;
1267

1268 0
    while (n--) {
1269 0
        *op++ = npy_half_to_double(*ip++);
1270 0
        *op++ = 0;
1271
    }
1272 0
}
1273

1274
/**begin repeat
1275
 *
1276
 * #FROMTYPE = BOOL,
1277
 *             BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1278
 *             LONG, ULONG, LONGLONG, ULONGLONG,
1279
 *             FLOAT, DOUBLE, LONGDOUBLE,
1280
 *             DATETIME, TIMEDELTA#
1281
 * #fromtype = npy_bool,
1282
 *             npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1283
 *             npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1284
 *             npy_float, npy_double, npy_longdouble,
1285
 *             npy_datetime, npy_timedelta#
1286
 */
1287
static void
1288 1
@FROMTYPE@_to_BOOL(void *input, void *output, npy_intp n,
1289
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1290
{
1291 1
    const @fromtype@ *ip = input;
1292 1
    npy_bool *op = output;
1293

1294 1
    while (n--) {
1295 1
        *op++ = (npy_bool)(*ip++ != NPY_FALSE);
1296
    }
1297 1
}
1298
/**end repeat**/
1299

1300
static void
1301 0
HALF_to_BOOL(void *input, void *output, npy_intp n,
1302
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1303
{
1304 0
    const npy_half *ip = input;
1305 0
    npy_bool *op = output;
1306

1307 0
    while (n--) {
1308 0
        *op++ = (npy_bool)(!npy_half_iszero(*ip++));
1309
    }
1310 0
}
1311

1312
/**begin repeat
1313
 *
1314
 * #FROMTYPE = CFLOAT, CDOUBLE, CLONGDOUBLE#
1315
 * #fromtype = npy_cfloat, npy_cdouble, npy_clongdouble#
1316
 */
1317
static void
1318 0
@FROMTYPE@_to_BOOL(void *input, void *output, npy_intp n,
1319
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1320
{
1321 0
    const @fromtype@ *ip = input;
1322 0
    npy_bool *op = output;
1323

1324 0
    while (n--) {
1325 0
        *op = (npy_bool)((ip->real != NPY_FALSE) ||
1326 0
                (ip->imag != NPY_FALSE));
1327 0
        op++;
1328 0
        ip++;
1329
    }
1330 0
}
1331
/**end repeat**/
1332

1333
/**begin repeat
1334
 * #TOTYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1335
 *           LONG, ULONG, LONGLONG, ULONGLONG,
1336
 *           HALF, FLOAT, DOUBLE, LONGDOUBLE,
1337
 *           DATETIME, TIMEDELTA#
1338
 * #totype = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1339
 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1340
 *           npy_half, npy_float, npy_double, npy_longdouble,
1341
 *           npy_datetime, npy_timedelta#
1342
 * #one = 1*10, NPY_HALF_ONE, 1*5#
1343
 * #zero = 0*10, NPY_HALF_ZERO, 0*5#
1344
 */
1345
static void
1346 1
BOOL_to_@TOTYPE@(void *input, void *output, npy_intp n,
1347
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1348
{
1349 1
    const npy_bool *ip = input;
1350 1
    @totype@ *op = output;
1351

1352 1
    while (n--) {
1353 1
        *op++ = (@totype@)((*ip++ != NPY_FALSE) ? @one@ : @zero@);
1354
    }
1355 1
}
1356
/**end repeat**/
1357

1358
/**begin repeat
1359
 *
1360
 * #TOTYPE = CFLOAT, CDOUBLE,CLONGDOUBLE#
1361
 * #totype = npy_float, npy_double, npy_longdouble#
1362
 */
1363

1364
/**begin repeat1
1365
 * #FROMTYPE = BOOL,
1366
 *             BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1367
 *             LONG, ULONG, LONGLONG, ULONGLONG,
1368
 *             FLOAT, DOUBLE, LONGDOUBLE,
1369
 *             DATETIME, TIMEDELTA#
1370
 * #fromtype = npy_bool,
1371
 *             npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1372
 *             npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1373
 *             npy_float, npy_double, npy_longdouble,
1374
 *             npy_datetime, npy_timedelta#
1375
 */
1376
static void
1377 1
@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
1378
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1379
{
1380 1
    const @fromtype@ *ip = input;
1381 1
    @totype@ *op = output;
1382

1383 1
    while (n--) {
1384 1
        *op++ = (@totype@)*ip++;
1385 1
        *op++ = 0.0;
1386
    }
1387

1388 1
}
1389
/**end repeat1**/
1390
/**end repeat**/
1391

1392
/**begin repeat
1393
 *
1394
 * #TOTYPE = CFLOAT,CDOUBLE,CLONGDOUBLE#
1395
 * #totype = npy_float, npy_double, npy_longdouble#
1396
 */
1397

1398
/**begin repeat1
1399
 * #FROMTYPE = CFLOAT,CDOUBLE,CLONGDOUBLE#
1400
 * #fromtype = npy_float, npy_double, npy_longdouble#
1401
 */
1402
static void
1403 1
@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n,
1404
        void *NPY_UNUSED(aip), void *NPY_UNUSED(aop))
1405
{
1406 1
    const @fromtype@ *ip = input;
1407 1
    @totype@ *op = output;
1408

1409 1
    n <<= 1;
1410 1
    while (n--) {
1411 1
        *op++ = (@totype@)*ip++;
1412
    }
1413 1
}
1414

1415
/**end repeat1**/
1416
/**end repeat**/
1417

1418
/**begin repeat
1419
 *
1420
 * #FROMTYPE = BOOL,
1421
 *             BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1422
 *             LONG, ULONG, LONGLONG, ULONGLONG,
1423
 *             HALF, FLOAT, DOUBLE, LONGDOUBLE,
1424
 *             CFLOAT, CDOUBLE, CLONGDOUBLE,
1425
 *             STRING, UNICODE, VOID, OBJECT,
1426
 *             DATETIME, TIMEDELTA#
1427
 * #fromtype = npy_bool,
1428
 *             npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1429
 *             npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1430
 *             npy_half, npy_float, npy_double, npy_longdouble,
1431
 *             npy_cfloat, npy_cdouble, npy_clongdouble,
1432
 *             npy_char, npy_char, npy_char, PyObject *,
1433
 *             npy_datetime, npy_timedelta#
1434
 * #skip = 1*18, PyArray_DESCR(aip)->elsize*3, 1*3#
1435
 */
1436
static void
1437 1
@FROMTYPE@_to_OBJECT(void *input, void *output, npy_intp n,
1438
        void *vaip, void *NPY_UNUSED(aop))
1439
{
1440 1
    @fromtype@ *ip = input;
1441 1
    PyObject **op = output;
1442 1
    PyArrayObject *aip = vaip;
1443

1444
    npy_intp i;
1445 1
    int skip = @skip@;
1446
    PyObject *tmp;
1447 1
    for (i = 0; i < n; i++, ip +=skip, op++) {
1448 1
        tmp = *op;
1449 1
        *op = @FROMTYPE@_getitem(ip, aip);
1450 1
        Py_XDECREF(tmp);
1451
    }
1452 1
}
1453
/**end repeat**/
1454

1455
#define _NPY_UNUSEDBOOL  NPY_UNUSED
1456
#define _NPY_UNUSEDBYTE  NPY_UNUSED
1457
#define _NPY_UNUSEDUBYTE  NPY_UNUSED
1458
#define _NPY_UNUSEDSHORT  NPY_UNUSED
1459
#define _NPY_UNUSEDUSHORT  NPY_UNUSED
1460
#define _NPY_UNUSEDINT  NPY_UNUSED
1461
#define _NPY_UNUSEDUINT  NPY_UNUSED
1462
#define _NPY_UNUSEDLONG  NPY_UNUSED
1463
#define _NPY_UNUSEDULONG  NPY_UNUSED
1464
#define _NPY_UNUSEDLONGLONG  NPY_UNUSED
1465
#define _NPY_UNUSEDULONGLONG  NPY_UNUSED
1466
#define _NPY_UNUSEDHALF NPY_UNUSED
1467
#define _NPY_UNUSEDFLOAT  NPY_UNUSED
1468
#define _NPY_UNUSEDDOUBLE  NPY_UNUSED
1469
#define _NPY_UNUSEDLONGDOUBLE  NPY_UNUSED
1470
#define _NPY_UNUSEDCFLOAT  NPY_UNUSED
1471
#define _NPY_UNUSEDCDOUBLE  NPY_UNUSED
1472
#define _NPY_UNUSEDCLONGDOUBLE  NPY_UNUSED
1473
#define _NPY_UNUSEDDATETIME  NPY_UNUSED
1474
#define _NPY_UNUSEDTIMEDELTA  NPY_UNUSED
1475
#define _NPY_UNUSEDHALF NPY_UNUSED
1476
#define _NPY_UNUSEDSTRING
1477
#define _NPY_UNUSEDVOID
1478
#define _NPY_UNUSEDUNICODE
1479

1480
/**begin repeat
1481
 *
1482
 * #TOTYPE = BOOL,
1483
 *           BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1484
 *           LONG, ULONG, LONGLONG, ULONGLONG,
1485
 *           HALF, FLOAT, DOUBLE, LONGDOUBLE,
1486
 *           CFLOAT, CDOUBLE, CLONGDOUBLE,
1487
 *           STRING, UNICODE, VOID,
1488
 *           DATETIME, TIMEDELTA#
1489
 * #totype = npy_bool,
1490
 *           npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1491
 *           npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1492
 *           npy_half, npy_float, npy_double, npy_longdouble,
1493
 *           npy_cfloat, npy_cdouble, npy_clongdouble,
1494
 *           npy_char, npy_char, npy_char,
1495
 *           npy_datetime, npy_timedelta#
1496
 * #skip = 1*18, PyArray_DESCR(aop)->elsize*3, 1*2#
1497
 */
1498
static void
1499 1
OBJECT_to_@TOTYPE@(void *input, void *output, npy_intp n,
1500
        void *NPY_UNUSED(aip), void *aop)
1501
{
1502 1
    PyObject **ip = input;
1503 1
    @totype@ *op = output;
1504

1505
    npy_intp i;
1506 1
    int skip = @skip@;
1507

1508 1
    for (i = 0; i < n; i++, ip++, op += skip) {
1509 1
        if (*ip == NULL) {
1510 0
            if (@TOTYPE@_setitem(Py_False, op, aop) < 0) {
1511
                return;
1512
            }
1513
        }
1514
        else {
1515 1
            if (@TOTYPE@_setitem(*ip, op, aop) < 0) {
1516
                return;
1517
            }
1518
        }
1519
    }
1520
}
1521
/**end repeat**/
1522

1523

1524
/**begin repeat
1525
 *
1526
 * #from = STRING*23, UNICODE*23, VOID*23#
1527
 * #fromtyp = npy_char*69#
1528
 * #is_string_to_bool = 1, 0*22, 1, 0*22, 0*23#
1529
 * #to = (BOOL,
1530
 *           BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1531
 *           LONG, ULONG, LONGLONG, ULONGLONG,
1532
 *           HALF, FLOAT, DOUBLE, LONGDOUBLE,
1533
 *           CFLOAT, CDOUBLE, CLONGDOUBLE,
1534
 *           STRING, UNICODE, VOID,
1535
 *           DATETIME, TIMEDELTA)*3#
1536
 * #totyp = (npy_bool,
1537
 *              npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1538
 *              npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1539
 *              npy_half, npy_float, npy_double, npy_longdouble,
1540
 *              npy_cfloat, npy_cdouble, npy_clongdouble,
1541
 *              npy_char, npy_char, npy_char,
1542
 *              npy_datetime, npy_timedelta)*3#
1543
 * #oskip = 1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
1544
 *          1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
1545
 *          1*18,(PyArray_DESCR(aop)->elsize)*3,1*2#
1546
 */
1547

1548
static void
1549 1
@from@_to_@to@(void *input, void *output, npy_intp n,
1550
        void *vaip, void *aop)
1551
{
1552 1
    @fromtyp@ *ip = input;
1553 1
    @totyp@ *op = output;
1554 1
    PyArrayObject *aip = vaip;
1555

1556
    npy_intp i;
1557 1
    int skip = PyArray_DESCR(aip)->elsize;
1558 1
    int oskip = @oskip@;
1559

1560 1
    for (i = 0; i < n; i++, ip+=skip, op+=oskip) {
1561 1
        PyObject *temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
1562 1
        if (temp == NULL) {
1563
            return;
1564
        }
1565
#if @is_string_to_bool@
1566
        /* Legacy behaviour converts strings to integers before going to bool */
1567 1
        Py_SETREF(temp, PyNumber_Long(temp));
1568 1
        if (temp == NULL) {
1569
            return;
1570
        }
1571
#endif
1572 1
        if (@to@_setitem(temp, op, aop)) {
1573 1
            Py_DECREF(temp);
1574
            return;
1575
        }
1576 1
        Py_DECREF(temp);
1577
    }
1578
}
1579

1580

1581
/**end repeat**/
1582

1583

1584
/**begin repeat
1585
 *
1586
 * #to = STRING*20, UNICODE*20, VOID*20#
1587
 * #totyp = npy_char*20, npy_char*20, npy_char*20#
1588
 * #from = (BOOL,
1589
 *             BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1590
 *             LONG, ULONG, LONGLONG, ULONGLONG,
1591
 *             HALF, FLOAT, DOUBLE, LONGDOUBLE,
1592
 *             CFLOAT, CDOUBLE, CLONGDOUBLE,
1593
 *             DATETIME, TIMEDELTA)*3#
1594
 * #fromtyp = (npy_bool,
1595
 *               npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1596
 *               npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1597
 *               npy_half, npy_float, npy_double, npy_longdouble,
1598
 *               npy_cfloat, npy_cdouble, npy_clongdouble,
1599
 *               npy_datetime, npy_timedelta)*3#
1600
 */
1601
static void
1602 1
@from@_to_@to@(void *input, void *output, npy_intp n,
1603
        void *vaip, void *vaop)
1604
{
1605 1
    @fromtyp@ *ip = input;
1606 1
    @totyp@ *op = output;
1607 1
    PyArrayObject *aip = vaip;
1608 1
    PyArrayObject *aop = vaop;
1609

1610
    npy_intp i;
1611 1
    PyObject *temp = NULL;
1612 1
    int skip = 1;
1613 1
    int oskip = PyArray_DESCR(aop)->elsize;
1614 1
    for (i = 0; i < n; i++, ip += skip, op += oskip) {
1615 1
        temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
1616 1
        if (temp == NULL) {
1617 0
            Py_INCREF(Py_False);
1618 0
            temp = Py_False;
1619
        }
1620 1
        if (@to@_setitem(temp, op, aop)) {
1621 0
            Py_DECREF(temp);
1622
            return;
1623
        }
1624 1
        Py_DECREF(temp);
1625
    }
1626
}
1627

1628
/**end repeat**/
1629

1630

1631
/*
1632
 *****************************************************************************
1633
 **                               SCAN                                      **
1634
 *****************************************************************************
1635
 */
1636

1637

1638
/*
1639
 * The first ignore argument is for backwards compatibility.
1640
 * Should be removed when the API version is bumped up.
1641
 */
1642

1643
/**begin repeat
1644
 * #fname = SHORT, USHORT, INT, UINT,
1645
 *          LONG, ULONG, LONGLONG, ULONGLONG#
1646
 * #type = npy_short, npy_ushort, npy_int, npy_uint,
1647
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong#
1648
 * #format = "hd", "hu", "d", "u",
1649
 *           "ld", "lu", NPY_LONGLONG_FMT, NPY_ULONGLONG_FMT#
1650
 */
1651
static int
1652 1
@fname@_scan(FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore),
1653
        PyArray_Descr *NPY_UNUSED(ignored))
1654
{
1655 1
    return fscanf(fp, "%"@format@, ip);
1656
}
1657
/**end repeat**/
1658

1659
/**begin repeat
1660
 * #fname = FLOAT, DOUBLE#
1661
 * #type = npy_float, npy_double#
1662
 */
1663
static int
1664 1
@fname@_scan(FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore),
1665
        PyArray_Descr *NPY_UNUSED(ignored))
1666
{
1667
    double result;
1668
    int ret;
1669

1670 1
    ret = NumPyOS_ascii_ftolf(fp, &result);
1671 1
    *ip = (@type@) result;
1672 1
    return ret;
1673
}
1674
/**end repeat**/
1675

1676
static int
1677 1
LONGDOUBLE_scan(FILE *fp, npy_longdouble *ip, void *NPY_UNUSED(ignore),
1678
        PyArray_Descr *NPY_UNUSED(ignored))
1679
{
1680
    long double result;
1681
    int ret;
1682

1683 1
    ret = NumPyOS_ascii_ftoLf(fp, &result);
1684 1
    *ip = (npy_longdouble) result;
1685 1
    return ret;
1686
}
1687

1688
static int
1689 0
HALF_scan(FILE *fp, npy_half *ip, void *NPY_UNUSED(ignore),
1690
        PyArray_Descr *NPY_UNUSED(ignored))
1691
{
1692
    double result;
1693
    int ret;
1694

1695 0
    ret = NumPyOS_ascii_ftolf(fp, &result);
1696 0
    *ip = npy_double_to_half(result);
1697 0
    return ret;
1698
}
1699

1700
/**begin repeat
1701
 * #fname = BYTE, UBYTE#
1702
 * #type = npy_byte, npy_ubyte#
1703
 * #btype = npy_int, npy_uint#
1704
 * #format = "d", "u"#
1705
 */
1706
static int
1707 0
@fname@_scan(FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore),
1708
        PyArray_Descr *NPY_UNUSED(ignore2))
1709
{
1710
    @btype@ temp;
1711
    int num;
1712

1713 0
    num = fscanf(fp, "%"@format@, &temp);
1714 0
    *ip = (@type@) temp;
1715 0
    return num;
1716
}
1717
/**end repeat**/
1718

1719
static int
1720 1
BOOL_scan(FILE *fp, npy_bool *ip, void *NPY_UNUSED(ignore),
1721
        PyArray_Descr *NPY_UNUSED(ignore2))
1722
{
1723
    double result;
1724
    int ret;
1725

1726 1
    ret = NumPyOS_ascii_ftolf(fp, &result);
1727 1
    *ip = (npy_bool) (result != 0.0);
1728 1
    return ret;
1729
}
1730

1731
/**begin repeat
1732
 * #fname = CFLOAT, CDOUBLE#
1733
 * #type = npy_cfloat, npy_cdouble#
1734
 */
1735
static int
1736 1
@fname@_scan(FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore),
1737
             PyArray_Descr *NPY_UNUSED(ignored))
1738
{
1739
    double result;
1740
    int ret_real, ret_imag;
1741

1742 1
    ret_real = NumPyOS_ascii_ftolf(fp, &result);
1743
    @type@ output;
1744
    // Peek next character
1745 1
    char next = getc(fp);
1746 1
    if ((next == '+') || (next == '-')) {
1747
        // Imaginary component specified
1748 1
        output.real = result;
1749
        // Revert peek and read imaginary component
1750 1
        ungetc(next, fp);
1751 1
        ret_imag = NumPyOS_ascii_ftolf(fp, &result);
1752
        // Peak next character
1753 1
        next = getc(fp);
1754 1
        if ((ret_imag == 1) && (next == 'j')) {
1755
            // If read is successful and the immediate following char is j
1756 1
            output.imag = result;
1757
        }
1758
        else {
1759 1
            output.imag = 0;
1760
            // Push an invalid char to trigger the not everything is read error
1761 1
            ungetc('a', fp);
1762
        }
1763
    }
1764 1
    else if (next == 'j') {
1765
        // Real component not specified
1766 1
        output.real = 0;
1767 1
        output.imag = result;
1768
    }
1769
    else {
1770
        // Imaginary component not specified
1771 1
        output.real = result;
1772 1
        output.imag = 0.;
1773
        // Next character is not + / - / j. Revert peek.
1774 1
        ungetc(next, fp);
1775
    }
1776 1
    *(@type@ *)ip = output;
1777 1
    return ret_real;
1778
}
1779
/**end repeat**/
1780

1781

1782
/**begin repeat
1783
 * #fname = CLONGDOUBLE,
1784
 *          OBJECT, STRING, UNICODE, VOID,
1785
 *          DATETIME, TIMEDELTA#
1786
 */
1787

1788
#define @fname@_scan NULL
1789

1790
/**end repeat**/
1791

1792

1793
/*
1794
 *****************************************************************************
1795
 **                             FROMSTR                                     **
1796
 *****************************************************************************
1797
 */
1798

1799

1800
/**begin repeat
1801
 * #fname = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
1802
 *          LONG, ULONG, LONGLONG, ULONGLONG,
1803
 *          DATETIME, TIMEDELTA#
1804
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
1805
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1806
 *         npy_datetime, npy_timedelta#
1807
 * #func = (PyOS_strtol, PyOS_strtoul)*4, NumPyOS_strtoll, NumPyOS_strtoull,
1808
 *         NumPyOS_strtoll*2#
1809
 * #btype = (npy_long, npy_ulong)*4, npy_longlong, npy_ulonglong,
1810
 *          npy_longlong*2#
1811
 */
1812
static int
1813 1
@fname@_fromstr(char *str, void *ip, char **endptr,
1814
        PyArray_Descr *NPY_UNUSED(ignore))
1815
{
1816
    @btype@ result;
1817

1818 1
    result = @func@(str, endptr, 10);
1819 1
    *(@type@ *)ip = result;
1820 1
    return 0;
1821
}
1822
/**end repeat**/
1823

1824
/**begin repeat
1825
 *
1826
 * #fname = FLOAT, DOUBLE#
1827
 * #type = npy_float, npy_double#
1828
 */
1829
static int
1830 1
@fname@_fromstr(char *str, void *ip, char **endptr,
1831
        PyArray_Descr *NPY_UNUSED(ignore))
1832
{
1833
    double result;
1834

1835 1
    result = NumPyOS_ascii_strtod(str, endptr);
1836 1
    *(@type@ *)ip = result;
1837 1
    return 0;
1838
}
1839
/**end repeat**/
1840

1841
static int
1842 1
LONGDOUBLE_fromstr(char *str, void *ip, char **endptr,
1843
        PyArray_Descr *NPY_UNUSED(ignore))
1844
{
1845
    long double result;
1846

1847 1
    result = NumPyOS_ascii_strtold(str, endptr);
1848 1
    *(npy_longdouble *)ip = result;
1849 1
    return 0;
1850
}
1851

1852
static int
1853 0
HALF_fromstr(char *str, void *ip, char **endptr,
1854
        PyArray_Descr *NPY_UNUSED(ignore))
1855
{
1856
    double result;
1857

1858 0
    result = NumPyOS_ascii_strtod(str, endptr);
1859 0
    *(npy_half *)ip = npy_double_to_half(result);
1860 0
    return 0;
1861
}
1862

1863
static int
1864 1
BOOL_fromstr(char *str, void *ip, char **endptr,
1865
        PyArray_Descr *NPY_UNUSED(ignore))
1866
{
1867
    double result;
1868

1869 1
    result = NumPyOS_ascii_strtod(str, endptr);
1870 1
    *(npy_bool *)ip = (result != 0.0);
1871 1
    return 0;
1872
}
1873

1874
/**begin repeat
1875
 * #fname = CFLOAT, CDOUBLE#
1876
 * #type = npy_cfloat, npy_cdouble#
1877
 */
1878
static int
1879 1
@fname@_fromstr(char *str, void *ip, char **endptr,
1880
        PyArray_Descr *NPY_UNUSED(ignore))
1881
{
1882
    double result;
1883

1884 1
    result = NumPyOS_ascii_strtod(str, endptr);
1885
    @type@ output;
1886

1887 1
    if (endptr && ((*endptr[0] == '+') || (*endptr[0] == '-'))) {
1888
        // Imaginary component specified
1889 1
        output.real = result;
1890
        // Reading imaginary component
1891 1
        char **prev = endptr;
1892 1
        str = *endptr;
1893 1
        result = NumPyOS_ascii_strtod(str, endptr);
1894 1
        if (endptr && *endptr[0] == 'j') {
1895
            // Read is successful if the immediate following char is j
1896 1
            output.imag = result;
1897
            // Skip j
1898 1
            ++*endptr;
1899
        }
1900
        else {
1901
            /*
1902
             * Set endptr to previous char to trigger the not everything is
1903
             * read error
1904
             */
1905
            endptr = prev;
1906
            output.imag = 0;
1907
        }
1908
    }
1909 1
    else if (endptr && *endptr[0] == 'j') {
1910
        // Real component not specified
1911 1
        output.real = 0;
1912 1
        output.imag = result;
1913
        // Skip j
1914 1
        ++*endptr;
1915
    }
1916
    else {
1917
        // Imaginary component not specified
1918 0
        output.real = result;
1919 0
        output.imag = 0.;
1920
    }
1921 1
    *(@type@ *)ip = output;
1922 1
    return 0;
1923
}
1924
/**end repeat**/
1925

1926

1927
/**begin repeat
1928
 * #fname = CLONGDOUBLE,
1929
 *          OBJECT, STRING, UNICODE, VOID#
1930
 */
1931

1932
#define @fname@_fromstr NULL
1933

1934
/**end repeat**/
1935

1936

1937
/*
1938
 *****************************************************************************
1939
 **                            COPYSWAPN                                    **
1940
 *****************************************************************************
1941
 */
1942

1943

1944
static NPY_INLINE void
1945 1
_basic_copyn(void *dst, npy_intp dstride, void *src, npy_intp sstride,
1946
             npy_intp n, int elsize) {
1947 1
    if (src == NULL) {
1948
        return;
1949
    }
1950 1
    if (sstride == elsize && dstride == elsize) {
1951 1
        memcpy(dst, src, n*elsize);
1952
    }
1953
    else {
1954 1
        _unaligned_strided_byte_copy(dst, dstride, src, sstride,
1955
                n, elsize);
1956
    }
1957
}
1958

1959
static NPY_INLINE void
1960
_basic_copy(void *dst, void *src, int elsize) {
1961 1
    if (src == NULL) {
1962
        return;
1963
    }
1964 1
    memcpy(dst, src, elsize);
1965
}
1966

1967

1968
/**begin repeat
1969
 *
1970
 * #fname = SHORT, USHORT, INT, UINT,
1971
 *          LONG, ULONG, LONGLONG, ULONGLONG,
1972
 *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
1973
 *          DATETIME, TIMEDELTA#
1974
 * #fsize = SHORT, SHORT, INT, INT,
1975
 *          LONG, LONG, LONGLONG, LONGLONG,
1976
 *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
1977
 *          DATETIME, TIMEDELTA#
1978
 * #type = npy_short, npy_ushort, npy_int, npy_uint,
1979
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
1980
 *         npy_half, npy_float, npy_double, npy_longdouble,
1981
 *         npy_datetime, npy_timedelta#
1982
 */
1983
static void
1984 1
@fname@_copyswapn (void *dst, npy_intp dstride, void *src, npy_intp sstride,
1985
                   npy_intp n, int swap, void *NPY_UNUSED(arr))
1986
{
1987
    /* copy first if needed */
1988 1
    _basic_copyn(dst, dstride, src, sstride, n, sizeof(@type@));
1989 1
    if (swap) {
1990 1
        _strided_byte_swap(dst, dstride, n, sizeof(@type@));
1991
    }
1992 1
}
1993

1994
static void
1995 1
@fname@_copyswap (void *dst, void *src, int swap, void *NPY_UNUSED(arr))
1996
{
1997
    /* copy first if needed */
1998 1
    _basic_copy(dst, src, sizeof(@type@));
1999

2000 1
    if (swap) {
2001
        char *a, *b, c;
2002

2003 1
        a = (char *)dst;
2004
#if NPY_SIZEOF_@fsize@ == 2
2005 1
        b = a + 1;
2006 1
        c = *a; *a++ = *b; *b = c;
2007
#elif NPY_SIZEOF_@fsize@ == 4
2008 1
        b = a + 3;
2009 1
        c = *a; *a++ = *b; *b-- = c;
2010 1
        c = *a; *a++ = *b; *b   = c;
2011
#elif NPY_SIZEOF_@fsize@ == 8
2012 1
        b = a + 7;
2013 1
        c = *a; *a++ = *b; *b-- = c;
2014 1
        c = *a; *a++ = *b; *b-- = c;
2015 1
        c = *a; *a++ = *b; *b-- = c;
2016 1
        c = *a; *a++ = *b; *b   = c;
2017
#elif NPY_SIZEOF_@fsize@ == 10
2018
        b = a + 9;
2019
        c = *a; *a++ = *b; *b-- = c;
2020
        c = *a; *a++ = *b; *b-- = c;
2021
        c = *a; *a++ = *b; *b-- = c;
2022
        c = *a; *a++ = *b; *b-- = c;
2023
        c = *a; *a++ = *b; *b   = c;
2024
#elif NPY_SIZEOF_@fsize@ == 12
2025
        b = a + 11;
2026
        c = *a; *a++ = *b; *b-- = c;
2027
        c = *a; *a++ = *b; *b-- = c;
2028
        c = *a; *a++ = *b; *b-- = c;
2029
        c = *a; *a++ = *b; *b-- = c;
2030
        c = *a; *a++ = *b; *b-- = c;
2031
        c = *a; *a++ = *b; *b   = c;
2032
#elif NPY_SIZEOF_@fsize@ == 16
2033 1
        b = a + 15;
2034 1
        c = *a; *a++ = *b; *b-- = c;
2035 1
        c = *a; *a++ = *b; *b-- = c;
2036 1
        c = *a; *a++ = *b; *b-- = c;
2037 1
        c = *a; *a++ = *b; *b-- = c;
2038 1
        c = *a; *a++ = *b; *b-- = c;
2039 1
        c = *a; *a++ = *b; *b-- = c;
2040 1
        c = *a; *a++ = *b; *b-- = c;
2041 1
        c = *a; *a++ = *b; *b   = c;
2042
#else
2043
        {
2044
            int i, nn;
2045

2046
            b = a + (NPY_SIZEOF_@fsize@-1);
2047
            nn = NPY_SIZEOF_@fsize@ / 2;
2048
            for (i = 0; i < nn; i++) {
2049
                c = *a;
2050
                *a++ = *b;
2051
                *b-- = c;
2052
            }
2053
        }
2054
#endif
2055
    }
2056 1
}
2057

2058
/**end repeat**/
2059

2060
/**begin repeat
2061
 *
2062
 * #fname = BOOL,
2063
 *          BYTE, UBYTE#
2064
 * #type = npy_bool,
2065
 *         npy_byte, npy_ubyte#
2066
 */
2067
static void
2068 1
@fname@_copyswapn (void *dst, npy_intp dstride, void *src, npy_intp sstride,
2069
        npy_intp n, int NPY_UNUSED(swap), void *NPY_UNUSED(arr))
2070
{
2071
    /* copy first if needed */
2072 1
    _basic_copyn(dst, dstride, src, sstride, n, sizeof(@type@));
2073
    /* ignore swap */
2074 1
}
2075

2076
static void
2077 1
@fname@_copyswap (void *dst, void *src, int NPY_UNUSED(swap),
2078
        void *NPY_UNUSED(arr))
2079
{
2080
    /* copy first if needed */
2081 1
    _basic_copy(dst, src, sizeof(@type@));
2082
    /* ignore swap */
2083 1
}
2084

2085
/**end repeat**/
2086

2087

2088

2089
/**begin repeat
2090
 *
2091
 * #fname = CFLOAT, CDOUBLE, CLONGDOUBLE#
2092
 * #fsize = FLOAT, DOUBLE, LONGDOUBLE#
2093
 * #type = npy_cfloat, npy_cdouble, npy_clongdouble#
2094
*/
2095
static void
2096 1
@fname@_copyswapn (void *dst, npy_intp dstride, void *src, npy_intp sstride,
2097
        npy_intp n, int swap, void *NPY_UNUSED(arr))
2098
{
2099
    /* copy first if needed */
2100 1
    _basic_copyn(dst, dstride, src, sstride, n, sizeof(@type@));
2101

2102 1
    if (swap) {
2103 1
        _strided_byte_swap(dst, dstride, n, NPY_SIZEOF_@fsize@);
2104 1
        _strided_byte_swap(((char *)dst + NPY_SIZEOF_@fsize@), dstride,
2105
                n, NPY_SIZEOF_@fsize@);
2106
    }
2107 1
}
2108

2109
static void
2110 1
@fname@_copyswap (void *dst, void *src, int swap, void *NPY_UNUSED(arr))
2111
{
2112
    /* copy first if needed */
2113 1
    _basic_copy(dst, src, sizeof(@type@));
2114

2115 1
    if (swap) {
2116
        char *a, *b, c;
2117 1
        a = (char *)dst;
2118
#if NPY_SIZEOF_@fsize@ == 4
2119 1
        b = a + 3;
2120 1
        c = *a; *a++ = *b; *b-- = c;
2121 1
        c = *a; *a++ = *b; *b   = c;
2122 1
        a += 2;
2123 1
        b = a + 3;
2124 1
        c = *a; *a++ = *b; *b-- = c;
2125 1
        c = *a; *a++ = *b; *b   = c;
2126
#elif NPY_SIZEOF_@fsize@ == 8
2127 1
        b = a + 7;
2128 1
        c = *a; *a++ = *b; *b-- = c;
2129 1
        c = *a; *a++ = *b; *b-- = c;
2130 1
        c = *a; *a++ = *b; *b-- = c;
2131 1
        c = *a; *a++ = *b; *b   = c;
2132 1
        a += 4;
2133 1
        b = a + 7;
2134 1
        c = *a; *a++ = *b; *b-- = c;
2135 1
        c = *a; *a++ = *b; *b-- = c;
2136 1
        c = *a; *a++ = *b; *b-- = c;
2137 1
        c = *a; *a++ = *b; *b   = c;
2138
#elif NPY_SIZEOF_@fsize@ == 10
2139
        b = a + 9;
2140
        c = *a; *a++ = *b; *b-- = c;
2141
        c = *a; *a++ = *b; *b-- = c;
2142
        c = *a; *a++ = *b; *b-- = c;
2143
        c = *a; *a++ = *b; *b-- = c;
2144
        c = *a; *a++ = *b; *b   = c;
2145
        a += 5;
2146
        b = a + 9;
2147
        c = *a; *a++ = *b; *b-- = c;
2148
        c = *a; *a++ = *b; *b-- = c;
2149
        c = *a; *a++ = *b; *b-- = c;
2150
        c = *a; *a++ = *b; *b-- = c;
2151
        c = *a; *a++ = *b; *b   = c;
2152
#elif NPY_SIZEOF_@fsize@ == 12
2153
        b = a + 11;
2154
        c = *a; *a++ = *b; *b-- = c;
2155
        c = *a; *a++ = *b; *b-- = c;
2156
        c = *a; *a++ = *b; *b-- = c;
2157
        c = *a; *a++ = *b; *b-- = c;
2158
        c = *a; *a++ = *b; *b-- = c;
2159
        c = *a; *a++ = *b; *b   = c;
2160
        a += 6;
2161
        b = a + 11;
2162
        c = *a; *a++ = *b; *b-- = c;
2163
        c = *a; *a++ = *b; *b-- = c;
2164
        c = *a; *a++ = *b; *b-- = c;
2165
        c = *a; *a++ = *b; *b-- = c;
2166
        c = *a; *a++ = *b; *b-- = c;
2167
        c = *a; *a++ = *b; *b   = c;
2168
#elif NPY_SIZEOF_@fsize@ == 16
2169 1
        b = a + 15;
2170 1
        c = *a; *a++ = *b; *b-- = c;
2171 1
        c = *a; *a++ = *b; *b-- = c;
2172 1
        c = *a; *a++ = *b; *b-- = c;
2173 1
        c = *a; *a++ = *b; *b-- = c;
2174 1
        c = *a; *a++ = *b; *b-- = c;
2175 1
        c = *a; *a++ = *b; *b-- = c;
2176 1
        c = *a; *a++ = *b; *b-- = c;
2177 1
        c = *a; *a++ = *b; *b   = c;
2178 1
        a += 8;
2179 1
        b = a + 15;
2180 1
        c = *a; *a++ = *b; *b-- = c;
2181 1
        c = *a; *a++ = *b; *b-- = c;
2182 1
        c = *a; *a++ = *b; *b-- = c;
2183 1
        c = *a; *a++ = *b; *b-- = c;
2184 1
        c = *a; *a++ = *b; *b-- = c;
2185 1
        c = *a; *a++ = *b; *b-- = c;
2186 1
        c = *a; *a++ = *b; *b-- = c;
2187 1
        c = *a; *a++ = *b; *b   = c;
2188
#else
2189
        {
2190
            int i, nn;
2191

2192
            b = a + (NPY_SIZEOF_@fsize@ - 1);
2193
            nn = NPY_SIZEOF_@fsize@ / 2;
2194
            for (i = 0; i < nn; i++) {
2195
                c = *a;
2196
                *a++ = *b;
2197
                *b-- = c;
2198
            }
2199
            a += nn;
2200
            b = a + (NPY_SIZEOF_@fsize@ - 1);
2201
            for (i = 0; i < nn; i++) {
2202
                c = *a;
2203
                *a++ = *b;
2204
                *b-- = c;
2205
            }
2206
        }
2207
#endif
2208
    }
2209 1
}
2210

2211
/**end repeat**/
2212

2213
static void
2214 1
OBJECT_copyswapn(PyObject **dst, npy_intp dstride, PyObject **src,
2215
        npy_intp sstride, npy_intp n, int NPY_UNUSED(swap),
2216
        void *NPY_UNUSED(arr))
2217
{
2218
    npy_intp i;
2219 1
    if (src != NULL) {
2220 1
        if (__ALIGNED(dst, sizeof(PyObject **))
2221 1
                && __ALIGNED(src, sizeof(PyObject **))
2222 1
                && __ALIGNED(dstride, sizeof(PyObject **))
2223 1
                && __ALIGNED(sstride, sizeof(PyObject **))) {
2224
            dstride /= sizeof(PyObject **);
2225
            sstride /= sizeof(PyObject **);
2226 1
            for (i = 0; i < n; i++) {
2227 1
                Py_XINCREF(*src);
2228 1
                Py_XDECREF(*dst);
2229 1
                *dst = *src;
2230 1
                dst += dstride;
2231 1
                src += sstride;
2232
            }
2233
        }
2234
        else {
2235
            unsigned char *dstp, *srcp;
2236
            PyObject *tmp;
2237
            dstp = (unsigned char*)dst;
2238
            srcp = (unsigned char*)src;
2239 1
            for (i = 0; i < n; i++) {
2240 1
                memcpy(&tmp, srcp, sizeof(tmp));
2241 1
                Py_XINCREF(tmp);
2242 1
                memcpy(&tmp, dstp, sizeof(tmp));
2243 1
                Py_XDECREF(tmp);
2244 1
                memcpy(dstp, srcp, sizeof(tmp));
2245 1
                dstp += dstride;
2246 1
                srcp += sstride;
2247
            }
2248
        }
2249
    }
2250
    /* ignore swap */
2251 1
    return;
2252
}
2253

2254
static void
2255 1
OBJECT_copyswap(PyObject **dst, PyObject **src, int NPY_UNUSED(swap),
2256
        void *NPY_UNUSED(arr))
2257
{
2258

2259 1
    if (src != NULL) {
2260 1
        if (__ALIGNED(dst,sizeof(PyObject **)) &&
2261 1
                __ALIGNED(src,sizeof(PyObject **))) {
2262 1
            Py_XINCREF(*src);
2263 1
            Py_XDECREF(*dst);
2264 1
            *dst = *src;
2265
        }
2266
        else {
2267
            PyObject *tmp;
2268 0
            memcpy(&tmp, src, sizeof(tmp));
2269 0
            Py_XINCREF(tmp);
2270 0
            memcpy(&tmp, dst, sizeof(tmp));
2271 0
            Py_XDECREF(tmp);
2272 0
            memcpy(dst, src, sizeof(tmp));
2273
        }
2274
    }
2275 1
}
2276

2277
/* ignore swap */
2278
static void
2279 1
STRING_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
2280
                  npy_intp n, int NPY_UNUSED(swap), PyArrayObject *arr)
2281
{
2282
    assert(arr != NULL);
2283 1
    if (arr == NULL) {
2284
        return;
2285
    }
2286 1
    _basic_copyn(dst, dstride, src, sstride, n, PyArray_DESCR(arr)->elsize);
2287 1
    return;
2288
}
2289

2290
/* */
2291
static void
2292 1
VOID_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
2293
                npy_intp n, int swap, PyArrayObject *arr)
2294
{
2295
    PyArray_Descr *descr;
2296

2297
    assert(arr != NULL);
2298 1
    if (arr == NULL) {
2299
        return;
2300
    }
2301

2302 1
    descr = PyArray_DESCR(arr);
2303

2304 1
    if (PyArray_HASFIELDS(arr)) {
2305
        PyObject *key, *value;
2306

2307 1
        Py_ssize_t pos = 0;
2308

2309 1
        while (PyDict_Next(descr->fields, &pos, &key, &value)) {
2310
            npy_intp offset;
2311
            PyArray_Descr * new;
2312 1
            if (NPY_TITLE_KEY(key, value)) {
2313 0
                continue;
2314
            }
2315 1
            if (_unpack_field(value, &new, &offset) < 0) {
2316 0
                ((PyArrayObject_fields *)arr)->descr = descr;
2317 0
                return;
2318
            }
2319
            /*
2320
             * TODO: temporarily modifying the array like this
2321
             *       is bad coding style, should be changed.
2322
             */
2323 1
            ((PyArrayObject_fields *)arr)->descr = new;
2324 1
            new->f->copyswapn(dst+offset, dstride,
2325 1
                    (src != NULL ? src+offset : NULL),
2326
                    sstride, n, swap, arr);
2327
        }
2328 1
        ((PyArrayObject_fields *)arr)->descr = descr;
2329 1
        return;
2330
    }
2331 1
    if (PyDataType_HASSUBARRAY(descr)) {
2332
        PyArray_Descr *new;
2333
        npy_intp num;
2334
        npy_intp i;
2335
        int subitemsize;
2336
        char *dstptr, *srcptr;
2337
        /*
2338
         * In certain cases subarray copy can be optimized. This is when
2339
         * swapping is unnecessary and the subarrays data type can certainly
2340
         * be simply copied (no object, fields, subarray, and not a user dtype).
2341
         */
2342 1
        npy_bool can_optimize_subarray = (!swap &&
2343 1
                !PyDataType_HASFIELDS(descr->subarray->base) &&
2344 1
                !PyDataType_HASSUBARRAY(descr->subarray->base) &&
2345 1
                !PyDataType_REFCHK(descr->subarray->base) &&
2346 1
                (descr->subarray->base->type_num < NPY_NTYPES));
2347

2348 1
        if (can_optimize_subarray) {
2349 1
            _basic_copyn(dst, dstride, src, sstride, n, descr->elsize);
2350 1
            return;
2351
        }
2352

2353 1
        new = descr->subarray->base;
2354
        /*
2355
         * TODO: temporarily modifying the array like this
2356
         *       is bad coding style, should be changed.
2357
         */
2358 1
        ((PyArrayObject_fields *)arr)->descr = new;
2359 1
        dstptr = dst;
2360 1
        srcptr = src;
2361 1
        subitemsize = new->elsize;
2362 1
        if (subitemsize == 0) {
2363
            /* There cannot be any elements, so return */
2364
            return;
2365
        }
2366 1
        num = descr->elsize / subitemsize;
2367 1
        for (i = 0; i < n; i++) {
2368 1
            new->f->copyswapn(dstptr, subitemsize, srcptr,
2369
                    subitemsize, num, swap, arr);
2370 1
            dstptr += dstride;
2371 1
            if (srcptr) {
2372 0
                srcptr += sstride;
2373
            }
2374
        }
2375 1
        ((PyArrayObject_fields *)arr)->descr = descr;
2376 1
        return;
2377
    }
2378
    /* Must be a naive Void type (e.g. a "V8") so simple copy is sufficient. */
2379 1
    _basic_copyn(dst, dstride, src, sstride, n, descr->elsize);
2380 1
    return;
2381
}
2382

2383
static void
2384 1
VOID_copyswap (char *dst, char *src, int swap, PyArrayObject *arr)
2385
{
2386
    PyArray_Descr *descr;
2387

2388
    assert(arr != NULL);
2389 1
    if (arr == NULL) {
2390
        return;
2391
    }
2392

2393 1
    descr = PyArray_DESCR(arr);
2394

2395 1
    if (PyArray_HASFIELDS(arr)) {
2396
        PyObject *key, *value;
2397 1
        Py_ssize_t pos = 0;
2398

2399 1
        while (PyDict_Next(descr->fields, &pos, &key, &value)) {
2400
            npy_intp offset;
2401
            PyArray_Descr * new;
2402 1
            if (NPY_TITLE_KEY(key, value)) {
2403 0
                continue;
2404
            }
2405 1
            if (_unpack_field(value, &new, &offset) < 0) {
2406 0
                ((PyArrayObject_fields *)arr)->descr = descr;
2407 0
                return;
2408
            }
2409
            /*
2410
             * TODO: temporarily modifying the array like this
2411
             *       is bad coding style, should be changed.
2412
             */
2413 1
            ((PyArrayObject_fields *)arr)->descr = new;
2414 1
            new->f->copyswap(dst+offset,
2415 1
                    (src != NULL ? src+offset : NULL),
2416
                    swap, arr);
2417
        }
2418 1
        ((PyArrayObject_fields *)arr)->descr = descr;
2419 1
        return;
2420
    }
2421 1
    if (PyDataType_HASSUBARRAY(descr)) {
2422
        PyArray_Descr *new;
2423
        npy_intp num;
2424
        int subitemsize;
2425
        /*
2426
         * In certain cases subarray copy can be optimized. This is when
2427
         * swapping is unnecessary and the subarrays data type can certainly
2428
         * be simply copied (no object, fields, subarray, and not a user dtype).
2429
         */
2430 1
        npy_bool can_optimize_subarray = (!swap &&
2431 1
                !PyDataType_HASFIELDS(descr->subarray->base) &&
2432 1
                !PyDataType_HASSUBARRAY(descr->subarray->base) &&
2433 1
                !PyDataType_REFCHK(descr->subarray->base) &&
2434 1
                (descr->subarray->base->type_num < NPY_NTYPES));
2435

2436 1
        if (can_optimize_subarray) {
2437 1
            _basic_copy(dst, src, descr->elsize);
2438
            return;
2439
        }
2440

2441 1
        new = descr->subarray->base;
2442
        /*
2443
         * TODO: temporarily modifying the array like this
2444
         *       is bad coding style, should be changed.
2445
         */
2446 1
        ((PyArrayObject_fields *)arr)->descr = new;
2447 1
        subitemsize = new->elsize;
2448 1
        if (subitemsize == 0) {
2449
            /* There cannot be any elements, so return */
2450
            return;
2451
        }
2452 1
        num = descr->elsize / subitemsize;
2453 1
        new->f->copyswapn(dst, subitemsize, src,
2454
                subitemsize, num, swap, arr);
2455 1
        ((PyArrayObject_fields *)arr)->descr = descr;
2456 1
        return;
2457
    }
2458
    /* Must be a naive Void type (e.g. a "V8") so simple copy is sufficient. */
2459 1
    _basic_copy(dst, src, descr->elsize);
2460
    return;
2461
}
2462

2463

2464
static void
2465 1
UNICODE_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
2466
                   npy_intp n, int swap, PyArrayObject *arr)
2467
{
2468
    int itemsize;
2469

2470
    assert(arr != NULL);
2471 1
    if (arr == NULL) {
2472
        return;
2473
    }
2474 1
    itemsize = PyArray_DESCR(arr)->elsize;
2475 1
    _basic_copyn(dst, dstride, src, sstride, n, itemsize);
2476

2477 1
    if (swap) {
2478
        int i;
2479
        char *_dst;
2480 1
        itemsize = itemsize / 4;
2481

2482 1
        while (n > 0) {
2483
            _dst = dst;
2484 1
            for (i=0; i < itemsize; i++) {
2485 1
                npy_bswap4_unaligned(_dst);
2486 1
                _dst += 4;
2487
            }
2488 1
            dst += dstride;
2489 1
            --n;
2490
        }
2491
    }
2492
}
2493

2494

2495
static void
2496 1
STRING_copyswap(char *dst, char *src, int NPY_UNUSED(swap), PyArrayObject *arr)
2497
{
2498
    assert(arr != NULL);
2499 1
    if (arr == NULL) {
2500
        return;
2501
    }
2502
    /* copy first if needed */
2503 1
    _basic_copy(dst, src, PyArray_DESCR(arr)->elsize);
2504
}
2505

2506
static void
2507 1
UNICODE_copyswap (char *dst, char *src, int swap, PyArrayObject *arr)
2508
{
2509
    int itemsize;
2510

2511
    assert(arr != NULL);
2512 1
    if (arr == NULL) {
2513
        return;
2514
    }
2515 1
    itemsize = PyArray_DESCR(arr)->elsize;
2516 1
    _basic_copy(dst, src, itemsize);
2517

2518 1
    if (swap) {
2519
        int i;
2520
        char *_dst;
2521 1
        itemsize = itemsize / 4;
2522

2523 1
        _dst = dst;
2524 1
        for (i=0; i < itemsize; i++) {
2525 1
            npy_bswap4_unaligned(_dst);
2526 1
            _dst += 4;
2527
        }
2528
    }
2529
}
2530

2531

2532
/*
2533
 *****************************************************************************
2534
 **                                 NONZERO                                 **
2535
 *****************************************************************************
2536
 */
2537

2538
#define _NONZERO(a) ((a) != 0)
2539

2540
/**begin repeat
2541
 *
2542
 * #fname = BOOL,
2543
 *          BYTE, UBYTE, SHORT, USHORT, INT, UINT,
2544
 *          LONG, ULONG, LONGLONG, ULONGLONG,
2545
 *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
2546
 *          DATETIME, TIMEDELTA#
2547
 * #type = npy_bool,
2548
 *         npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
2549
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
2550
 *         npy_half, npy_float, npy_double, npy_longdouble,
2551
 *         npy_datetime, npy_timedelta#
2552
 * #isfloat = 0*11, 1*4, 0*2#
2553
 * #nonzero = _NONZERO*11, !npy_half_iszero, _NONZERO*5#
2554
 */
2555
static npy_bool
2556 1
@fname@_nonzero (char *ip, PyArrayObject *ap)
2557
{
2558 1
    if (ap == NULL || PyArray_ISBEHAVED_RO(ap)) {
2559 1
        @type@ *ptmp = (@type@ *)ip;
2560 1
        return (npy_bool) @nonzero@(*ptmp);
2561
    }
2562
    else {
2563
        /*
2564
         * Don't worry about swapping for integer types,
2565
         * since we are just testing for equality with 0.
2566
         * For float types, the signed zeros require us to swap.
2567
         */
2568
        @type@ tmp;
2569
#if @isfloat@
2570 1
        PyArray_DESCR(ap)->f->copyswap(&tmp, ip, PyArray_ISBYTESWAPPED(ap),
2571
                                       ap);
2572
#else
2573 1
        memcpy(&tmp, ip, sizeof(@type@));
2574
#endif
2575 1
        return (npy_bool) @nonzero@(tmp);
2576
    }
2577
}
2578
/**end repeat**/
2579

2580
/**begin repeat
2581
 *
2582
 * #fname = CFLOAT, CDOUBLE, CLONGDOUBLE#
2583
 * #type = npy_cfloat, npy_cdouble, npy_clongdouble#
2584
 */
2585
static npy_bool
2586 1
@fname@_nonzero (char *ip, PyArrayObject *ap)
2587
{
2588 1
    if (ap == NULL || PyArray_ISBEHAVED_RO(ap)) {
2589 1
        @type@ *ptmp = (@type@ *)ip;
2590 1
        return (npy_bool) ((ptmp->real != 0) || (ptmp->imag != 0));
2591
    }
2592
    else {
2593
        @type@ tmp;
2594 0
        PyArray_DESCR(ap)->f->copyswap(&tmp, ip, PyArray_ISBYTESWAPPED(ap),
2595
                                       ap);
2596 0
        return (npy_bool) ((tmp.real != 0) || (tmp.imag != 0));
2597
    }
2598
}
2599
/**end repeat**/
2600

2601

2602
#define WHITESPACE " \t\n\r\v\f"
2603
#define WHITELEN 6
2604

2605
static npy_bool
2606
Py_STRING_ISSPACE(char ch)
2607
{
2608 1
    char white[] = WHITESPACE;
2609
    int j;
2610 1
    npy_bool space = NPY_FALSE;
2611

2612 1
    for (j = 0; j < WHITELEN; j++) {
2613 1
        if (ch == white[j]) {
2614
            space = NPY_TRUE;
2615
            break;
2616
        }
2617
    }
2618
    return space;
2619
}
2620

2621
static npy_bool
2622 1
STRING_nonzero (char *ip, PyArrayObject *ap)
2623
{
2624 1
    int len = PyArray_DESCR(ap)->elsize;
2625
    int i;
2626 1
    npy_bool nonz = NPY_FALSE;
2627 1
    npy_bool seen_null = NPY_FALSE;
2628

2629 1
    for (i = 0; i < len; i++) {
2630 1
        if (*ip == '\0') {
2631
            seen_null = NPY_TRUE;
2632
        }
2633 1
        else if (seen_null || !Py_STRING_ISSPACE(*ip)) {
2634
            nonz = NPY_TRUE;
2635
            break;
2636
        }
2637 1
        ip++;
2638
    }
2639 1
    return nonz;
2640
}
2641

2642
static npy_bool
2643 1
UNICODE_nonzero (npy_ucs4 *ip, PyArrayObject *ap)
2644
{
2645 1
    int len = PyArray_DESCR(ap)->elsize >> 2;
2646
    int i;
2647 1
    npy_bool nonz = NPY_FALSE;
2648 1
    npy_bool seen_null = NPY_FALSE;
2649 1
    char *buffer = NULL;
2650

2651 1
    if (PyArray_ISBYTESWAPPED(ap) || !PyArray_ISALIGNED(ap)) {
2652 0
        buffer = PyArray_malloc(PyArray_DESCR(ap)->elsize);
2653 0
        if (buffer == NULL) {
2654
            return nonz;
2655
        }
2656 0
        memcpy(buffer, ip, PyArray_DESCR(ap)->elsize);
2657 0
        if (PyArray_ISBYTESWAPPED(ap)) {
2658 0
            byte_swap_vector(buffer, len, 4);
2659
        }
2660
        ip = (npy_ucs4 *)buffer;
2661
    }
2662

2663 1
    for (i = 0; i < len; i++) {
2664 1
        if (*ip == '\0') {
2665
            seen_null = NPY_TRUE;
2666
        }
2667 1
        else if (seen_null || !Py_UNICODE_ISSPACE(*ip)) {
2668
            nonz = NPY_TRUE;
2669
            break;
2670
        }
2671 1
        ip++;
2672
    }
2673 1
    PyArray_free(buffer);
2674 1
    return nonz;
2675
}
2676

2677
static npy_bool
2678 1
OBJECT_nonzero (PyObject **ip, PyArrayObject *ap)
2679
{
2680

2681 1
    if (PyArray_ISALIGNED(ap)) {
2682 1
        if (*ip == NULL) {
2683
            return NPY_FALSE;
2684
        }
2685 1
        return (npy_bool) PyObject_IsTrue(*ip);
2686
    }
2687
    else {
2688
        PyObject *obj;
2689 1
        memcpy(&obj, ip, sizeof(obj));
2690 1
        if (obj == NULL) {
2691
            return NPY_FALSE;
2692
        }
2693 1
        return (npy_bool) PyObject_IsTrue(obj);
2694
    }
2695
}
2696

2697
/*
2698
 * if we have fields, then nonzero only if all sub-fields are nonzero.
2699
 */
2700
static npy_bool
2701 1
VOID_nonzero (char *ip, PyArrayObject *ap)
2702
{
2703
    int i;
2704
    int len;
2705 1
    npy_bool nonz = NPY_FALSE;
2706

2707 1
    if (PyArray_HASFIELDS(ap)) {
2708
        PyArray_Descr *descr;
2709
        PyObject *key, *value;
2710
        int savedflags;
2711 1
        Py_ssize_t pos = 0;
2712

2713 1
        descr = PyArray_DESCR(ap);
2714 1
        savedflags = PyArray_FLAGS(ap);
2715 1
        while (PyDict_Next(descr->fields, &pos, &key, &value)) {
2716
            PyArray_Descr * new;
2717
            npy_intp offset;
2718 1
            if (NPY_TITLE_KEY(key, value)) {
2719 0
                continue;
2720
            }
2721 1
            if (_unpack_field(value, &new, &offset) < 0) {
2722 0
                PyErr_Clear();
2723 0
                continue;
2724
            }
2725
            /*
2726
             * TODO: temporarily modifying the array like this
2727
             *       is bad coding style, should be changed.
2728
             */
2729 1
            ((PyArrayObject_fields *)ap)->descr = new;
2730 1
            ((PyArrayObject_fields *)ap)->flags = savedflags;
2731 1
            if ((new->alignment > 1) && !__ALIGNED(ip + offset,
2732
                        new->alignment)) {
2733
                PyArray_CLEARFLAGS(ap, NPY_ARRAY_ALIGNED);
2734
            }
2735
            else {
2736
                PyArray_ENABLEFLAGS(ap, NPY_ARRAY_ALIGNED);
2737
            }
2738 1
            if (new->f->nonzero(ip+offset, ap)) {
2739 1
                nonz = NPY_TRUE;
2740 1
                break;
2741
            }
2742
        }
2743 1
        ((PyArrayObject_fields *)ap)->descr = descr;
2744 1
        ((PyArrayObject_fields *)ap)->flags = savedflags;
2745
        return nonz;
2746
    }
2747 1
    len = PyArray_DESCR(ap)->elsize;
2748 1
    for (i = 0; i < len; i++) {
2749 1
        if (*ip != '\0') {
2750
            nonz = NPY_TRUE;
2751
            break;
2752
        }
2753 1
        ip++;
2754
    }
2755
    return nonz;
2756
}
2757

2758
#undef __ALIGNED
2759

2760

2761
/*
2762
 *****************************************************************************
2763
 **                                 COMPARE                                 **
2764
 *****************************************************************************
2765
 */
2766

2767

2768
/* boolean type */
2769

2770
static int
2771 1
BOOL_compare(npy_bool *ip1, npy_bool *ip2, PyArrayObject *NPY_UNUSED(ap))
2772
{
2773 1
    return (*ip1 ? (*ip2 ? 0 : 1) : (*ip2 ? -1 : 0));
2774
}
2775

2776

2777
/* integer types */
2778

2779
/**begin repeat
2780
 * #TYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
2781
 *         LONG, ULONG, LONGLONG, ULONGLONG,
2782
 *         DATETIME, TIMEDELTA#
2783
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
2784
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
2785
 *         npy_datetime, npy_timedelta#
2786
 */
2787

2788
static int
2789 1
@TYPE@_compare (@type@ *pa, @type@ *pb, PyArrayObject *NPY_UNUSED(ap))
2790
{
2791 1
    const @type@ a = *pa;
2792 1
    const @type@ b = *pb;
2793

2794 1
    return a < b ? -1 : a == b ? 0 : 1;
2795
}
2796

2797
/**end repeat**/
2798

2799

2800
/* float types */
2801

2802
/*
2803
 * The real/complex comparison functions are compatible with the new sort
2804
 * order for nans introduced in numpy 1.4.0. All nan values now compare
2805
 * larger than non-nan values and are sorted to the end. The comparison
2806
 * order is:
2807
 *
2808
 *      Real: [R, nan]
2809
 *      Complex: [R + Rj, R + nanj, nan + Rj, nan + nanj]
2810
 *
2811
 *  where complex values with the same nan placements are sorted according
2812
 *  to the non-nan part if it exists. If both the real and imaginary parts
2813
 *  of complex types are non-nan the order is the same as the real parts
2814
 *  unless they happen to be equal, in which case the order is that of the
2815
 *  imaginary parts.
2816
 */
2817

2818
/**begin repeat
2819
 *
2820
 * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
2821
 * #type = npy_float, npy_double, npy_longdouble#
2822
 */
2823

2824
#define LT(a,b) ((a) < (b) || ((b) != (b) && (a) ==(a)))
2825

2826
static int
2827 1
@TYPE@_compare(@type@ *pa, @type@ *pb)
2828
{
2829 1
    const @type@ a = *pa;
2830 1
    const @type@ b = *pb;
2831
    int ret;
2832

2833 1
    if (LT(a,b)) {
2834
        ret = -1;
2835
    }
2836 1
    else if (LT(b,a)) {
2837
        ret = 1;
2838
    }
2839
    else {
2840 1
        ret = 0;
2841
    }
2842 1
    return ret;
2843
}
2844

2845

2846
static int
2847 1
C@TYPE@_compare(@type@ *pa, @type@ *pb)
2848
{
2849 1
    const @type@ ar = pa[0];
2850 1
    const @type@ ai = pa[1];
2851 1
    const @type@ br = pb[0];
2852 1
    const @type@ bi = pb[1];
2853
    int ret;
2854

2855 1
    if (ar < br) {
2856 1
        if (ai == ai || bi != bi) {
2857
            ret = -1;
2858
        }
2859
        else {
2860 0
            ret = 1;
2861
        }
2862
    }
2863 1
    else if (br < ar) {
2864 1
        if (bi == bi || ai != ai) {
2865
            ret = 1;
2866
        }
2867
        else {
2868 0
            ret = -1;
2869
        }
2870
    }
2871 1
    else if (ar == br || (ar != ar && br != br)) {
2872 1
        if (LT(ai,bi)) {
2873
            ret = -1;
2874
        }
2875 1
        else if (LT(bi,ai)) {
2876
            ret = 1;
2877
        }
2878
        else {
2879 1
            ret = 0;
2880
        }
2881
    }
2882 0
    else if (ar == ar) {
2883
        ret = -1;
2884
    }
2885
    else {
2886 0
        ret = 1;
2887
    }
2888

2889 1
    return ret;
2890
}
2891

2892
#undef LT
2893

2894
/**end repeat**/
2895

2896
static int
2897 1
HALF_compare (npy_half *pa, npy_half *pb, PyArrayObject *NPY_UNUSED(ap))
2898
{
2899 1
    npy_half a = *pa, b = *pb;
2900
    npy_bool a_isnan, b_isnan;
2901
    int ret;
2902

2903 1
    a_isnan = npy_half_isnan(a);
2904 1
    b_isnan = npy_half_isnan(b);
2905

2906 1
    if (a_isnan) {
2907 0
        ret = b_isnan ? 0 : -1;
2908
    }
2909 1
    else if (b_isnan) {
2910
        ret = 1;
2911
    }
2912 1
    else if(npy_half_lt_nonan(a, b)) {
2913
        ret = -1;
2914
    }
2915 1
    else if(npy_half_lt_nonan(b, a)) {
2916
        ret = 1;
2917
    }
2918
    else {
2919 1
        ret = 0;
2920
    }
2921

2922 1
    return ret;
2923
}
2924

2925

2926
/* object type */
2927

2928
static int
2929 1
OBJECT_compare(PyObject **ip1, PyObject **ip2, PyArrayObject *NPY_UNUSED(ap))
2930
{
2931
    /*
2932
     * ALIGNMENT NOTE: It seems that PyArray_Sort is already handling
2933
     * the alignment of pointers, so it doesn't need to be handled
2934
     * here.
2935
     */
2936

2937
    int ret;
2938
    /*
2939
     * work around gh-3879, we cannot abort an in-progress quicksort
2940
     * so at least do not raise again
2941
     */
2942 1
    if (PyErr_Occurred()) {
2943
        return 0;
2944
    }
2945 1
    if ((*ip1 == NULL) || (*ip2 == NULL)) {
2946 0
        if (ip1 == ip2) {
2947
            return 1;
2948
        }
2949 0
        if (ip1 == NULL) {
2950
            return -1;
2951
        }
2952 0
        return 1;
2953
    }
2954

2955 1
    ret = PyObject_RichCompareBool(*ip1, *ip2, Py_LT);
2956 1
    if (ret < 0) {
2957
        /* error occurred, avoid the next call to PyObject_RichCompareBool */
2958
        return 0;
2959
    }
2960 1
    if (ret == 1) {
2961
        return -1;
2962
    }
2963 1
    else if (PyObject_RichCompareBool(*ip1, *ip2, Py_GT) == 1) {
2964
        return 1;
2965
    }
2966
    else {
2967 1
        return 0;
2968
    }
2969
}
2970

2971

2972
/* string type */
2973

2974
static int
2975 1
STRING_compare(char *ip1, char *ip2, PyArrayObject *ap)
2976
{
2977 1
    const unsigned char *c1 = (unsigned char *)ip1;
2978 1
    const unsigned char *c2 = (unsigned char *)ip2;
2979 1
    const size_t len = PyArray_DESCR(ap)->elsize;
2980
    int i;
2981

2982 1
    i = memcmp(c1, c2, len);
2983 1
    if (i > 0) {
2984
        return 1;
2985
    }
2986 1
    else if (i < 0) {
2987
        return -1;
2988
    }
2989 1
    return 0;
2990
}
2991

2992

2993
/* unicode type */
2994

2995
static int
2996 1
UNICODE_compare(npy_ucs4 *ip1, npy_ucs4 *ip2,
2997
                PyArrayObject *ap)
2998
{
2999 1
    int itemsize = PyArray_DESCR(ap)->elsize;
3000

3001 1
    if (itemsize < 0) {
3002
        return 0;
3003
    }
3004 1
    itemsize /= sizeof(npy_ucs4);
3005 1
    while (itemsize-- > 0) {
3006 1
        npy_ucs4 c1 = *ip1++;
3007 1
        npy_ucs4 c2 = *ip2++;
3008 1
        if (c1 != c2) {
3009 1
            return (c1 < c2) ? -1 : 1;
3010
        }
3011
    }
3012
    return 0;
3013
}
3014

3015

3016
/* void type */
3017

3018
/*
3019
 * If fields are defined, then compare on first field and if equal
3020
 * compare on second field.  Continue until done or comparison results
3021
 * in not_equal.
3022
 *
3023
 * Must align data passed on to sub-comparisons.
3024
 * Also must swap data based on to sub-comparisons.
3025
 */
3026
static int
3027 1
VOID_compare(char *ip1, char *ip2, PyArrayObject *ap)
3028
{
3029
    PyArray_Descr *descr;
3030
    PyObject *names, *key;
3031
    PyObject *tup;
3032
    PyArrayObject_fields dummy_struct;
3033 1
    PyArrayObject *dummy = (PyArrayObject *)&dummy_struct;
3034
    char *nip1, *nip2;
3035 1
    int i, res = 0, swap = 0;
3036

3037 1
    if (!PyArray_HASFIELDS(ap)) {
3038
        return STRING_compare(ip1, ip2, ap);
3039
    }
3040
    descr = PyArray_DESCR(ap);
3041
    /*
3042
     * Compare on the first-field.  If equal, then
3043
     * compare on the second-field, etc.
3044
     */
3045
    names = descr->names;
3046 1
    for (i = 0; i < PyTuple_GET_SIZE(names); i++) {
3047
        PyArray_Descr *new;
3048
        npy_intp offset;
3049 1
        key = PyTuple_GET_ITEM(names, i);
3050 1
        tup = PyDict_GetItem(descr->fields, key);
3051 1
        if (_unpack_field(tup, &new, &offset) < 0) {
3052
            goto finish;
3053
        }
3054
        /* descr is the only field checked by compare or copyswap */
3055 1
        dummy_struct.descr = new;
3056 1
        swap = PyArray_ISBYTESWAPPED(dummy);
3057 1
        nip1 = ip1 + offset;
3058 1
        nip2 = ip2 + offset;
3059 1
        if (swap || new->alignment > 1) {
3060 1
            if (swap || !npy_is_aligned(nip1, new->alignment)) {
3061
                /* create buffer and copy */
3062 1
                nip1 = npy_alloc_cache(new->elsize);
3063 1
                if (nip1 == NULL) {
3064
                    goto finish;
3065
                }
3066 1
                memcpy(nip1, ip1 + offset, new->elsize);
3067 1
                if (swap)
3068 1
                    new->f->copyswap(nip1, NULL, swap, dummy);
3069
            }
3070 1
            if (swap || !npy_is_aligned(nip2, new->alignment)) {
3071
                /* create buffer and copy */
3072 1
                nip2 = npy_alloc_cache(new->elsize);
3073 1
                if (nip2 == NULL) {
3074 0
                    if (nip1 != ip1 + offset) {
3075 0
                        npy_free_cache(nip1, new->elsize);
3076
                    }
3077
                    goto finish;
3078
                }
3079 1
                memcpy(nip2, ip2 + offset, new->elsize);
3080 1
                if (swap)
3081 1
                    new->f->copyswap(nip2, NULL, swap, dummy);
3082
            }
3083
        }
3084 1
        res = new->f->compare(nip1, nip2, dummy);
3085 1
        if (swap || new->alignment > 1) {
3086 1
            if (nip1 != ip1 + offset) {
3087 1
                npy_free_cache(nip1, new->elsize);
3088
            }
3089 1
            if (nip2 != ip2 + offset) {
3090 1
                npy_free_cache(nip2, new->elsize);
3091
            }
3092
        }
3093 1
        if (res != 0) {
3094
            break;
3095
        }
3096
    }
3097

3098 1
finish:
3099
    return res;
3100
}
3101

3102

3103
/*
3104
 *****************************************************************************
3105
 **                                 ARGFUNC                                 **
3106
 *****************************************************************************
3107
 */
3108
#if defined(__ARM_NEON__) || defined (__ARM_NEON)
3109
    int32_t _mm_movemask_epi8_neon(uint8x16_t input)
3110
    {
3111
        int8x8_t m0 = vcreate_s8(0x0706050403020100ULL);
3112
        uint8x16_t v0 = vshlq_u8(vshrq_n_u8(input, 7), vcombine_s8(m0, m0));
3113
        uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(v0)));
3114
        return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 8);
3115
    }
3116
#endif
3117
#define _LESS_THAN_OR_EQUAL(a,b) ((a) <= (b))
3118

3119
static int
3120 1
BOOL_argmax(npy_bool *ip, npy_intp n, npy_intp *max_ind,
3121
            PyArrayObject *NPY_UNUSED(aip))
3122

3123
{
3124 1
    npy_intp i = 0;
3125
    /* memcmp like logical_and on i386 is maybe slower for small arrays */
3126
#ifdef NPY_HAVE_SSE2_INTRINSICS
3127 1
    const __m128i zero = _mm_setzero_si128();
3128 1
    for (; i < n - (n % 32); i+=32) {
3129 0
        __m128i d1 = _mm_loadu_si128((__m128i*)&ip[i]);
3130 0
        __m128i d2 = _mm_loadu_si128((__m128i*)&ip[i + 16]);
3131 0
        d1 = _mm_cmpeq_epi8(d1, zero);
3132 0
        d2 = _mm_cmpeq_epi8(d2, zero);
3133 0
        if (_mm_movemask_epi8(_mm_min_epu8(d1, d2)) != 0xFFFF) {
3134
            break;
3135
        }
3136
    }
3137
#else
3138
    #if defined(__ARM_NEON__) || defined (__ARM_NEON)
3139
        uint8x16_t zero = vdupq_n_u8(0);
3140
        for(; i < n - (n % 32); i+=32) {
3141
            uint8x16_t d1 = vld1q_u8((uint8_t *)&ip[i]);
3142
            uint8x16_t d2 = vld1q_u8((uint8_t *)&ip[i + 16]);
3143
            d1 = vceqq_u8(d1, zero);
3144
            d2 = vceqq_u8(d2, zero);
3145
            if(_mm_movemask_epi8_neon(vminq_u8(d1, d2)) != 0xFFFF) {
3146
                break;
3147
            }
3148
        }
3149
    #endif
3150
#endif
3151 1
    for (; i < n; i++) {
3152 1
        if (ip[i]) {
3153 1
            *max_ind = i;
3154 1
            return 0;
3155
        }
3156
    }
3157 0
    *max_ind = 0;
3158 0
    return 0;
3159
}
3160

3161
/**begin repeat
3162
 *
3163
 * #fname = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
3164
 *          LONG, ULONG, LONGLONG, ULONGLONG,
3165
 *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
3166
 *          CFLOAT, CDOUBLE, CLONGDOUBLE,
3167
 *          DATETIME, TIMEDELTA#
3168
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
3169
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3170
 *         npy_half, npy_float, npy_double, npy_longdouble,
3171
 *         npy_float, npy_double, npy_longdouble,
3172
 *         npy_datetime, npy_timedelta#
3173
 * #isfloat = 0*10, 1*7, 0*2#
3174
 * #isnan = nop*10, npy_half_isnan, npy_isnan*6, nop*2#
3175
 * #le = _LESS_THAN_OR_EQUAL*10, npy_half_le, _LESS_THAN_OR_EQUAL*8#
3176
 * #iscomplex = 0*14, 1*3, 0*2#
3177
 * #incr = ip++*14, ip+=2*3, ip++*2#
3178
 * #isdatetime = 0*17, 1*2#
3179
 */
3180
static int
3181 1
@fname@_argmax(@type@ *ip, npy_intp n, npy_intp *max_ind,
3182
        PyArrayObject *NPY_UNUSED(aip))
3183
{
3184
    npy_intp i;
3185 1
    @type@ mp = *ip;
3186
#if @iscomplex@
3187 1
    @type@ mp_im = ip[1];
3188
#endif
3189

3190 1
    *max_ind = 0;
3191

3192
#if @isfloat@
3193 1
    if (@isnan@(mp)) {
3194
        /* nan encountered; it's maximal */
3195
        return 0;
3196
    }
3197
#endif
3198
#if @iscomplex@
3199 1
    if (@isnan@(mp_im)) {
3200
        /* nan encountered; it's maximal */
3201
        return 0;
3202
    }
3203
#endif
3204
#if @isdatetime@
3205 1
    if (mp == NPY_DATETIME_NAT) {
3206
        /* NaT encountered, it's maximal */
3207
        return 0;
3208
    }
3209
#endif
3210

3211 1
    for (i = 1; i < n; i++) {
3212 1
        @incr@;
3213
        /*
3214
         * Propagate nans, similarly as max() and min()
3215
         */
3216
#if @iscomplex@
3217
        /* Lexical order for complex numbers */
3218 1
        if ((ip[0] > mp) || ((ip[0] == mp) && (ip[1] > mp_im))
3219 1
                || @isnan@(ip[0]) || @isnan@(ip[1])) {
3220 1
            mp = ip[0];
3221 1
            mp_im = ip[1];
3222 1
            *max_ind = i;
3223 1
            if (@isnan@(mp) || @isnan@(mp_im)) {
3224
                /* nan encountered, it's maximal */
3225
                break;
3226
            }
3227
        }
3228
#else
3229
#if @isdatetime@
3230 1
        if (*ip == NPY_DATETIME_NAT) {
3231
            /* NaT encountered, it's maximal */
3232 1
            *max_ind = i;
3233 1
            break;
3234
        }
3235
#endif
3236 1
        if (!@le@(*ip, mp)) {  /* negated, for correct nan handling */
3237 1
            mp = *ip;
3238 1
            *max_ind = i;
3239
#if @isfloat@
3240 1
            if (@isnan@(mp)) {
3241
                /* nan encountered, it's maximal */
3242
                break;
3243
            }
3244
#endif
3245
        }
3246
#endif
3247
    }
3248 1
    return 0;
3249
}
3250

3251
/**end repeat**/
3252

3253
static int
3254 1
BOOL_argmin(npy_bool *ip, npy_intp n, npy_intp *min_ind,
3255
            PyArrayObject *NPY_UNUSED(aip))
3256

3257
{
3258 1
    npy_bool * p = memchr(ip, 0, n * sizeof(*ip));
3259 1
    if (p == NULL) {
3260 1
        *min_ind = 0;
3261 1
        return 0;
3262
    }
3263 1
    *min_ind = p - ip;
3264 1
    return 0;
3265
}
3266

3267
/**begin repeat
3268
 *
3269
 * #fname = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
3270
 *          LONG, ULONG, LONGLONG, ULONGLONG,
3271
 *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
3272
 *          CFLOAT, CDOUBLE, CLONGDOUBLE,
3273
 *          DATETIME, TIMEDELTA#
3274
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
3275
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3276
 *         npy_half, npy_float, npy_double, npy_longdouble,
3277
 *         npy_float, npy_double, npy_longdouble,
3278
 *         npy_datetime, npy_timedelta#
3279
 * #isfloat = 0*10, 1*7, 0*2#
3280
 * #isnan = nop*10, npy_half_isnan, npy_isnan*6, nop*2#
3281
 * #le = _LESS_THAN_OR_EQUAL*10, npy_half_le, _LESS_THAN_OR_EQUAL*8#
3282
 * #iscomplex = 0*14, 1*3, 0*2#
3283
 * #incr = ip++*14, ip+=2*3, ip++*2#
3284
 * #isdatetime = 0*17, 1*2#
3285
 */
3286
static int
3287 1
@fname@_argmin(@type@ *ip, npy_intp n, npy_intp *min_ind,
3288
        PyArrayObject *NPY_UNUSED(aip))
3289
{
3290
    npy_intp i;
3291 1
    @type@ mp = *ip;
3292
#if @iscomplex@
3293 1
    @type@ mp_im = ip[1];
3294
#endif
3295

3296 1
    *min_ind = 0;
3297

3298
#if @isfloat@
3299 1
    if (@isnan@(mp)) {
3300
        /* nan encountered; it's minimal */
3301
        return 0;
3302
    }
3303
#endif
3304
#if @iscomplex@
3305 1
    if (@isnan@(mp_im)) {
3306
        /* nan encountered; it's minimal */
3307
        return 0;
3308
    }
3309
#endif
3310
#if @isdatetime@
3311 1
    if (mp == NPY_DATETIME_NAT) {
3312
        /* NaT encountered, it's minimal */
3313
        return 0;
3314
    }
3315
#endif
3316

3317 1
    for (i = 1; i < n; i++) {
3318 1
        @incr@;
3319
        /*
3320
         * Propagate nans, similarly as max() and min()
3321
         */
3322
#if @iscomplex@
3323
        /* Lexical order for complex numbers */
3324 1
        if ((mp > ip[0]) || ((ip[0] == mp) && (mp_im > ip[1]))
3325 1
                || @isnan@(ip[0]) || @isnan@(ip[1])) {
3326 1
            mp = ip[0];
3327 1
            mp_im = ip[1];
3328 1
            *min_ind = i;
3329 1
            if (@isnan@(mp) || @isnan@(mp_im)) {
3330
                /* nan encountered, it's minimal */
3331
                break;
3332
            }
3333
        }
3334
#else
3335
#if @isdatetime@
3336 1
        if (*ip == NPY_DATETIME_NAT) {
3337
            /* NaT encountered, it's minimal */
3338 1
            *min_ind = i;
3339 1
            break;
3340
        }
3341
#endif 
3342 1
        if (!@le@(mp, *ip)) {  /* negated, for correct nan handling */
3343 1
            mp = *ip;
3344 1
            *min_ind = i;
3345
#if @isfloat@
3346 1
            if (@isnan@(mp)) {
3347
                /* nan encountered, it's minimal */
3348
                break;
3349
            }
3350
#endif
3351
        }
3352
#endif
3353
    }
3354 1
    return 0;
3355
}
3356

3357
/**end repeat**/
3358

3359
#undef _LESS_THAN_OR_EQUAL
3360

3361
static int
3362 1
OBJECT_argmax(PyObject **ip, npy_intp n, npy_intp *max_ind,
3363
              PyArrayObject *NPY_UNUSED(aip))
3364
{
3365
    npy_intp i;
3366

3367 1
    *max_ind = 0;
3368
    /* Skip over all leading NULL entries */
3369 1
    for (i = 0; i < n && ip[i] == NULL; ++i);
3370 1
    if (i < n) {
3371
        /* Found first non-NULL entry */
3372 1
        PyObject *mp = ip[i];
3373 1
        *max_ind = i;
3374 1
        for (i = i + 1; i < n; ++i) {
3375 1
            PyObject *val = ip[i];
3376 1
            if (val != NULL) {
3377 1
                int greater_than = PyObject_RichCompareBool(val, mp, Py_GT);
3378

3379 1
                if (greater_than < 0) {
3380
                    return 0;
3381
                }
3382 1
                if (greater_than) {
3383 1
                    mp = val;
3384 1
                    *max_ind = i;
3385
                }
3386
            }
3387
        }
3388
    }
3389

3390
    return 0;
3391
}
3392

3393
/**begin repeat
3394
 *
3395
 * #fname = STRING, UNICODE#
3396
 * #type = npy_char, npy_ucs4#
3397
 */
3398
static int
3399 1
@fname@_argmax(@type@ *ip, npy_intp n, npy_intp *max_ind, PyArrayObject *aip)
3400
{
3401
    npy_intp i;
3402 1
    int elsize = PyArray_DESCR(aip)->elsize;
3403 1
    @type@ *mp = (@type@ *)PyArray_malloc(elsize);
3404

3405 1
    if (mp == NULL) {
3406
        return 0;
3407
    }
3408 1
    memcpy(mp, ip, elsize);
3409 1
    *max_ind = 0;
3410 1
    for (i = 1; i < n; i++) {
3411 1
        ip += elsize / sizeof(@type@);
3412 1
        if (@fname@_compare(ip, mp, aip) > 0) {
3413 1
            memcpy(mp, ip, elsize);
3414 1
            *max_ind = i;
3415
        }
3416
    }
3417 1
    PyArray_free(mp);
3418 1
    return 0;
3419
}
3420

3421
/**end repeat**/
3422

3423
#define VOID_argmax NULL
3424

3425
static int
3426 1
OBJECT_argmin(PyObject **ip, npy_intp n, npy_intp *min_ind,
3427
              PyArrayObject *NPY_UNUSED(aip))
3428
{
3429
    npy_intp i;
3430

3431 1
    *min_ind = 0;
3432
    /* Skip over all leading NULL entries */
3433 1
    for (i = 0; i < n && ip[i] == NULL; ++i);
3434 1
    if (i < n) {
3435
        /* Found first non-NULL entry */
3436 1
        PyObject *mp = ip[i];
3437 1
        *min_ind = i;
3438 1
        for (i = i + 1; i < n ; ++i) {
3439 1
            PyObject *val = ip[i];
3440 1
            if (val != NULL) {
3441 1
                int less_than = PyObject_RichCompareBool(val, mp, Py_LT);
3442

3443 1
                if (less_than < 0) {
3444
                    return 0;
3445
                }
3446 1
                if (less_than) {
3447 1
                    mp = val;
3448 1
                    *min_ind = i;
3449
                }
3450
            }
3451
        }
3452
    }
3453

3454
    return 0;
3455
}
3456

3457
/**begin repeat
3458
 *
3459
 * #fname = STRING, UNICODE#
3460
 * #type = npy_char, npy_ucs4#
3461
 */
3462
static int
3463 1
@fname@_argmin(@type@ *ip, npy_intp n, npy_intp *min_ind, PyArrayObject *aip)
3464
{
3465
    npy_intp i;
3466 1
    int elsize = PyArray_DESCR(aip)->elsize;
3467 1
    @type@ *mp = (@type@ *)PyArray_malloc(elsize);
3468

3469 1
    if (mp==NULL) return 0;
3470 1
    memcpy(mp, ip, elsize);
3471 1
    *min_ind = 0;
3472 1
    for(i=1; i<n; i++) {
3473 1
        ip += elsize / sizeof(@type@);
3474 1
        if (@fname@_compare(mp,ip,aip) > 0) {
3475 1
            memcpy(mp, ip, elsize);
3476 1
            *min_ind=i;
3477
        }
3478
    }
3479 1
    PyArray_free(mp);
3480 1
    return 0;
3481
}
3482

3483
/**end repeat**/
3484

3485

3486
#define VOID_argmin NULL
3487

3488

3489
/*
3490
 *****************************************************************************
3491
 **                                  DOT                                    **
3492
 *****************************************************************************
3493
 */
3494

3495
/*
3496
 * dot means inner product
3497
 */
3498

3499
/************************** MAYBE USE CBLAS *********************************/
3500

3501

3502
/**begin repeat
3503
 *
3504
 * #name = FLOAT, DOUBLE#
3505
 * #type = npy_float, npy_double#
3506
 * #prefix = s, d#
3507
 */
3508
NPY_NO_EXPORT void
3509 1
@name@_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op,
3510
           npy_intp n, void *NPY_UNUSED(ignore))
3511
{
3512
#if defined(HAVE_CBLAS)
3513 1
    CBLAS_INT is1b = blas_stride(is1, sizeof(@type@));
3514 1
    CBLAS_INT is2b = blas_stride(is2, sizeof(@type@));
3515

3516 1
    if (is1b && is2b)
3517
    {
3518
        double sum = 0.;  /* double for stability */
3519

3520 1
        while (n > 0) {
3521 1
            CBLAS_INT chunk = n < NPY_CBLAS_CHUNK ? n : NPY_CBLAS_CHUNK;
3522

3523 1
            sum += CBLAS_FUNC(cblas_@prefix@dot)(chunk,
3524
                                     (@type@ *) ip1, is1b,
3525
                                     (@type@ *) ip2, is2b);
3526
            /* use char strides here */
3527 1
            ip1 += chunk * is1;
3528 1
            ip2 += chunk * is2;
3529 1
            n -= chunk;
3530
        }
3531 1
        *((@type@ *)op) = (@type@)sum;
3532
    }
3533
    else
3534
#endif
3535
    {
3536
        @type@ sum = (@type@)0;  /* could make this double */
3537
        npy_intp i;
3538

3539 1
        for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3540 1
            const @type@ ip1r = *((@type@ *)ip1);
3541 1
            const @type@ ip2r = *((@type@ *)ip2);
3542

3543 1
            sum += ip1r * ip2r;
3544
        }
3545 1
        *((@type@ *)op) = sum;
3546
    }
3547 1
}
3548
/**end repeat**/
3549

3550
/**begin repeat
3551
 *
3552
 * #name = CFLOAT, CDOUBLE#
3553
 * #ctype = npy_cfloat, npy_cdouble#
3554
 * #type = npy_float, npy_double#
3555
 * #prefix = c, z#
3556
 */
3557
NPY_NO_EXPORT void
3558 1
@name@_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2,
3559
           char *op, npy_intp n, void *NPY_UNUSED(ignore))
3560
{
3561
#if defined(HAVE_CBLAS)
3562 1
    CBLAS_INT is1b = blas_stride(is1, sizeof(@ctype@));
3563 1
    CBLAS_INT is2b = blas_stride(is2, sizeof(@ctype@));
3564

3565 1
    if (is1b && is2b) {
3566
        double sum[2] = {0., 0.};  /* double for stability */
3567

3568 1
        while (n > 0) {
3569 1
            CBLAS_INT chunk = n < NPY_CBLAS_CHUNK ? n : NPY_CBLAS_CHUNK;
3570
            @type@ tmp[2];
3571

3572 1
            CBLAS_FUNC(cblas_@prefix@dotu_sub)((CBLAS_INT)n, ip1, is1b, ip2, is2b, tmp);
3573 1
            sum[0] += (double)tmp[0];
3574 1
            sum[1] += (double)tmp[1];
3575
            /* use char strides here */
3576 1
            ip1 += chunk * is1;
3577 1
            ip2 += chunk * is2;
3578 1
            n -= chunk;
3579
        }
3580 1
        ((@type@ *)op)[0] = (@type@)sum[0];
3581 1
        ((@type@ *)op)[1] = (@type@)sum[1];
3582
    }
3583
    else
3584
#endif
3585
    {
3586
        @type@ sumr = (@type@)0.0;
3587
        @type@ sumi = (@type@)0.0;
3588
        npy_intp i;
3589

3590 1
        for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3591 1
            const @type@ ip1r = ((@type@ *)ip1)[0];
3592 1
            const @type@ ip1i = ((@type@ *)ip1)[1];
3593 1
            const @type@ ip2r = ((@type@ *)ip2)[0];
3594 1
            const @type@ ip2i = ((@type@ *)ip2)[1];
3595

3596 1
            sumr += ip1r * ip2r - ip1i * ip2i;
3597 1
            sumi += ip1r * ip2i + ip1i * ip2r;
3598
        }
3599 1
        ((@type@ *)op)[0] = sumr;
3600 1
        ((@type@ *)op)[1] = sumi;
3601
    }
3602 1
}
3603

3604
/**end repeat**/
3605

3606
/**************************** NO CBLAS VERSIONS *****************************/
3607

3608
static void
3609 1
BOOL_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op, npy_intp n,
3610
         void *NPY_UNUSED(ignore))
3611
{
3612 1
    npy_bool tmp = NPY_FALSE;
3613
    npy_intp i;
3614

3615 1
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3616 1
        if ((*((npy_bool *)ip1) != 0) && (*((npy_bool *)ip2) != 0)) {
3617
            tmp = NPY_TRUE;
3618
            break;
3619
        }
3620
    }
3621 1
    *((npy_bool *)op) = tmp;
3622 1
}
3623

3624
/**begin repeat
3625
 *
3626
 * #name = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
3627
 *         LONG, ULONG, LONGLONG, ULONGLONG,
3628
 *         LONGDOUBLE, DATETIME, TIMEDELTA#
3629
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
3630
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3631
 *         npy_longdouble, npy_datetime, npy_timedelta#
3632
 * #out = npy_long, npy_ulong, npy_long, npy_ulong, npy_long, npy_ulong,
3633
 *        npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3634
 *        npy_longdouble, npy_datetime, npy_timedelta#
3635
 */
3636
static void
3637 1
@name@_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op, npy_intp n,
3638
           void *NPY_UNUSED(ignore))
3639
{
3640 1
    @out@ tmp = (@out@)0;
3641
    npy_intp i;
3642

3643 1
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3644 1
        tmp += (@out@)(*((@type@ *)ip1)) *
3645 1
               (@out@)(*((@type@ *)ip2));
3646
    }
3647 1
    *((@type@ *)op) = (@type@) tmp;
3648 1
}
3649
/**end repeat**/
3650

3651
static void
3652 1
HALF_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op,
3653
         npy_intp n, void *NPY_UNUSED(ignore))
3654
{
3655 1
    float tmp = 0.0f;
3656
    npy_intp i;
3657

3658 1
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3659 1
        tmp += npy_half_to_float(*((npy_half *)ip1)) *
3660 1
               npy_half_to_float(*((npy_half *)ip2));
3661
    }
3662 1
    *((npy_half *)op) = npy_float_to_half(tmp);
3663 1
}
3664

3665
static void
3666 1
CLONGDOUBLE_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2,
3667
                            char *op, npy_intp n, void *NPY_UNUSED(ignore))
3668
{
3669 1
    npy_longdouble tmpr = 0.0L;
3670 1
    npy_longdouble tmpi = 0.0L;
3671
    npy_intp i;
3672

3673 1
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3674 1
        const npy_longdouble ip1r = ((npy_longdouble *)ip1)[0];
3675 1
        const npy_longdouble ip1i = ((npy_longdouble *)ip1)[1];
3676 1
        const npy_longdouble ip2r = ((npy_longdouble *)ip2)[0];
3677 1
        const npy_longdouble ip2i = ((npy_longdouble *)ip2)[1];
3678

3679 1
        tmpr += ip1r * ip2r - ip1i * ip2i;
3680 1
        tmpi += ip1r * ip2i + ip1i * ip2r;
3681
    }
3682 1
    ((npy_longdouble *)op)[0] = tmpr;
3683 1
    ((npy_longdouble *)op)[1] = tmpi;
3684 1
}
3685

3686
static void
3687 1
OBJECT_dot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op, npy_intp n,
3688
           void *NPY_UNUSED(ignore))
3689
{
3690
    /*
3691
     * ALIGNMENT NOTE: np.dot, np.inner etc. enforce that the array is
3692
     * BEHAVED before getting to this point, so unaligned pointers aren't
3693
     * handled here.
3694
     */
3695
    npy_intp i;
3696 1
    PyObject *tmp1, *tmp2, *tmp = NULL;
3697
    PyObject **tmp3;
3698 1
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
3699 1
        if ((*((PyObject **)ip1) == NULL) || (*((PyObject **)ip2) == NULL)) {
3700 0
            tmp1 = Py_False;
3701 0
            Py_INCREF(Py_False);
3702
        }
3703
        else {
3704 1
            tmp1 = PyNumber_Multiply(*((PyObject **)ip1), *((PyObject **)ip2));
3705 1
            if (!tmp1) {
3706 0
                Py_XDECREF(tmp);
3707
                return;
3708
            }
3709
        }
3710 1
        if (i == 0) {
3711
            tmp = tmp1;
3712
        }
3713
        else {
3714 1
            tmp2 = PyNumber_Add(tmp, tmp1);
3715 1
            Py_XDECREF(tmp);
3716 1
            Py_XDECREF(tmp1);
3717 1
            if (!tmp2) {
3718
                return;
3719
            }
3720
            tmp = tmp2;
3721
        }
3722
    }
3723 1
    tmp3 = (PyObject**) op;
3724 1
    tmp2 = *tmp3;
3725 1
    *((PyObject **)op) = tmp;
3726 1
    Py_XDECREF(tmp2);
3727
}
3728

3729

3730
/*
3731
 *****************************************************************************
3732
 **                                 FILL                                    **
3733
 *****************************************************************************
3734
 */
3735

3736

3737
#define BOOL_fill NULL
3738

3739
/* this requires buffer to be filled with objects or NULL */
3740
static int
3741 1
OBJECT_fill(PyObject **buffer, npy_intp length, void *NPY_UNUSED(ignored))
3742
{
3743 1
    int retval = 0;
3744
    npy_intp i;
3745 1
    PyObject *start = buffer[0];
3746 1
    PyObject *delta = buffer[1];
3747
    PyObject *second;
3748

3749 1
    delta = PyNumber_Subtract(delta, start);
3750 1
    if (!delta) {
3751
        return -1;
3752
    }
3753 1
    second = start = PyNumber_Add(start, delta);
3754 1
    if (!start) {
3755
        goto error;
3756
    }
3757 1
    buffer += 2;
3758

3759 1
    for (i = 2; i < length; i++, buffer++) {
3760 1
        start = PyNumber_Add(start, delta);
3761 1
        if (!start) {
3762
            goto error;
3763
        }
3764 1
        Py_XDECREF(*buffer);
3765 1
        *buffer = start;
3766
    }
3767
    goto finish;
3768

3769 0
error:
3770
    retval = -1;
3771

3772 1
finish:
3773 1
    Py_XDECREF(second);
3774 1
    Py_DECREF(delta);
3775
    return retval;
3776
}
3777

3778
/**begin repeat
3779
 *
3780
 * #NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
3781
 *         LONG, ULONG, LONGLONG, ULONGLONG,
3782
 *         FLOAT, DOUBLE, LONGDOUBLE,
3783
 *         DATETIME, TIMEDELTA#
3784
 * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
3785
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3786
 *         npy_float, npy_double, npy_longdouble,
3787
 *         npy_datetime, npy_timedelta#
3788
*/
3789
static int
3790 1
@NAME@_fill(@type@ *buffer, npy_intp length, void *NPY_UNUSED(ignored))
3791
{
3792
    npy_intp i;
3793 1
    @type@ start = buffer[0];
3794 1
    @type@ delta = buffer[1];
3795

3796 1
    delta -= start;
3797 1
    for (i = 2; i < length; ++i) {
3798 1
        buffer[i] = start + i*delta;
3799
    }
3800 1
    return 0;
3801
}
3802
/**end repeat**/
3803

3804
static int
3805 1
HALF_fill(npy_half *buffer, npy_intp length, void *NPY_UNUSED(ignored))
3806
{
3807
    npy_intp i;
3808 1
    float start = npy_half_to_float(buffer[0]);
3809 1
    float delta = npy_half_to_float(buffer[1]);
3810

3811 1
    delta -= start;
3812 1
    for (i = 2; i < length; ++i) {
3813 1
        buffer[i] = npy_float_to_half(start + i*delta);
3814
    }
3815 1
    return 0;
3816
}
3817

3818
/**begin repeat
3819
 *
3820
 * #NAME = CFLOAT, CDOUBLE, CLONGDOUBLE#
3821
 * #type = npy_cfloat, npy_cdouble, npy_clongdouble#
3822
*/
3823
static int
3824 1
@NAME@_fill(@type@ *buffer, npy_intp length, void *NPY_UNUSED(ignore))
3825
{
3826
    npy_intp i;
3827
    @type@ start;
3828
    @type@ delta;
3829

3830 1
    start.real = buffer->real;
3831 1
    start.imag = buffer->imag;
3832 1
    delta.real = buffer[1].real;
3833 1
    delta.imag = buffer[1].imag;
3834 1
    delta.real -= start.real;
3835 1
    delta.imag -= start.imag;
3836 1
    buffer += 2;
3837 1
    for (i = 2; i < length; i++, buffer++) {
3838 1
        buffer->real = start.real + i*delta.real;
3839 1
        buffer->imag = start.imag + i*delta.imag;
3840
    }
3841 1
    return 0;
3842
}
3843
/**end repeat**/
3844

3845

3846
/* this requires buffer to be filled with objects or NULL */
3847
static void
3848 0
OBJECT_fillwithscalar(PyObject **buffer, npy_intp length, PyObject **value,
3849
        void *NPY_UNUSED(ignored))
3850
{
3851
    npy_intp i;
3852 0
    PyObject *val = *value;
3853 0
    for (i = 0; i < length; i++) {
3854 0
        Py_XINCREF(val);
3855 0
        Py_XDECREF(buffer[i]);
3856 0
        buffer[i] = val;
3857
    }
3858 0
}
3859
/**begin repeat
3860
 *
3861
 * #NAME = BOOL, BYTE, UBYTE#
3862
 * #type = npy_bool, npy_byte, npy_ubyte#
3863
 */
3864
static void
3865 0
@NAME@_fillwithscalar(@type@ *buffer, npy_intp length, @type@ *value,
3866
        void *NPY_UNUSED(ignored))
3867
{
3868 0
    memset(buffer, *value, length);
3869 0
}
3870
/**end repeat**/
3871

3872
/**begin repeat
3873
 *
3874
 * #NAME = SHORT, USHORT, INT, UINT,
3875
 *         LONG, ULONG, LONGLONG, ULONGLONG,
3876
 *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
3877
 *         CFLOAT, CDOUBLE, CLONGDOUBLE,
3878
 *         DATETIME, TIMEDELTA#
3879
 * #type = npy_short, npy_ushort, npy_int, npy_uint,
3880
 *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
3881
 *         npy_half, npy_float, npy_double, npy_longdouble,
3882
 *         npy_cfloat, npy_cdouble, npy_clongdouble,
3883
 *         npy_datetime, npy_timedelta#
3884
 */
3885
static void
3886 0
@NAME@_fillwithscalar(@type@ *buffer, npy_intp length, @type@ *value,
3887
        void *NPY_UNUSED(ignored))
3888
{
3889
    npy_intp i;
3890 0
    @type@ val = *value;
3891

3892 0
    for (i = 0; i < length; ++i) {
3893 0
        buffer[i] = val;
3894
    }
3895 0
}
3896
/**end repeat**/
3897

3898

3899
/*
3900
 *****************************************************************************
3901
 **                       small correlate                                   **
3902
 *****************************************************************************
3903
 */
3904

3905
/*
3906
 * Compute correlation of data with small kernels
3907
 * Calling a BLAS dot product for the inner loop of the correlation is overkill
3908
 * for small kernels. It is faster to compute it directly.
3909
 * Intended to be used by _pyarray_correlate so no input verifications is done
3910
 * especially it does not handle the boundaries, they should be handled by the
3911
 * caller.
3912
 * Returns 0 if kernel is considered too large or types are not supported, then
3913
 * the regular array dot should be used to process the data.
3914
 *
3915
 * d_, dstride, nd, dtype: data pointer, its stride in bytes, number of
3916
 *                         elements and type of data
3917
 * k_, kstride, nk, ktype: kernel pointer, its stride in bytes, number of
3918
 *                         elements and type of data
3919
 * out_, ostride: output data pointer and its stride in bytes
3920
 */
3921
NPY_NO_EXPORT int
3922 1
small_correlate(const char * d_, npy_intp dstride,
3923
                npy_intp nd, enum NPY_TYPES dtype,
3924
                const char * k_, npy_intp kstride,
3925
                npy_intp nk, enum NPY_TYPES ktype,
3926
                char * out_, npy_intp ostride)
3927
{
3928
    /* only handle small kernels and uniform types */
3929 1
    if (nk > 11 || dtype != ktype) {
3930
        return 0;
3931
    }
3932

3933 1
    switch (dtype) {
3934
/**begin repeat
3935
 * Float types
3936
 *  #type = npy_float, npy_double#
3937
 *  #TYPE = NPY_FLOAT, NPY_DOUBLE#
3938
 */
3939 1
        case @TYPE@:
3940
            {
3941
                npy_intp i;
3942 1
                const @type@ * d = (@type@*)d_;
3943 1
                const @type@ * k = (@type@*)k_;
3944 1
                @type@ * out = (@type@*)out_;
3945 1
                dstride /= sizeof(@type@);
3946 1
                kstride /= sizeof(@type@);
3947 1
                ostride /= sizeof(@type@);
3948
                /* unroll inner loop to optimize register usage of the kernel*/
3949 1
                switch (nk) {
3950
/**begin repeat1
3951
 *  #ksz_outer = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11# */
3952 1
                    case @ksz_outer@:
3953
                    {
3954
/**begin repeat2
3955
 *  #ksz = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11# */
3956
#if @ksz@ <= @ksz_outer@
3957
                        /* load kernel */
3958 1
                        const @type@ k@ksz@ = k[(@ksz@ - 1) * kstride];
3959
#endif
3960
/**end repeat2**/
3961 1
                        for (i = 0; i < nd; i++) {
3962 1
                            @type@ s = 0;
3963
/**begin repeat2
3964
 *  #ksz = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11# */
3965
#if @ksz@ <= @ksz_outer@
3966 1
                            s += d[(i + @ksz@ - 1) * dstride] * k@ksz@;
3967
#endif
3968
/**end repeat2**/
3969 1
                            out[i * ostride] = s;
3970
                        }
3971
                        return 1;
3972
                    }
3973
/**end repeat1**/
3974
                    default:
3975
                        return 0;
3976
                }
3977
            }
3978
/**end repeat**/
3979
        default:
3980
            return 0;
3981
    }
3982
}
3983

3984
/*
3985
*/
3986

3987
/* A clone function for the datetime dtype c_metadata */
3988
static NpyAuxData *
3989 1
_datetime_dtype_metadata_clone(NpyAuxData *data)
3990
{
3991 1
    PyArray_DatetimeDTypeMetaData *newdata =
3992
        (PyArray_DatetimeDTypeMetaData *)PyArray_malloc(
3993
                        sizeof(*newdata));
3994 1
    if (newdata == NULL) {
3995 0
        PyErr_NoMemory();
3996 0
        return NULL;
3997
    }
3998

3999 1
    memcpy(newdata, data, sizeof(*newdata));
4000

4001 1
    return (NpyAuxData *)newdata;
4002
}
4003

4004
/*
4005
 * Allocate and initialize a PyArray_DatetimeDTypeMetaData object
4006
 */
4007
static NpyAuxData*
4008 1
_create_datetime_metadata(NPY_DATETIMEUNIT base, int num)
4009
{
4010
    PyArray_DatetimeDTypeMetaData *data;
4011

4012
    /* Allocate memory for the metadata */
4013 1
    data = PyArray_malloc(sizeof(*data));
4014 1
    if (data == NULL) {
4015 0
        PyErr_NoMemory();
4016 0
        return NULL;
4017
    }
4018

4019
    /* Initialize the base aux data */
4020 1
    memset(data, 0, sizeof(PyArray_DatetimeDTypeMetaData));
4021 1
    data->base.free = (NpyAuxData_FreeFunc *)PyArray_free;
4022 1
    data->base.clone = _datetime_dtype_metadata_clone;
4023

4024 1
    data->meta.base = base;
4025 1
    data->meta.num = num;
4026

4027 1
    return (NpyAuxData*)data;
4028
}
4029

4030

4031
/*
4032
 *****************************************************************************
4033
 **                       SETUP FUNCTION POINTERS                           **
4034
 *****************************************************************************
4035
 */
4036

4037
/**begin repeat
4038
 *
4039
 * #from = VOID, STRING, UNICODE#
4040
 * #suff = void, string, unicode#
4041
 * #sort = 0, 1, 1#
4042
 * #align = char, char, npy_ucs4#
4043
 * #NAME = Void, String, Unicode#
4044
 * #endian = |, |, =#
4045
 * #flags = 0, 0, NPY_NEEDS_INIT#
4046
 */
4047
static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
4048
    {
4049
        @from@_to_BOOL,
4050
        @from@_to_BYTE,
4051
        @from@_to_UBYTE,
4052
        @from@_to_SHORT,
4053
        @from@_to_USHORT,
4054
        @from@_to_INT,
4055
        @from@_to_UINT,
4056
        @from@_to_LONG,
4057
        @from@_to_ULONG,
4058
        @from@_to_LONGLONG,
4059
        @from@_to_ULONGLONG,
4060
        @from@_to_FLOAT,
4061
        @from@_to_DOUBLE,
4062
        @from@_to_LONGDOUBLE,
4063
        @from@_to_CFLOAT,
4064
        @from@_to_CDOUBLE,
4065
        @from@_to_CLONGDOUBLE,
4066
        @from@_to_OBJECT,
4067
        @from@_to_STRING,
4068
        @from@_to_UNICODE,
4069
        @from@_to_VOID
4070
    },
4071
    @from@_getitem,
4072
    @from@_setitem,
4073
    (PyArray_CopySwapNFunc*)@from@_copyswapn,
4074
    (PyArray_CopySwapFunc*)@from@_copyswap,
4075
    (PyArray_CompareFunc*)@from@_compare,
4076
    (PyArray_ArgFunc*)@from@_argmax,
4077
    (PyArray_DotFunc*)NULL,
4078
    (PyArray_ScanFunc*)@from@_scan,
4079
    @from@_fromstr,
4080
    (PyArray_NonzeroFunc*)@from@_nonzero,
4081
    (PyArray_FillFunc*)NULL,
4082
    (PyArray_FillWithScalarFunc*)NULL,
4083
#if @sort@
4084
    {
4085
        quicksort_@suff@,
4086
        heapsort_@suff@,
4087
        timsort_@suff@
4088
    },
4089
    {
4090
        aquicksort_@suff@,
4091
        aheapsort_@suff@,
4092
        atimsort_@suff@
4093
    },
4094
#else
4095
    {
4096
        NULL, NULL, NULL
4097
    },
4098
    {
4099
        NULL, NULL, NULL
4100
    },
4101
#endif
4102
    NULL,
4103
    (PyArray_ScalarKindFunc*)NULL,
4104
    NULL,
4105
    NULL,
4106
    (PyArray_FastClipFunc *)NULL,
4107
    (PyArray_FastPutmaskFunc *)NULL,
4108
    (PyArray_FastTakeFunc *)NULL,
4109
    (PyArray_ArgFunc*)@from@_argmin
4110
};
4111

4112
/*
4113
 * FIXME: check for PY3K
4114
 */
4115
static PyArray_Descr @from@_Descr = {
4116
    PyObject_HEAD_INIT(&PyArrayDescr_Type)
4117
    /* typeobj */
4118
    &Py@NAME@ArrType_Type,
4119
    /* kind */
4120
    NPY_@from@LTR,
4121
    /* type */
4122
    NPY_@from@LTR,
4123
    /* byteorder */
4124
    '@endian@',
4125
    /* flags, unicode needs init as py3.3 does not like printing garbage  */
4126
    @flags@,
4127
    /* type_num */
4128
    NPY_@from@,
4129
    /* elsize */
4130
    0,
4131
    /* alignment */
4132
    _ALIGN(@align@),
4133
    /* subarray */
4134
    NULL,
4135
    /* fields */
4136
    NULL,
4137
    /* names */
4138
    NULL,
4139
    /* f */
4140
    &_Py@NAME@_ArrFuncs,
4141
    /* metadata */
4142
    NULL,
4143
    /* c_metadata */
4144
    NULL,
4145
    /* hash */
4146
    -1,
4147
};
4148

4149
/**end repeat**/
4150

4151
/**begin repeat
4152
 *
4153
 * #from = BOOL,
4154
 *         BYTE, UBYTE, SHORT, USHORT, INT, UINT,
4155
 *         LONG, ULONG, LONGLONG, ULONGLONG,
4156
 *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
4157
 *         CFLOAT, CDOUBLE, CLONGDOUBLE,
4158
 *         OBJECT, DATETIME, TIMEDELTA#
4159
 * #suff = bool,
4160
 *         byte, ubyte, short, ushort, int, uint,
4161
 *         long, ulong, longlong, ulonglong,
4162
 *         half, float, double, longdouble,
4163
 *         cfloat, cdouble, clongdouble,
4164
 *         object, datetime, timedelta#
4165
 * #sort = 1*18, 0*1, 1*2#
4166
 * #fromtype = npy_bool,
4167
 *             npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
4168
 *             npy_long, npy_ulong, npy_longlong, npy_ulonglong,
4169
 *             npy_half, npy_float, npy_double, npy_longdouble,
4170
 *             npy_cfloat, npy_cdouble, npy_clongdouble,
4171
 *             PyObject *, npy_datetime, npy_timedelta#
4172
 * #rsort = 1*5, 0*16#
4173
 * #NAME = Bool,
4174
 *         Byte, UByte, Short, UShort, Int, UInt,
4175
 *         Long, ULong, LongLong, ULongLong,
4176
 *         Half, Float, Double, LongDouble,
4177
 *         CFloat, CDouble, CLongDouble,
4178
 *         Object, Datetime, Timedelta#
4179
 * #kind = GENBOOL,
4180
 *         SIGNED, UNSIGNED, SIGNED, UNSIGNED, SIGNED, UNSIGNED,
4181
 *         SIGNED, UNSIGNED, SIGNED, UNSIGNED,
4182
 *         FLOATING, FLOATING, FLOATING, FLOATING,
4183
 *         COMPLEX, COMPLEX, COMPLEX,
4184
 *         OBJECT, DATETIME, TIMEDELTA#
4185
 * #endian = |*3, =*15, |, =*2#
4186
 * #isobject= 0*18,NPY_OBJECT_DTYPE_FLAGS,0*2#
4187
 */
4188

4189
static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
4190
    {
4191
        @from@_to_BOOL,
4192
        @from@_to_BYTE,
4193
        @from@_to_UBYTE,
4194
        @from@_to_SHORT,
4195
        @from@_to_USHORT,
4196
        @from@_to_INT,
4197
        @from@_to_UINT,
4198
        @from@_to_LONG,
4199
        @from@_to_ULONG,
4200
        @from@_to_LONGLONG,
4201
        @from@_to_ULONGLONG,
4202
        @from@_to_FLOAT,
4203
        @from@_to_DOUBLE,
4204
        @from@_to_LONGDOUBLE,
4205
        @from@_to_CFLOAT,
4206
        @from@_to_CDOUBLE,
4207
        @from@_to_CLONGDOUBLE,
4208
        @from@_to_OBJECT,
4209
        @from@_to_STRING,
4210
        @from@_to_UNICODE,
4211
        @from@_to_VOID
4212
    },
4213
    @from@_getitem,
4214
    @from@_setitem,
4215
    (PyArray_CopySwapNFunc*)@from@_copyswapn,
4216
    (PyArray_CopySwapFunc*)@from@_copyswap,
4217
    (PyArray_CompareFunc*)@from@_compare,
4218
    (PyArray_ArgFunc*)@from@_argmax,
4219
    (PyArray_DotFunc*)@from@_dot,
4220
    (PyArray_ScanFunc*)@from@_scan,
4221
    @from@_fromstr,
4222
    (PyArray_NonzeroFunc*)@from@_nonzero,
4223
    (PyArray_FillFunc*)@from@_fill,
4224
    (PyArray_FillWithScalarFunc*)@from@_fillwithscalar,
4225
#if @sort@
4226
    {
4227
        quicksort_@suff@,
4228
        heapsort_@suff@,
4229
        #if @rsort@
4230
            radixsort_@suff@
4231
        #else
4232
            timsort_@suff@
4233
        #endif
4234
    },
4235
    {
4236
        aquicksort_@suff@,
4237
        aheapsort_@suff@,
4238
        #if @rsort@
4239
            aradixsort_@suff@
4240
        #else
4241
            atimsort_@suff@
4242
        #endif
4243
    },
4244
#else
4245
    {
4246
        NULL, NULL, NULL
4247
    },
4248
    {
4249
        NULL, NULL, NULL
4250
    },
4251
#endif
4252
    NULL,
4253
    (PyArray_ScalarKindFunc*)NULL,
4254
    NULL,
4255
    NULL,
4256
    (PyArray_FastClipFunc*)NULL,
4257
    (PyArray_FastPutmaskFunc*)NULL,
4258
    (PyArray_FastTakeFunc*)NULL,
4259
    (PyArray_ArgFunc*)@from@_argmin
4260
};
4261

4262
/*
4263
 * FIXME: check for PY3K
4264
 */
4265
NPY_NO_EXPORT PyArray_Descr @from@_Descr = {
4266
    PyObject_HEAD_INIT(&PyArrayDescr_Type)
4267
    /* typeobj */
4268
    &Py@NAME@ArrType_Type,
4269
    /* kind */
4270
    NPY_@kind@LTR,
4271
    /* type */
4272
    NPY_@from@LTR,
4273
    /* byteorder */
4274
    '@endian@',
4275
    /* flags */
4276
    @isobject@,
4277
    /* type_num */
4278
    NPY_@from@,
4279
    /* elsize */
4280
    sizeof(@fromtype@),
4281
    /* alignment */
4282
    _ALIGN(@fromtype@),
4283
    /* subarray */
4284
    NULL,
4285
    /* fields */
4286
    NULL,
4287
    /* names */
4288
    NULL,
4289
    /* f */
4290
    &_Py@NAME@_ArrFuncs,
4291
    /* metadata */
4292
    NULL,
4293
    /* c_metadata */
4294
    NULL,
4295
    /* hash */
4296
    -1,
4297
};
4298

4299
/**end repeat**/
4300

4301
#define _MAX_LETTER 128
4302
static char _letter_to_num[_MAX_LETTER];
4303

4304
static PyArray_Descr *_builtin_descrs[] = {
4305
    &BOOL_Descr,
4306
    &BYTE_Descr,
4307
    &UBYTE_Descr,
4308
    &SHORT_Descr,
4309
    &USHORT_Descr,
4310
    &INT_Descr,
4311
    &UINT_Descr,
4312
    &LONG_Descr,
4313
    &ULONG_Descr,
4314
    &LONGLONG_Descr,
4315
    &ULONGLONG_Descr,
4316
    &FLOAT_Descr,
4317
    &DOUBLE_Descr,
4318
    &LONGDOUBLE_Descr,
4319
    &CFLOAT_Descr,
4320
    &CDOUBLE_Descr,
4321
    &CLONGDOUBLE_Descr,
4322
    &OBJECT_Descr,
4323
    &STRING_Descr,
4324
    &UNICODE_Descr,
4325
    &VOID_Descr,
4326
    &DATETIME_Descr,
4327
    &TIMEDELTA_Descr,
4328
    &HALF_Descr
4329
};
4330

4331
/*NUMPY_API
4332
 * Get the PyArray_Descr structure for a type.
4333
 */
4334
NPY_NO_EXPORT PyArray_Descr *
4335 1
PyArray_DescrFromType(int type)
4336
{
4337 1
    PyArray_Descr *ret = NULL;
4338

4339 1
    if (type < 0) {
4340
        /*
4341
         * It's not valid for type to be less than 0.
4342
         * If that happens, then no other branch of
4343
         * this if/else chain should be followed.
4344
         * This is effectively a no-op that ensures
4345
         * the default error is raised.
4346
         */
4347
        ret = NULL;
4348
    }
4349 1
    else if (type < NPY_NTYPES) {
4350 1
        ret = _builtin_descrs[type];
4351
    }
4352 1
    else if (type == NPY_NOTYPE) {
4353
        /*
4354
         * This needs to not raise an error so
4355
         * that PyArray_DescrFromType(NPY_NOTYPE)
4356
         * works for backwards-compatible C-API
4357
         */
4358
        return NULL;
4359
    }
4360 1
    else if ((type == NPY_CHAR) || (type == NPY_CHARLTR)) {
4361 1
        if (type == NPY_CHAR) {
4362
            /*
4363
             * warning added 2017-04-25, 1.13
4364
             * deprecated in 1.7
4365
             * */
4366 1
            if (DEPRECATE("The NPY_CHAR type_num is deprecated. "
4367
                          "Please port your code to use "
4368
                          "NPY_STRING instead.") < 0) {
4369
                return NULL;
4370
            }
4371
        }
4372 1
        ret = PyArray_DescrNew(_builtin_descrs[NPY_STRING]);
4373 1
        if (ret == NULL) {
4374
            return NULL;
4375
        }
4376 1
        ret->elsize = 1;
4377 1
        ret->type = NPY_CHARLTR;
4378 1
        return ret;
4379
    }
4380 1
    else if (PyTypeNum_ISUSERDEF(type)) {
4381 1
        ret = userdescrs[type - NPY_USERDEF];
4382
    }
4383
    else {
4384 1
        int num = NPY_NTYPES;
4385 1
        if (type < _MAX_LETTER) {
4386 1
            num = (int) _letter_to_num[type];
4387
        }
4388 1
        if (num >= NPY_NTYPES) {
4389
            ret = NULL;
4390
        }
4391
        else {
4392 1
            ret = _builtin_descrs[num];
4393
        }
4394
    }
4395 1
    if (ret == NULL) {
4396 0
        PyErr_SetString(PyExc_ValueError,
4397
                "Invalid data-type for array");
4398
    }
4399
    else {
4400 1
        Py_INCREF(ret);
4401
    }
4402

4403
    return ret;
4404
}
4405

4406
/*
4407
 *****************************************************************************
4408
 **                             SETUP TYPE INFO                             **
4409
 *****************************************************************************
4410
 */
4411

4412

4413
/*
4414
 * This function is called during numpy module initialization,
4415
 * and is used to initialize internal dtype tables.
4416
 */
4417
NPY_NO_EXPORT int
4418 1
set_typeinfo(PyObject *dict)
4419
{
4420
    PyObject *infodict, *s;
4421
    int i;
4422

4423
    PyArray_Descr *dtype;
4424
    PyObject *cobj, *key;
4425

4426
    /*
4427
     * Override the base class for all types, eventually all of this logic
4428
     * should be defined on the class and inherited to the scalar.
4429
     * (NPY_HALF is the largest builtin one.)
4430
     */
4431 1
    for (i = 0; i <= NPY_HALF; i++) {
4432 1
        if (dtypemeta_wrap_legacy_descriptor(_builtin_descrs[i]) < 0) {
4433
            return -1;
4434
        }
4435
    }
4436

4437
    /*
4438
     * Add cast functions for the new types
4439
     */
4440

4441
    /**begin repeat
4442
     *
4443
     * #name1 = BOOL,
4444
     *          BYTE, UBYTE, SHORT, USHORT, INT, UINT,
4445
     *          LONG, ULONG, LONGLONG, ULONGLONG,
4446
     *          HALF, FLOAT, DOUBLE, LONGDOUBLE,
4447
     *          CFLOAT, CDOUBLE, CLONGDOUBLE,
4448
     *          OBJECT, STRING, UNICODE, VOID,
4449
     *          DATETIME,TIMEDELTA#
4450
     */
4451

4452
    /**begin repeat1
4453
     *
4454
     * #name2 = HALF, DATETIME, TIMEDELTA#
4455
     */
4456

4457 1
    dtype = _builtin_descrs[NPY_@name1@];
4458 1
    if (dtype->f->castdict == NULL) {
4459 1
        dtype->f->castdict = PyDict_New();
4460 1
        if (dtype->f->castdict == NULL) {
4461
            return -1;
4462
        }
4463
    }
4464 1
    key = PyLong_FromLong(NPY_@name2@);
4465 1
    if (key == NULL) {
4466
        return -1;
4467
    }
4468 1
    cobj = NpyCapsule_FromVoidPtr((void *)@name1@_to_@name2@, NULL);
4469 1
    if (cobj == NULL) {
4470 0
        Py_DECREF(key);
4471
        return -1;
4472
    }
4473 1
    if (PyDict_SetItem(dtype->f->castdict, key, cobj) < 0) {
4474 0
        Py_DECREF(key);
4475 0
        Py_DECREF(cobj);
4476
        return -1;
4477
    }
4478 1
    Py_DECREF(key);
4479 1
    Py_DECREF(cobj);
4480

4481
    /**end repeat1**/
4482

4483
    /**end repeat**/
4484

4485 1
    _builtin_descrs[NPY_DATETIME]->c_metadata = _create_datetime_metadata(
4486
                NPY_DATETIME_DEFAULTUNIT, 1);
4487 1
    if (_builtin_descrs[NPY_DATETIME]->c_metadata == NULL) {
4488
        return -1;
4489
    }
4490 1
    _builtin_descrs[NPY_TIMEDELTA]->c_metadata = _create_datetime_metadata(
4491
                NPY_DATETIME_DEFAULTUNIT, 1);
4492 1
    if (_builtin_descrs[NPY_DATETIME]->c_metadata == NULL) {
4493
        return -1;
4494
    }
4495

4496 1
    for (i = 0; i < _MAX_LETTER; i++) {
4497 1
        _letter_to_num[i] = NPY_NTYPES;
4498
    }
4499

4500
    /**begin repeat
4501
     *
4502
     * #name = BOOL,
4503
     *         BYTE, UBYTE, SHORT, USHORT, INT, UINT,
4504
     *         INTP, UINTP,
4505
     *         LONG, ULONG, LONGLONG, ULONGLONG,
4506
     *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
4507
     *         CFLOAT, CDOUBLE, CLONGDOUBLE,
4508
     *         OBJECT, STRING, UNICODE, VOID,
4509
     *         DATETIME,TIMEDELTA#
4510
     */
4511

4512 1
    _letter_to_num[NPY_@name@LTR] = NPY_@name@;
4513

4514
    /**end repeat**/
4515

4516 1
    _letter_to_num[NPY_STRINGLTR2] = NPY_STRING;
4517

4518
    /**begin repeat
4519
      * #name = BOOL,
4520
      *         BYTE, UBYTE, SHORT, USHORT, INT, UINT,
4521
      *         LONG, ULONG, LONGLONG, ULONGLONG,
4522
      *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
4523
      *         CFLOAT, CDOUBLE, CLONGDOUBLE,
4524
      *         OBJECT, STRING, UNICODE, VOID,
4525
      *         DATETIME, TIMEDELTA#
4526
      */
4527

4528 1
    @name@_Descr.fields = Py_None;
4529

4530
    /**end repeat**/
4531

4532

4533
    /**begin repeat
4534
      * #name = STRING, UNICODE, VOID#
4535
      */
4536

4537 1
    PyDataType_MAKEUNSIZED(&@name@_Descr);
4538

4539
    /**end repeat**/
4540

4541 <