summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorMarten van Kerkwijk <mhvk@astro.utoronto.ca>2018-08-04 15:15:42 +0200
committerGitHub <noreply@github.com>2018-08-04 15:15:42 +0200
commit9d0225b800df3c2b0bffee9960df87b15527509c (patch)
tree5d8116dd77dcc89c5df42b7d3ef28b0eda28e62d /numpy/core
parentb5e01bcb668da0413170a886c258e00d2540e752 (diff)
parent537135661dd2b589bca1969f1cef24525b4a95d0 (diff)
downloadnumpy-9d0225b800df3c2b0bffee9960df87b15527509c.tar.gz
Merge pull request #11615 from seberg/clip_order
BUG: Clip uses wrong memory order in output
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/src/multiarray/calculation.c33
-rw-r--r--numpy/core/tests/test_numeric.py20
2 files changed, 39 insertions, 14 deletions
diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c
index e47dd81b9..90ee2c5b2 100644
--- a/numpy/core/src/multiarray/calculation.c
+++ b/numpy/core/src/multiarray/calculation.c
@@ -5,6 +5,7 @@
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#include "numpy/arrayobject.h"
+#include "lowlevel_strided_loops.h"
#include "npy_config.h"
@@ -1102,7 +1103,18 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
if (out == newin) {
outgood = 1;
}
- if (!outgood && PyArray_ISONESEGMENT(out) &&
+
+
+ /* make sure the shape of the output array is the same */
+ if (!PyArray_SAMESHAPE(newin, out)) {
+ PyErr_SetString(PyExc_ValueError, "clip: Output array must have the"
+ "same shape as the input.");
+ goto fail;
+ }
+
+ if (!outgood && PyArray_EQUIVALENTLY_ITERABLE(
+ self, out, PyArray_TRIVIALLY_ITERABLE_OP_READ,
+ PyArray_TRIVIALLY_ITERABLE_OP_NOREAD) &&
PyArray_CHKFLAGS(out, NPY_ARRAY_ALIGNED) &&
PyArray_ISNOTSWAPPED(out) &&
PyArray_EquivTypes(PyArray_DESCR(out), indescr)) {
@@ -1111,15 +1123,19 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
/*
* Do we still not have a suitable output array?
- * Create one, now
+ * Create one, now. No matter why the array is not suitable a copy has
+ * to be made. This may be just to avoid memory overlap though.
*/
if (!outgood) {
int oflags;
- if (PyArray_ISFORTRAN(out))
+ if (PyArray_ISFORTRAN(self)) {
oflags = NPY_ARRAY_FARRAY;
- else
+ }
+ else {
oflags = NPY_ARRAY_CARRAY;
- oflags |= NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_FORCECAST;
+ }
+ oflags |= (NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_FORCECAST |
+ NPY_ARRAY_ENSURECOPY);
Py_INCREF(indescr);
newout = (PyArrayObject*)PyArray_FromArray(out, indescr, oflags);
if (newout == NULL) {
@@ -1131,13 +1147,6 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
Py_INCREF(newout);
}
- /* make sure the shape of the output array is the same */
- if (!PyArray_SAMESHAPE(newin, newout)) {
- PyErr_SetString(PyExc_ValueError, "clip: Output array must have the"
- "same shape as the input.");
- goto fail;
- }
-
/* Now we can call the fast-clip function */
min_data = max_data = NULL;
if (mina != NULL) {
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index 53486dc51..a1a92ef32 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -1530,7 +1530,7 @@ class TestClip(object):
m = -0.5
M = 0.6
self.fastclip(a, m, M, a)
- self.clip(a, m, M, ac)
+ self.clip(ac, m, M, ac)
assert_array_strict_equal(a, ac)
def test_noncontig_inplace(self):
@@ -1543,7 +1543,7 @@ class TestClip(object):
m = -0.5
M = 0.6
self.fastclip(a, m, M, a)
- self.clip(a, m, M, ac)
+ self.clip(ac, m, M, ac)
assert_array_equal(a, ac)
def test_type_cast_01(self):
@@ -1722,6 +1722,22 @@ class TestClip(object):
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
+ def test_clip_with_out_transposed(self):
+ # Test that the out argument works when tranposed
+ a = np.arange(16).reshape(4, 4)
+ out = np.empty_like(a).T
+ a.clip(4, 10, out=out)
+ expected = self.clip(a, 4, 10)
+ assert_array_equal(out, expected)
+
+ def test_clip_with_out_memory_overlap(self):
+ # Test that the out argument works when it has memory overlap
+ a = np.arange(16).reshape(4, 4)
+ ac = a.copy()
+ a[:-1].clip(4, 10, out=a[1:])
+ expected = self.clip(ac[:-1], 4, 10)
+ assert_array_equal(a[1:], expected)
+
def test_clip_inplace_array(self):
# Test native double input with array min/max
a = self._generate_data(self.nr, self.nc)