diff options
author | Jaime Fernandez <jaimefrio@google.com> | 2016-03-27 11:16:37 +0200 |
---|---|---|
committer | Jaime Fernandez <jaimefrio@google.com> | 2016-03-27 11:16:37 +0200 |
commit | 2df40376a944c39dbd68ac4510c3aa65a31ddf92 (patch) | |
tree | 6105920e29c7269580b344289cfc557c89a52701 /numpy | |
parent | 63f3f246f73873c40b32092b0052befeaa6d9d05 (diff) | |
download | numpy-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.c | 66 |
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) { |