summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/calculation.c35
-rw-r--r--numpy/core/tests/test_numeric.py8
2 files changed, 29 insertions, 14 deletions
diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c
index f30e0441d..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,9 +1103,18 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
if (out == newin) {
outgood = 1;
}
- if (!outgood && PyArray_ISONESEGMENT(out) &&
- /* Both are contiguous, but must be identically so */
- PyArray_ISFORTRAN(out) == PyArray_ISFORTRAN(self) &&
+
+
+ /* 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)) {
@@ -1113,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(self))
+ 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) {
@@ -1133,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 62aec1433..a1a92ef32 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -1730,6 +1730,14 @@ class TestClip(object):
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)