Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
7db58754
Commit
7db58754
authored
Apr 14, 2013
by
Mark Florisson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #212 from markflorisson88/master
Relax stride check for zero- and one-sized dimensions
parents
65706856
9dc28bd4
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
188 additions
and
90 deletions
+188
-90
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+138
-90
tests/memoryview/relaxed_strides.pyx
tests/memoryview/relaxed_strides.pyx
+50
-0
No files found.
Cython/Utility/MemoryView_C.c
View file @
7db58754
...
...
@@ -106,10 +106,11 @@ static int __Pyx_init_memviewslice(
__Pyx_memviewslice
*
memviewslice
,
int
memview_is_new_reference
);
static
CYTHON_INLINE
int
__pyx_add_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
PyThread_type_lock
lock
);
static
CYTHON_INLINE
int
__pyx_sub_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
PyThread_type_lock
lock
);
static
CYTHON_INLINE
int
__pyx_add_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
PyThread_type_lock
lock
);
static
CYTHON_INLINE
int
__pyx_sub_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
PyThread_type_lock
lock
);
#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p)
#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
...
...
@@ -117,7 +118,8 @@ static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(__pyx_atomic_int *ac
static
CYTHON_INLINE
void
__Pyx_INC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
static
CYTHON_INLINE
void
__Pyx_XDEC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
/////////////// MemviewSliceIndex.proto ///////////////
static
CYTHON_INLINE
char
*
__pyx_memviewslice_index_full
(
const
char
*
bufp
,
Py_ssize_t
idx
,
Py_ssize_t
stride
,
Py_ssize_t
suboffset
);
static
CYTHON_INLINE
char
*
__pyx_memviewslice_index_full
(
const
char
*
bufp
,
Py_ssize_t
idx
,
Py_ssize_t
stride
,
Py_ssize_t
suboffset
);
/////////////// ObjectToMemviewSlice ///////////////
...
...
@@ -150,6 +152,127 @@ __pyx_fail:
////////// MemviewSliceInit //////////
static
int
__pyx_check_strides
(
Py_buffer
*
buf
,
int
dim
,
int
ndim
,
int
spec
)
{
if
(
buf
->
shape
[
dim
]
<=
1
)
return
1
;
if
(
buf
->
strides
)
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
)
{
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
|
__Pyx_MEMVIEW_FULL
))
{
if
(
buf
->
strides
[
dim
]
!=
sizeof
(
void
*
))
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly contiguous "
"in dimension %d."
,
dim
);
goto
fail
;
}
}
else
if
(
buf
->
strides
[
dim
]
!=
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous "
"in the same dimension."
);
goto
fail
;
}
}
if
(
spec
&
__Pyx_MEMVIEW_FOLLOW
)
{
Py_ssize_t
stride
=
buf
->
strides
[
dim
];
if
(
stride
<
0
)
stride
=
-
stride
;
if
(
stride
<
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous "
"in the same dimension."
);
goto
fail
;
}
}
}
else
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
&&
dim
!=
ndim
-
1
)
{
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not contiguous in "
"dimension %d"
,
dim
);
goto
fail
;
}
else
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
))
{
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not indirect in "
"dimension %d"
,
dim
);
goto
fail
;
}
else
if
(
buf
->
suboffsets
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer exposes suboffsets but no strides"
);
goto
fail
;
}
}
return
1
;
fail:
return
0
;
}
static
int
__pyx_check_suboffsets
(
Py_buffer
*
buf
,
int
dim
,
int
ndim
,
int
spec
)
{
/* Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
ptr may not be set to NULL but may be uninitialized? */
if
(
spec
&
__Pyx_MEMVIEW_DIRECT
)
{
if
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
dim
]
>=
0
)
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer not compatible with direct access "
"in dimension %d."
,
dim
);
goto
fail
;
}
}
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
!
buf
->
suboffsets
||
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
dim
]
<
0
))
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly accessisble "
"in dimension %d."
,
dim
);
goto
fail
;
}
}
return
1
;
fail:
return
0
;
}
static
int
__pyx_verify_contig
(
Py_buffer
*
buf
,
int
ndim
,
int
c_or_f_flag
)
{
int
i
;
if
(
c_or_f_flag
&
__Pyx_IS_F_CONTIG
)
{
Py_ssize_t
stride
=
1
;
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
]
&&
buf
->
shape
[
i
]
>
1
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not fortran contiguous."
);
goto
fail
;
}
stride
=
stride
*
buf
->
shape
[
i
];
}
}
else
if
(
c_or_f_flag
&
__Pyx_IS_C_CONTIG
)
{
Py_ssize_t
stride
=
1
;
for
(
i
=
ndim
-
1
;
i
>-
1
;
i
--
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
]
&&
buf
->
shape
[
i
]
>
1
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not C contiguous."
);
goto
fail
;
}
stride
=
stride
*
buf
->
shape
[
i
];
}
}
return
1
;
fail:
return
0
;
}
static
int
__Pyx_ValidateAndInit_memviewslice
(
int
*
axes_specs
,
int
c_or_f_flag
,
...
...
@@ -195,7 +318,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
if
(
!
__Pyx_BufFmt_CheckString
(
&
ctx
,
buf
->
format
))
goto
fail
;
}
if
((
unsigned
)
buf
->
itemsize
!=
dtype
->
size
)
{
if
((
unsigned
)
buf
->
itemsize
!=
dtype
->
size
)
{
PyErr_Format
(
PyExc_ValueError
,
"Item size of buffer (%"
CYTHON_FORMAT_SSIZE_T
"u byte%s) "
"does not match size of '%s' (%"
CYTHON_FORMAT_SSIZE_T
"u byte%s)"
,
...
...
@@ -207,95 +330,20 @@ static int __Pyx_ValidateAndInit_memviewslice(
goto
fail
;
}
/* Check axes */
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
spec
=
axes_specs
[
i
];
if
(
buf
->
strides
)
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
)
{
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
|
__Pyx_MEMVIEW_FULL
))
{
if
(
buf
->
strides
[
i
]
!=
sizeof
(
void
*
))
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly contiguous in dimension %d."
,
i
);
goto
fail
;
}
}
else
if
(
buf
->
strides
[
i
]
!=
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous in the same dimension."
);
goto
fail
;
}
}
if
(
spec
&
__Pyx_MEMVIEW_FOLLOW
)
{
Py_ssize_t
stride
=
buf
->
strides
[
i
];
if
(
stride
<
0
)
stride
=
-
stride
;
if
(
stride
<
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous in the same dimension."
);
goto
fail
;
}
}
}
else
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
&&
i
!=
ndim
-
1
)
{
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not contiguous in "
"dimension %d"
,
i
);
goto
fail
;
}
else
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
))
{
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not indirect in "
"dimension %d"
,
i
);
goto
fail
;
}
else
if
(
buf
->
suboffsets
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer exposes suboffsets but no strides"
);
goto
fail
;
}
}
/* Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
ptr may not be set to NULL but may be uninitialized? */
if
(
spec
&
__Pyx_MEMVIEW_DIRECT
)
{
if
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
>=
0
)
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer not compatible with direct access in dimension %d."
,
i
);
goto
fail
;
}
}
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
!
buf
->
suboffsets
||
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
<
0
))
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly accessisble in dimension %d."
,
i
);
goto
fail
;
}
}
if
(
!
__pyx_check_strides
(
buf
,
i
,
ndim
,
spec
))
goto
fail
;
if
(
!
__pyx_check_suboffsets
(
buf
,
i
,
ndim
,
spec
))
goto
fail
;
}
if
(
buf
->
strides
)
{
if
(
c_or_f_flag
&
__Pyx_IS_F_CONTIG
)
{
Py_ssize_t
stride
=
1
;
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
])
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not fortran contiguous."
);
goto
fail
;
}
stride
=
stride
*
buf
->
shape
[
i
];
}
}
else
if
(
c_or_f_flag
&
__Pyx_IS_C_CONTIG
)
{
Py_ssize_t
stride
=
1
;
for
(
i
=
ndim
-
1
;
i
>-
1
;
i
--
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
])
{
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not C contiguous."
);
goto
fail
;
}
stride
=
stride
*
buf
->
shape
[
i
];
}
}
}
/* Check contiguity */
if
(
buf
->
strides
&&
!
__pyx_verify_contig
(
buf
,
ndim
,
c_or_f_flag
))
goto
fail
;
/* Initialize */
if
(
unlikely
(
__Pyx_init_memviewslice
(
memview
,
ndim
,
memviewslice
,
new_memview
!=
NULL
)
==
-
1
))
{
goto
fail
;
...
...
tests/memoryview/relaxed_strides.pyx
0 → 100644
View file @
7db58754
# tag: numpy
# mode: run
"""
Test accepting NumPy arrays with arbitrary strides for zero- or one-sized
dimensions.
Thanks to Nathaniel Smith and Sebastian Berg.
See also:
Mailing list threads:
http://thread.gmane.org/gmane.comp.python.cython.devel/14762
http://thread.gmane.org/gmane.comp.python.cython.devel/14634
Detailed discussion of the difference between numpy/cython's current
definition of "contiguity", and the correct definition:
http://thread.gmane.org/gmane.comp.python.cython.devel/14634/focus=14640
The PR implementing NPY_RELAXED_STRIDES_CHECKING:
https://github.com/numpy/numpy/pull/3162
Another test case:
https://github.com/numpy/numpy/issues/2956
"""
import
numpy
as
np
def
test_one_sized
(
array
):
"""
>>> a = np.ascontiguousarray(np.arange(10, dtype=np.double)[::100])
>>> test_one_sized(a)[0]
1.0
>>> a = np.arange(10, dtype=np.double)[::100]
>>> test_one_sized(a)[0]
1.0
"""
cdef
double
[::
1
]
a
=
array
a
[
0
]
+=
1.
return
array
def
test_zero_sized
(
array
):
"""
>>> a = np.ascontiguousarray(np.arange(10, dtype=np.double)[100:200:10])
>>> a = test_zero_sized(a)
>>> a = np.arange(10, dtype=np.double)[100:200:10]
>>> a = test_zero_sized(a)
"""
cdef
double
[::
1
]
a
=
array
return
a
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment