summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorJaime Fernandez <jaimefrio@google.com>2016-03-27 11:16:37 +0200
committerJaime Fernandez <jaimefrio@google.com>2016-03-27 11:16:37 +0200
commit2df40376a944c39dbd68ac4510c3aa65a31ddf92 (patch)
tree6105920e29c7269580b344289cfc557c89a52701 /numpy
parent63f3f246f73873c40b32092b0052befeaa6d9d05 (diff)
downloadnumpy-2df40376a944c39dbd68ac4510c3aa65a31ddf92.tar.gz
BUG: more on inplace reductions, fixes #615
This is a follow up to #7407 and #7466. It fixes an error in the comments (0 is the output and 1 is the input), moves them around so they apply to both branches of the if/else, and changes memcpy to memmove, since the memory segments can be overlapping, as pointed out by Valgrind in a really old issue.
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/umath/ufunc_object.c66
1 files changed, 38 insertions, 28 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 52299c1be..28c59f890 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -3293,13 +3293,16 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
dataptr_copy[1] = dataptr[1];
dataptr_copy[2] = dataptr[0];
- /* Copy the first element to start the reduction */
+ /*
+ * Copy the first element to start the reduction.
+ *
+ * Output (dataptr[0]) and input (dataptr[1]) may point to
+ * the same memory, e.g. np.add.accumulate(a, out=a).
+ */
if (otype == NPY_OBJECT) {
/*
- * Input (dataptr[0]) and output (dataptr[1]) may point
- * to the same memory (i.e. np.add.accumulate(a, out=a)).
- * In that case need to incref before decref to avoid the
- * possibility of the reference count being zero temporarily.
+ * Incref before decref to avoid the possibility of the
+ * reference count being zero temporarily.
*/
Py_XINCREF(*(PyObject **)dataptr_copy[1]);
Py_XDECREF(*(PyObject **)dataptr_copy[0]);
@@ -3307,7 +3310,7 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
*(PyObject **)dataptr_copy[1];
}
else {
- memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
+ memmove(dataptr_copy[0], dataptr_copy[1], itemsize);
}
if (count_m1 > 0) {
@@ -3355,13 +3358,16 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
dataptr_copy[1] = PyArray_BYTES(op[1]);
dataptr_copy[2] = PyArray_BYTES(op[0]);
- /* Copy the first element to start the reduction */
+ /*
+ * Copy the first element to start the reduction.
+ *
+ * Output (dataptr[0]) and input (dataptr[1]) may point to the
+ * same memory, e.g. np.add.accumulate(a, out=a).
+ */
if (otype == NPY_OBJECT) {
/*
- * Input (dataptr[0]) and output (dataptr[1]) may point
- * to the same memory (i.e. np.add.accumulate(a, out=a, axis=0)).
- * In that case need to incref before decref to avoid the
- * possibility of the reference count being zero temporarily.
+ * Incref before decref to avoid the possibility of the
+ * reference count being zero temporarily.
*/
Py_XINCREF(*(PyObject **)dataptr_copy[1]);
Py_XDECREF(*(PyObject **)dataptr_copy[0]);
@@ -3369,7 +3375,7 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
*(PyObject **)dataptr_copy[1];
}
else {
- memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
+ memmove(dataptr_copy[0], dataptr_copy[1], itemsize);
}
if (count > 1) {
@@ -3698,15 +3704,17 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
dataptr_copy[1] = dataptr[1] + stride1*start;
dataptr_copy[2] = dataptr[0] + stride0_ind*i;
- /* Copy the first element to start the reduction */
+ /*
+ * Copy the first element to start the reduction.
+ *
+ * Output (dataptr[0]) and input (dataptr[1]) may point
+ * to the same memory, e.g.
+ * np.add.reduceat(a, np.arange(len(a)), out=a).
+ */
if (otype == NPY_OBJECT) {
/*
- * Input (dataptr[0]) and output (dataptr[1]) may
- * point to the same memory, e.g.
- * np.add.reduceat(a, np.arange(len(a)), out=a).
- * In that case need to incref before decref to
- * avoid the possibility of the reference count
- * being zero temporarily.
+ * Incref before decref to avoid the possibility of
+ * the reference count being zero temporarily.
*/
Py_XINCREF(*(PyObject **)dataptr_copy[1]);
Py_XDECREF(*(PyObject **)dataptr_copy[0]);
@@ -3714,7 +3722,7 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
*(PyObject **)dataptr_copy[1];
}
else {
- memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
+ memmove(dataptr_copy[0], dataptr_copy[1], itemsize);
}
if (count > 1) {
@@ -3764,15 +3772,17 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
dataptr_copy[1] = PyArray_BYTES(op[1]) + stride1*start;
dataptr_copy[2] = PyArray_BYTES(op[0]) + stride0_ind*i;
- /* Copy the first element to start the reduction */
+ /*
+ * Copy the first element to start the reduction.
+ *
+ * Output (dataptr[0]) and input (dataptr[1]) may point to
+ * the same memory, e.g.
+ * np.add.reduceat(a, np.arange(len(a)), out=a).
+ */
if (otype == NPY_OBJECT) {
/*
- * Input (dataptr[0]) and output (dataptr[1]) may point
- * to the same memory, e.g.
- * np.add.reduceat(a, np.arange(len(a)), out=a).
- * In that case need to incref before decref to avoid
- * the possibility of the reference count being zero
- * temporarily.
+ * Incref before decref to avoid the possibility of the
+ * reference count being zero temporarily.
*/
Py_XINCREF(*(PyObject **)dataptr_copy[1]);
Py_XDECREF(*(PyObject **)dataptr_copy[0]);
@@ -3780,7 +3790,7 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind,
*(PyObject **)dataptr_copy[1];
}
else {
- memcpy(dataptr_copy[0], dataptr_copy[1], itemsize);
+ memmove(dataptr_copy[0], dataptr_copy[1], itemsize);
}
if (count > 1) {