[Numpy-discussion] Learning "strides"
Sasha
ndarray at mac.com
Fri Feb 3 10:10:02 EST 2006
On Feb 2, 2006, at 10:02 PM, Travis Oliphant wrote:
>>
>> Please let me know if you plan to change PyArray_CheckStrides so that
>> we don't duplicate effort.
>>
>>
> I won't do anything with it in the near future.
>
Attached patch deals with negative strides and prohibits zero
strides. I think we can agree that this is the right behavior while
zero-stride semantics are being discussed. Since I am touching C-
API, I would like you to take a look before I commit. Also I am not
sure "self->data - new->data" is always the right was to compute
offset in array_strides_set .
-- sasha
-------------- next part --------------
Index: numpy/core/include/numpy/arrayobject.h
===================================================================
--- numpy/core/include/numpy/arrayobject.h (revision 2053)
+++ numpy/core/include/numpy/arrayobject.h (working copy)
@@ -74,7 +74,7 @@
#define PY_SUCCEED 1
/* Helpful to distinguish what is installed */
-#define NDARRAY_VERSION 0x00090403
+#define NDARRAY_VERSION 0x00090404
/* Some platforms don't define bool, long long, or long double.
Handle that here.
Index: numpy/core/src/arrayobject.c
===================================================================
--- numpy/core/src/arrayobject.c (revision 2053)
+++ numpy/core/src/arrayobject.c (working copy)
@@ -3517,7 +3517,7 @@
*/
/*OBJECT_API*/
static Bool
-PyArray_CheckStrides(int elsize, int nd, intp numbytes,
+PyArray_CheckStrides(int elsize, int nd, intp numbytes, intp offset,
intp *dims, intp *newstrides)
{
int i;
@@ -3526,7 +3526,17 @@
numbytes = PyArray_MultiplyList(dims, nd) * elsize;
for (i=0; i<nd; i++) {
- if (newstrides[i]*(dims[i]-1)+elsize > numbytes) {
+ intp stride = newstrides[i];
+ if (stride > 0) {
+ if (offset + stride*(dims[i]-1)+elsize > numbytes) {
+ return FALSE;
+ }
+ }
+ else if (stride < 0) {
+ if (offset + stride*dims[i] < 0) {
+ return FALSE;
+ }
+ } else {
return FALSE;
}
}
@@ -4064,10 +4074,8 @@
}
}
else { /* buffer given -- use it */
- buffer.len -= offset;
- buffer.ptr += offset;
if (dims.len == 1 && dims.ptr[0] == -1) {
- dims.ptr[0] = buffer.len / itemsize;
+ dims.ptr[offset] = buffer.len / itemsize;
}
else if (buffer.len < itemsize* \
PyArray_MultiplyList(dims.ptr, dims.len)) {
@@ -4084,7 +4092,7 @@
goto fail;
}
if (!PyArray_CheckStrides(itemsize, strides.len,
- buffer.len,
+ buffer.len, offset,
dims.ptr, strides.ptr)) {
PyErr_SetString(PyExc_ValueError,
"strides is incompatible "\
@@ -4104,7 +4112,7 @@
PyArray_NewFromDescr(subtype, descr,
dims.len, dims.ptr,
strides.ptr,
- (char *)buffer.ptr,
+ offset + (char *)buffer.ptr,
buffer.flags, NULL);
if (ret == NULL) {descr=NULL; goto fail;}
PyArray_UpdateFlags(ret, UPDATE_ALL_FLAGS);
@@ -4222,7 +4230,8 @@
numbytes = PyArray_MultiplyList(new->dimensions,
new->nd)*new->descr->elsize;
- if (!PyArray_CheckStrides(self->descr->elsize, self->nd, numbytes,
+ if (!PyArray_CheckStrides(self->descr->elsize, self->nd, numbytes,
+ self->data - new->data,
self->dimensions, newstrides.ptr)) {
PyErr_SetString(PyExc_ValueError, "strides is not "\
"compatible with available memory");
Index: numpy/core/tests/test_multiarray.py
===================================================================
--- numpy/core/tests/test_multiarray.py (revision 2053)
+++ numpy/core/tests/test_multiarray.py (working copy)
@@ -62,6 +62,34 @@
assert_equal(self.one.dtype.str[1], 'i')
assert_equal(self.three.dtype.str[1], 'f')
+ def check_stridesattr(self):
+ x = self.one
+ def make_array(size, offset, strides):
+ return ndarray([size], buffer=x,
+ offset=offset*x.itemsize,
+ strides=strides*x.itemsize)
+ assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1]))
+ self.failUnlessRaises(ValueError, make_array, 4, 4, -2)
+ self.failUnlessRaises(ValueError, make_array, 4, 3, -1)
+ self.failUnlessRaises(ValueError, make_array, 8, 3, 1)
+ self.failUnlessRaises(ValueError, make_array, 8, 3, 0)
+
+ def check_set_stridesattr(self):
+ x = self.one
+ def make_array(size, offset, strides):
+ try:
+ r = ndarray([size], buffer=x, offset=offset*x.itemsize)
+ except:
+ pass
+ r.strides = strides=strides*x.itemsize
+ return r
+ assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1]))
+ self.failUnlessRaises(ValueError, make_array, 4, 4, -2)
+ self.failUnlessRaises(ValueError, make_array, 4, 3, -1)
+ self.failUnlessRaises(ValueError, make_array, 8, 3, 1)
+ self.failUnlessRaises(ValueError, make_array, 8, 3, 0)
+
+
class test_dtypedescr(ScipyTestCase):
def check_construction(self):
d1 = dtype('i4')
More information about the NumPy-Discussion
mailing list