summaryrefslogtreecommitdiff
path: root/numpy/core/src
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2019-04-10 08:36:53 +0300
committerGitHub <noreply@github.com>2019-04-10 08:36:53 +0300
commit3837444977aaa207c0ce031ad0167ea0e2400506 (patch)
tree07a44499a7d1d31422cc965a9b73e10528a58af7 /numpy/core/src
parentc5413e780a90c0f636d563b0d31ad812131aac0c (diff)
parentd6a8cabd725e93a1dcfc03f0b4154dd96fd4ce8f (diff)
downloadnumpy-3837444977aaa207c0ce031ad0167ea0e2400506.tar.gz
Merge branch 'master' into isfinite-datetime
Diffstat (limited to 'numpy/core/src')
-rw-r--r--numpy/core/src/multiarray/common.c2
-rw-r--r--numpy/core/src/multiarray/item_selection.c3
-rw-r--r--numpy/core/src/multiarray/iterators.c51
-rw-r--r--numpy/core/src/umath/fast_loop_macros.h121
-rw-r--r--numpy/core/src/umath/loops.c.src26
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