Hello, looking at the code, when only adding/removing dimensions with size 1, numpy takes a small shortcut, however it uses 0 stride lengths as value for the new one element dimensions temporarily, then replacing it again to ensure the new array is contiguous. This replacing does not check if the dimension has more then size 1. Likely there is a better way to fix it, but the attached diff should do it.
Regards, Sebastian On Do, 2012-08-09 at 13:06 +0000, Dave Hirschfeld wrote: > Dave Hirschfeld <dave.hirschfeld <at> gmail.com> writes: > > > > > It seems that reshape doesn't work correctly on an array which has been > > resized using the 0-stride trick e.g. > > > > In [73]: x = array([5]) > > > > In [74]: y = as_strided(x, shape=(10,), strides=(0,)) > > > > In [75]: y > > Out[75]: array([5, 5, 5, 5, 5, 5, 5, 5, 5, 5]) > > > > In [76]: y.reshape([10,1]) > > Out[76]: > > array([[ 5], > > [ 8], > > [ 762933412], > > [-2013265919], > > [ 26], > > [ 64], > > [ 762933414], > > [-2013244356], > > [ 26], > > [ 64]]) <================ Should all be 5???????? > > > > In [77]: y.copy().reshape([10,1]) > > Out[77]: > > array([[5], > > [5], > > [5], > > [5], > > [5], > > [5], > > [5], > > [5], > > [5], > > [5]])--- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -273,21 +273,21 @@ PyArray_Newshape(PyArrayObject *self, PyArray_Dims *newdims, * appropriate value to preserve contiguousness */ if (order == NPY_FORTRANORDER) { - if (strides[0] == 0) { + if ((strides[0] == 0) && (dimensions[0] == 1)) { strides[0] = PyArray_DESCR(self)->elsize; } for (i = 1; i < ndim; i++) { - if (strides[i] == 0) { + if ((strides[i] == 0) && (dimensions[i] == 1)) { strides[i] = strides[i-1] * dimensions[i-1]; } } } else { - if (strides[ndim-1] == 0) { + if ((strides[ndim-1] == 0) && (dimensions[ndim-1] == 1)) { strides[ndim-1] = PyArray_DESCR(self)->elsize; } for (i = ndim - 2; i > -1; i--) { - if (strides[i] == 0) { + if ((strides[i] == 0) && (dimensions[i] == 1)) { strides[i] = strides[i+1] * dimensions[i+1]; } } > > > > In [78]: np.__version__ > > Out[78]: '1.6.2' > > > > Perhaps a clause such as below is required in reshape? > > > > if any(stride == 0 for stride in y.strides): > > return y.copy().reshape(shape) > > else: > > return y.reshape(shape) > > > > Regards, > > Dave > > > > Though it would be good to avoid the copy which you should be able to do in > this > case. Investigating further: > > In [15]: y.strides > Out[15]: (0,) > > In [16]: z = y.reshape([10,1]) > > In [17]: z.strides > Out[17]: (4, 4) > > In [18]: z.strides = (0, 4) > > In [19]: z > Out[19]: > array([[5], > [5], > [5], > [5], > [5], > [5], > [5], > [5], > [5], > [5]]) > > In [32]: y.reshape([5, 2]) > Out[32]: > array([[5, 5], > [5, 5], > [5, 5], > [5, 5], > [5, 5]]) > > In [33]: y.reshape([5, 2]).strides > Out[33]: (0, 0) > > So it seems that reshape is incorrectly setting the stride of axis0 to 4, but > only when the appended axis is of size 1. > > -Dave > > > > > _______________________________________________ > NumPy-Discussion mailing list > NumPy-Discussion@scipy.org > http://mail.scipy.org/mailman/listinfo/numpy-discussion >
>From eed2abca6144e16c5d9ca208ef90dd01f7dd6009 Mon Sep 17 00:00:00 2001 From: Sebastian Berg <sebast...@sipsolutions.net> Date: Thu, 9 Aug 2012 17:17:32 +0200 Subject: [PATCH] Fix reshaping of arrays with stride 0 in a dimension with size of more then 1. --- numpy/core/src/multiarray/shape.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c index 0672326..09a6cb0 100644 --- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -273,21 +273,21 @@ PyArray_Newshape(PyArrayObject *self, PyArray_Dims *newdims, * appropriate value to preserve contiguousness */ if (order == NPY_FORTRANORDER) { - if (strides[0] == 0) { + if ((strides[0] == 0) && (dimensions[0] == 1)) { strides[0] = PyArray_DESCR(self)->elsize; } for (i = 1; i < ndim; i++) { - if (strides[i] == 0) { + if ((strides[i] == 0) && (dimensions[i] == 1)) { strides[i] = strides[i-1] * dimensions[i-1]; } } } else { - if (strides[ndim-1] == 0) { + if ((strides[ndim-1] == 0) && (dimensions[ndim-1] == 1)) { strides[ndim-1] = PyArray_DESCR(self)->elsize; } for (i = ndim - 2; i > -1; i--) { - if (strides[i] == 0) { + if ((strides[i] == 0) && (dimensions[i] == 1)) { strides[i] = strides[i+1] * dimensions[i+1]; } } -- 1.7.9.5
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion