diff options
| author | Matti Picus <matti.picus@gmail.com> | 2019-04-10 08:36:53 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-10 08:36:53 +0300 |
| commit | 3837444977aaa207c0ce031ad0167ea0e2400506 (patch) | |
| tree | 07a44499a7d1d31422cc965a9b73e10528a58af7 /numpy/core/src | |
| parent | c5413e780a90c0f636d563b0d31ad812131aac0c (diff) | |
| parent | d6a8cabd725e93a1dcfc03f0b4154dd96fd4ce8f (diff) | |
| download | numpy-3837444977aaa207c0ce031ad0167ea0e2400506.tar.gz | |
Merge branch 'master' into isfinite-datetime
Diffstat (limited to 'numpy/core/src')
| -rw-r--r-- | numpy/core/src/multiarray/common.c | 2 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/item_selection.c | 3 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/iterators.c | 51 | ||||
| -rw-r--r-- | numpy/core/src/umath/fast_loop_macros.h | 121 | ||||
| -rw-r--r-- | numpy/core/src/umath/loops.c.src | 26 |
5 files changed, 95 insertions, 108 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index addb67732..52694d491 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -343,7 +343,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims, typestr = PyDict_GetItemString(ip, "typestr"); #if defined(NPY_PY3K) /* Allow unicode type strings */ - if (PyUnicode_Check(typestr)) { + if (typestr && PyUnicode_Check(typestr)) { tmp = PyUnicode_AsASCIIString(typestr); typestr = tmp; } diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c index ff7c1130a..6065c1df4 100644 --- a/numpy/core/src/multiarray/item_selection.c +++ b/numpy/core/src/multiarray/item_selection.c @@ -607,7 +607,8 @@ PyArray_Repeat(PyArrayObject *aop, PyObject *op, int axis) else { for (j = 0; j < n; j++) { if (counts[j] < 0) { - PyErr_SetString(PyExc_ValueError, "count < 0"); + PyErr_SetString(PyExc_ValueError, + "repeats may not contain negative values."); goto fail; } total += counts[j]; diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c index a3bc8e742..9fcdc91b2 100644 --- a/numpy/core/src/multiarray/iterators.c +++ b/numpy/core/src/multiarray/iterators.c @@ -539,6 +539,7 @@ iter_subscript(PyArrayIterObject *self, PyObject *ind) char *dptr; int size; PyObject *obj = NULL; + PyObject *new; PyArray_CopySwapFunc *copyswap; if (ind == Py_Ellipsis) { @@ -640,36 +641,36 @@ iter_subscript(PyArrayIterObject *self, PyObject *ind) obj = ind; } - if (PyArray_Check(obj)) { - /* Check for Boolean object */ - if (PyArray_TYPE((PyArrayObject *)obj) == NPY_BOOL) { - ret = iter_subscript_Bool(self, (PyArrayObject *)obj); - Py_DECREF(indtype); - } - /* Check for integer array */ - else if (PyArray_ISINTEGER((PyArrayObject *)obj)) { - PyObject *new; - new = PyArray_FromAny(obj, indtype, 0, 0, - NPY_ARRAY_FORCECAST | NPY_ARRAY_ALIGNED, NULL); - if (new == NULL) { - goto fail; - } - Py_DECREF(obj); - obj = new; - new = iter_subscript_int(self, (PyArrayObject *)obj); - Py_DECREF(obj); - return new; - } - else { - goto fail; - } + /* Any remaining valid input is an array or has been turned into one */ + if (!PyArray_Check(obj)) { + goto fail; + } + + /* Check for Boolean array */ + if (PyArray_TYPE((PyArrayObject *)obj) == NPY_BOOL) { + ret = iter_subscript_Bool(self, (PyArrayObject *)obj); + Py_DECREF(indtype); Py_DECREF(obj); return (PyObject *)ret; } - else { - Py_DECREF(indtype); + + /* Only integer arrays left */ + if (!PyArray_ISINTEGER((PyArrayObject *)obj)) { + goto fail; } + Py_INCREF(indtype); + new = PyArray_FromAny(obj, indtype, 0, 0, + NPY_ARRAY_FORCECAST | NPY_ARRAY_ALIGNED, NULL); + if (new == NULL) { + goto fail; + } + Py_DECREF(indtype); + Py_DECREF(obj); + ret = (PyArrayObject *)iter_subscript_int(self, (PyArrayObject *)new); + Py_DECREF(new); + return (PyObject *)ret; + fail: if (!PyErr_Occurred()) { diff --git a/numpy/core/src/umath/fast_loop_macros.h b/numpy/core/src/umath/fast_loop_macros.h index e3cfa1f72..7a1ed66bc 100644 --- a/numpy/core/src/umath/fast_loop_macros.h +++ b/numpy/core/src/umath/fast_loop_macros.h @@ -74,73 +74,52 @@ #define IS_BINARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \ steps[1] == sizeof(tin) && \ steps[2] == sizeof(tout)) + /* binary loop input and output contiguous with first scalar */ #define IS_BINARY_CONT_S1(tin, tout) (steps[0] == 0 && \ steps[1] == sizeof(tin) && \ steps[2] == sizeof(tout)) + /* binary loop input and output contiguous with second scalar */ #define IS_BINARY_CONT_S2(tin, tout) (steps[0] == sizeof(tin) && \ steps[1] == 0 && \ steps[2] == sizeof(tout)) - -/* - * loop with contiguous specialization - * op should be the code storing the result in `tout * out` - * combine with NPY_GCC_OPT_3 to allow autovectorization - * should only be used where its worthwhile to avoid code bloat - */ -#define BASE_OUTPUT_LOOP(tout, op) \ - OUTPUT_LOOP { \ - tout * out = (tout *)op1; \ - op; \ - } -#define OUTPUT_LOOP_FAST(tout, op) \ - do { \ - /* condition allows compiler to optimize the generic macro */ \ - if (IS_OUTPUT_CONT(tout)) { \ - BASE_OUTPUT_LOOP(tout, op) \ - } \ - else { \ - BASE_OUTPUT_LOOP(tout, op) \ - } \ - } \ - while (0) - /* * loop with contiguous specialization * op should be the code working on `tin in` and - * storing the result in `tout * out` + * storing the result in `tout *out` * combine with NPY_GCC_OPT_3 to allow autovectorization * should only be used where its worthwhile to avoid code bloat */ #define BASE_UNARY_LOOP(tin, tout, op) \ UNARY_LOOP { \ const tin in = *(tin *)ip1; \ - tout * out = (tout *)op1; \ + tout *out = (tout *)op1; \ op; \ } -#define UNARY_LOOP_FAST(tin, tout, op) \ + +#define UNARY_LOOP_FAST(tin, tout, op) \ do { \ - /* condition allows compiler to optimize the generic macro */ \ - if (IS_UNARY_CONT(tin, tout)) { \ - if (args[0] == args[1]) { \ - BASE_UNARY_LOOP(tin, tout, op) \ + /* condition allows compiler to optimize the generic macro */ \ + if (IS_UNARY_CONT(tin, tout)) { \ + if (args[0] == args[1]) { \ + BASE_UNARY_LOOP(tin, tout, op) \ + } \ + else { \ + BASE_UNARY_LOOP(tin, tout, op) \ + } \ } \ else { \ BASE_UNARY_LOOP(tin, tout, op) \ } \ } \ - else { \ - BASE_UNARY_LOOP(tin, tout, op) \ - } \ - } \ while (0) /* * loop with contiguous specialization * op should be the code working on `tin in1`, `tin in2` and - * storing the result in `tout * out` + * storing the result in `tout *out` * combine with NPY_GCC_OPT_3 to allow autovectorization * should only be used where its worthwhile to avoid code bloat */ @@ -148,9 +127,10 @@ BINARY_LOOP { \ const tin in1 = *(tin *)ip1; \ const tin in2 = *(tin *)ip2; \ - tout * out = (tout *)op1; \ + tout *out = (tout *)op1; \ op; \ } + /* * unfortunately gcc 6/7 regressed and we need to give it additional hints to * vectorize inplace operations (PR80198) @@ -171,59 +151,62 @@ for(i = 0; i < n; i++, ip1 += is1, ip2 += is2, op1 += os1) { \ const tin in1 = *(tin *)ip1; \ const tin in2 = *(tin *)ip2; \ - tout * out = (tout *)op1; \ + tout *out = (tout *)op1; \ op; \ } + #define BASE_BINARY_LOOP_S(tin, tout, cin, cinp, vin, vinp, op) \ const tin cin = *(tin *)cinp; \ BINARY_LOOP { \ const tin vin = *(tin *)vinp; \ - tout * out = (tout *)op1; \ + tout *out = (tout *)op1; \ op; \ } + /* PR80198 again, scalar works without the pragma */ #define BASE_BINARY_LOOP_S_INP(tin, tout, cin, cinp, vin, vinp, op) \ const tin cin = *(tin *)cinp; \ BINARY_LOOP { \ const tin vin = *(tin *)vinp; \ - tout * out = (tout *)vinp; \ + tout *out = (tout *)vinp; \ op; \ } -#define BINARY_LOOP_FAST(tin, tout, op) \ + +#define BINARY_LOOP_FAST(tin, tout, op) \ do { \ - /* condition allows compiler to optimize the generic macro */ \ - if (IS_BINARY_CONT(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[0]) == 0 && \ - abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \ - BASE_BINARY_LOOP_INP(tin, tout, op) \ + /* condition allows compiler to optimize the generic macro */ \ + if (IS_BINARY_CONT(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[0]) == 0 && \ + abs_ptrdiff(args[2], args[1]) >= NPY_MAX_SIMD_SIZE) { \ + BASE_BINARY_LOOP_INP(tin, tout, op) \ + } \ + else if (abs_ptrdiff(args[2], args[1]) == 0 && \ + abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \ + BASE_BINARY_LOOP_INP(tin, tout, op) \ + } \ + else { \ + BASE_BINARY_LOOP(tin, tout, op) \ + } \ } \ - else if (abs_ptrdiff(args[2], args[1]) == 0 && \ - abs_ptrdiff(args[2], args[0]) >= NPY_MAX_SIMD_SIZE) { \ - BASE_BINARY_LOOP_INP(tin, tout, op) \ + else if (IS_BINARY_CONT_S1(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[1]) == 0) { \ + BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \ + } \ + else { \ + BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \ + } \ } \ - else { \ - BASE_BINARY_LOOP(tin, tout, op) \ - } \ - } \ - else if (IS_BINARY_CONT_S1(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[1]) == 0) { \ - BASE_BINARY_LOOP_S_INP(tin, tout, in1, args[0], in2, ip2, op) \ + else if (IS_BINARY_CONT_S2(tin, tout)) { \ + if (abs_ptrdiff(args[2], args[0]) == 0) { \ + BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \ + } \ + else { \ + BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \ + }\ } \ else { \ - BASE_BINARY_LOOP_S(tin, tout, in1, args[0], in2, ip2, op) \ - } \ - } \ - else if (IS_BINARY_CONT_S2(tin, tout)) { \ - if (abs_ptrdiff(args[2], args[0]) == 0) { \ - BASE_BINARY_LOOP_S_INP(tin, tout, in2, args[1], in1, ip1, op) \ + BASE_BINARY_LOOP(tin, tout, op) \ } \ - else { \ - BASE_BINARY_LOOP_S(tin, tout, in2, args[1], in1, ip1, op) \ - }\ - } \ - else { \ - BASE_BINARY_LOOP(tin, tout, op) \ - } \ } \ while (0) diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index 1e65acd3b..290a87a33 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -652,7 +652,11 @@ BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN NPY_NO_EXPORT void BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - OUTPUT_LOOP_FAST(npy_bool, *out = @val@); + /* + * The (void)in; suppresses an unused variable warning raised by gcc and allows + * us to re-use this macro even though we do not depend on in + */ + UNARY_LOOP_FAST(npy_bool, npy_bool, (void)in; *out = @val@); } /**end repeat**/ @@ -896,7 +900,11 @@ NPY_NO_EXPORT void NPY_NO_EXPORT void @TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - OUTPUT_LOOP_FAST(npy_bool, *out = @val@); + /* + * The (void)in; suppresses an unused variable warning raised by gcc and allows + * us to re-use this macro even though we do not depend on in + */ + UNARY_LOOP_FAST(@type@, npy_bool, (void)in; *out = @val@); } /**end repeat1**/ @@ -1019,13 +1027,10 @@ NPY_NO_EXPORT void * #c = u,u,u,ul,ull# */ -NPY_NO_EXPORT void +NPY_NO_EXPORT NPY_GCC_OPT_3 void @TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - UNARY_LOOP { - const @type@ in1 = *(@type@ *)ip1; - *((@type@ *)op1) = in1; - } + UNARY_LOOP_FAST(@type@, @type@, *out = in); } NPY_NO_EXPORT NPY_GCC_OPT_3 void @@ -2232,13 +2237,10 @@ HALF_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU } } -NPY_NO_EXPORT void +NPY_NO_EXPORT NPY_GCC_OPT_3 void HALF_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - UNARY_LOOP { - const npy_half in1 = *(npy_half *)ip1; - *((npy_half *)op1) = in1&0x7fffu; - } + UNARY_LOOP_FAST(npy_half, npy_half, *out = in&0x7fffu); } NPY_NO_EXPORT void |
