diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-02-28 07:43:19 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-02-28 07:43:19 +0000 |
commit | a538c37f2a78fda5118ffa54f8b6257f11d4b5a3 (patch) | |
tree | 1e5e53569837dc9208627a31683a73e8d7a68e57 /numpy/core/src/arrayobject.c | |
parent | 3e5fdde668f661e82789bdd764ee6846f43efe84 (diff) | |
download | numpy-a538c37f2a78fda5118ffa54f8b6257f11d4b5a3.tar.gz |
Allow any integer as a stride (including zero --- though you need to understand that case to use it effectively). Also. fix a bug in strides_set that appeared when an array had say a string as it's base object instead of an array.
Diffstat (limited to 'numpy/core/src/arrayobject.c')
-rw-r--r-- | numpy/core/src/arrayobject.c | 84 |
1 files changed, 45 insertions, 39 deletions
diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index 5a54195f8..7530eba4a 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -3592,49 +3592,40 @@ PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) } /* This routine checks to see if newstrides (of length nd) will not - walk outside of the memory implied by a single segment array of the provided - dimensions and element size. If numbytes is 0 it will be calculated from - the provided shape and element size. - - For axes with a positive stride this function checks for a walk - beyond the right end of the buffer, for axes with a negative stride, - it checks for a walk beyond the left end of the buffer. Zero strides - are disallowed. + ever be able to walk outside of the memory implied numbytes and offset. + + The available memory is assumed to start at -offset and proceed + to numbytes-offset. The strides are checked to ensure + that accessing memory using striding will not try to reach beyond + this memory for any of the axes. + + If numbytes is 0 it will be calculated using the dimensions and + element-size. + + This function checks for walking beyond the beginning and right-end + of the buffer and therefore works for any integer stride (positive + or negative). */ + /*OBJECT_API*/ static Bool PyArray_CheckStrides(int elsize, int nd, intp numbytes, intp offset, intp *dims, intp *newstrides) { int i; - + intp byte_begin; + intp begin; + intp end; + if (numbytes == 0) numbytes = PyArray_MultiplyList(dims, nd) * elsize; - + + begin = -offset; + end = numbytes - offset - elsize; for (i=0; i<nd; i++) { - intp stride = newstrides[i]; - if (stride > 0) { - /* The last stride does not need to be fully inside - the buffer, only its first elsize bytes */ - if (offset + stride*(dims[i]-1)+elsize > numbytes) { - return FALSE; - } - } - else if (stride < 0) { - if (offset + stride*dims[i] < 0) { - return FALSE; - } - } else { - /* XXX: Zero strides may be useful, but currently - XXX: allowing them would lead to strange results, - XXX: for example : - XXX: >>> x = arange(5) - XXX: >>> x.strides = 0 - XXX: >>> x += 1 - XXX: >>> x - XXX: array([5, 5, 5, 5, 5]) */ + byte_begin = newstrides[i]*(dims[i]-1); + if ((byte_begin < begin) || (byte_begin > end)) return FALSE; - } } return TRUE; @@ -4334,7 +4325,10 @@ array_strides_set(PyArrayObject *self, PyObject *obj) { PyArray_Dims newstrides = {NULL, 0}; PyArrayObject *new; - intp numbytes; + intp numbytes=-1; + intp offset; + int buf_len; + char *buf; if (!PyArray_IntpConverter(obj, &newstrides) || \ newstrides.ptr == NULL) { @@ -4347,13 +4341,25 @@ array_strides_set(PyArrayObject *self, PyObject *obj) goto fail; } new = self; - while(new->base != NULL) { - if (PyArray_Check(new->base)) - new = (PyArrayObject *)new->base; + offset = 0; + while(PyArray_Check(new->base)) { + new = (PyArrayObject *)(new->base); + } + /* Get the available memory through the buffer + interface on new->base or if that fails + from the current new */ + if (PyObject_AsReadBuffer(new->base, (const void **)&buf, + &buf_len) >= 0) { + offset = self->data - buf; + numbytes = buf_len + offset; + } + else { + PyErr_Clear(); + numbytes = PyArray_MultiplyList(new->dimensions, + new->nd)*new->descr->elsize; + offset = self->data - new->data; } - numbytes = PyArray_MultiplyList(new->dimensions, - new->nd)*new->descr->elsize; - + if (!PyArray_CheckStrides(self->descr->elsize, self->nd, numbytes, self->data - new->data, self->dimensions, newstrides.ptr)) { |