summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorStefan Krah <skrah@bytereef.org>2015-02-01 13:53:54 (GMT)
committerStefan Krah <skrah@bytereef.org>2015-02-01 13:53:54 (GMT)
commit363af44a4abff02ece61e456d55824f298448992 (patch)
tree1ecc31d3808152ca2f09ded5594cb715dc32a4c2 /Objects
parenta5e1dbef146b9d1aece4e3def828d2b216a07e41 (diff)
downloadcpython-363af44a4abff02ece61e456d55824f298448992.zip
cpython-363af44a4abff02ece61e456d55824f298448992.tar.gz
cpython-363af44a4abff02ece61e456d55824f298448992.tar.bz2
Issue #22445: PyBuffer_IsContiguous() now implements precise contiguity
tests, compatible with NumPy's NPY_RELAXED_STRIDES_CHECKING compilation flag. Previously the function reported false negatives for corner cases.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/abstract.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 9ab60f2..92d1ac8 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -367,16 +367,35 @@ _IsFortranContiguous(const Py_buffer *view)
Py_ssize_t sd, dim;
int i;
- if (view->ndim == 0) return 1;
- if (view->strides == NULL) return (view->ndim == 1);
+ /* 1) len = product(shape) * itemsize
+ 2) itemsize > 0
+ 3) len = 0 <==> exists i: shape[i] = 0 */
+ if (view->len == 0) return 1;
+ if (view->strides == NULL) { /* C-contiguous by definition */
+ /* Trivially F-contiguous */
+ if (view->ndim <= 1) return 1;
+
+ /* ndim > 1 implies shape != NULL */
+ assert(view->shape != NULL);
+
+ /* Effectively 1-d */
+ sd = 0;
+ for (i=0; i<view->ndim; i++) {
+ if (view->shape[i] > 1) sd += 1;
+ }
+ return sd <= 1;
+ }
+
+ /* strides != NULL implies both of these */
+ assert(view->ndim > 0);
+ assert(view->shape != NULL);
sd = view->itemsize;
- if (view->ndim == 1) return (view->shape[0] == 1 ||
- sd == view->strides[0]);
for (i=0; i<view->ndim; i++) {
dim = view->shape[i];
- if (dim == 0) return 1;
- if (view->strides[i] != sd) return 0;
+ if (dim > 1 && view->strides[i] != sd) {
+ return 0;
+ }
sd *= dim;
}
return 1;
@@ -388,16 +407,22 @@ _IsCContiguous(const Py_buffer *view)
Py_ssize_t sd, dim;
int i;
- if (view->ndim == 0) return 1;
- if (view->strides == NULL) return 1;
+ /* 1) len = product(shape) * itemsize
+ 2) itemsize > 0
+ 3) len = 0 <==> exists i: shape[i] = 0 */
+ if (view->len == 0) return 1;
+ if (view->strides == NULL) return 1; /* C-contiguous by definition */
+
+ /* strides != NULL implies both of these */
+ assert(view->ndim > 0);
+ assert(view->shape != NULL);
sd = view->itemsize;
- if (view->ndim == 1) return (view->shape[0] == 1 ||
- sd == view->strides[0]);
for (i=view->ndim-1; i>=0; i--) {
dim = view->shape[i];
- if (dim == 0) return 1;
- if (view->strides[i] != sd) return 0;
+ if (dim > 1 && view->strides[i] != sd) {
+ return 0;
+ }
sd *= dim;
}
return 1;