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
Boxiang Sun
cython
Commits
9dc28bd4
Commit
9dc28bd4
authored
Apr 14, 2013
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow arbitrary strides and zero- and one-sized dimensions
parent
65706856
Changes
2
Show 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 @
9dc28bd4
...
@@ -106,10 +106,11 @@ static int __Pyx_init_memviewslice(
...
@@ -106,10 +106,11 @@ static int __Pyx_init_memviewslice(
__Pyx_memviewslice
*
memviewslice
,
__Pyx_memviewslice
*
memviewslice
,
int
memview_is_new_reference
);
int
memview_is_new_reference
);
static
CYTHON_INLINE
int
__pyx_add_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
static
CYTHON_INLINE
int
__pyx_add_acquisition_count_locked
(
PyThread_type_lock
lock
);
__pyx_atomic_int
*
acquisition_count
,
PyThread_type_lock
lock
);
static
CYTHON_INLINE
int
__pyx_sub_acquisition_count_locked
(
__pyx_atomic_int
*
acquisition_count
,
static
CYTHON_INLINE
int
__pyx_sub_acquisition_count_locked
(
PyThread_type_lock
lock
);
__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_pointer(memview) (memview->acquisition_count_aligned_p)
#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
#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__)
#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
...
@@ -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_INC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
static
CYTHON_INLINE
void
__Pyx_XDEC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
static
CYTHON_INLINE
void
__Pyx_XDEC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
/////////////// MemviewSliceIndex.proto ///////////////
/////////////// 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 ///////////////
/////////////// ObjectToMemviewSlice ///////////////
...
@@ -150,101 +152,50 @@ __pyx_fail:
...
@@ -150,101 +152,50 @@ __pyx_fail:
////////// MemviewSliceInit //////////
////////// MemviewSliceInit //////////
static
int
__Pyx_ValidateAndInit_memviewslice
(
static
int
int
*
axes_specs
,
__pyx_check_strides
(
Py_buffer
*
buf
,
int
dim
,
int
ndim
,
int
spec
)
int
c_or_f_flag
,
int
buf_flags
,
int
ndim
,
__Pyx_TypeInfo
*
dtype
,
__Pyx_BufFmt_StackElem
stack
[],
__Pyx_memviewslice
*
memviewslice
,
PyObject
*
original_obj
)
{
{
struct
__pyx_memoryview_obj
*
memview
,
*
new_memview
;
if
(
buf
->
shape
[
dim
]
<=
1
)
__Pyx_RefNannyDeclarations
return
1
;
Py_buffer
*
buf
;
int
i
,
spec
=
0
,
retval
=
-
1
;
__Pyx_BufFmt_Context
ctx
;
int
from_memoryview
=
__pyx_memoryview_check
(
original_obj
);
__Pyx_RefNannySetupContext
(
"ValidateAndInit_memviewslice"
,
0
);
if
(
from_memoryview
&&
__pyx_typeinfo_cmp
(
dtype
,
((
struct
__pyx_memoryview_obj
*
)
original_obj
)
->
typeinfo
))
{
/* We have a matching dtype, skip format parsing */
memview
=
(
struct
__pyx_memoryview_obj
*
)
original_obj
;
new_memview
=
NULL
;
}
else
{
memview
=
(
struct
__pyx_memoryview_obj
*
)
__pyx_memoryview_new
(
original_obj
,
buf_flags
,
0
,
dtype
);
new_memview
=
memview
;
if
(
unlikely
(
!
memview
))
goto
fail
;
}
buf
=
&
memview
->
view
;
if
(
buf
->
ndim
!=
ndim
)
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer has wrong number of dimensions (expected %d, got %d)"
,
ndim
,
buf
->
ndim
);
goto
fail
;
}
if
(
new_memview
)
{
__Pyx_BufFmt_Init
(
&
ctx
,
stack
,
dtype
);
if
(
!
__Pyx_BufFmt_CheckString
(
&
ctx
,
buf
->
format
))
goto
fail
;
}
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)"
,
buf
->
itemsize
,
(
buf
->
itemsize
>
1
)
?
"s"
:
""
,
dtype
->
name
,
dtype
->
size
,
(
dtype
->
size
>
1
)
?
"s"
:
""
);
goto
fail
;
}
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
spec
=
axes_specs
[
i
];
if
(
buf
->
strides
)
{
if
(
buf
->
strides
)
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
)
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
)
{
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
|
__Pyx_MEMVIEW_FULL
))
{
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
|
__Pyx_MEMVIEW_FULL
))
{
if
(
buf
->
strides
[
i
]
!=
sizeof
(
void
*
))
{
if
(
buf
->
strides
[
dim
]
!=
sizeof
(
void
*
))
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly contiguous in dimension %d."
,
i
);
"Buffer is not indirectly contiguous "
"in dimension %d."
,
dim
);
goto
fail
;
goto
fail
;
}
}
}
else
if
(
buf
->
strides
[
i
]
!=
buf
->
itemsize
)
{
}
else
if
(
buf
->
strides
[
dim
]
!=
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous in the same dimension."
);
"Buffer and memoryview are not contiguous "
"in the same dimension."
);
goto
fail
;
goto
fail
;
}
}
}
}
if
(
spec
&
__Pyx_MEMVIEW_FOLLOW
)
{
if
(
spec
&
__Pyx_MEMVIEW_FOLLOW
)
{
Py_ssize_t
stride
=
buf
->
strides
[
i
];
Py_ssize_t
stride
=
buf
->
strides
[
dim
];
if
(
stride
<
0
)
if
(
stride
<
0
)
stride
=
-
stride
;
stride
=
-
stride
;
if
(
stride
<
buf
->
itemsize
)
{
if
(
stride
<
buf
->
itemsize
)
{
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
"Buffer and memoryview are not contiguous in the same dimension."
);
"Buffer and memoryview are not contiguous "
"in the same dimension."
);
goto
fail
;
goto
fail
;
}
}
}
}
}
else
{
}
else
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
&&
i
!=
ndim
-
1
)
{
if
(
spec
&
__Pyx_MEMVIEW_CONTIG
&&
dim
!=
ndim
-
1
)
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not contiguous in "
"C-contiguous buffer is not contiguous in "
"dimension %d"
,
i
);
"dimension %d"
,
dim
);
goto
fail
;
goto
fail
;
}
else
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
))
{
}
else
if
(
spec
&
(
__Pyx_MEMVIEW_PTR
))
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"C-contiguous buffer is not indirect in "
"C-contiguous buffer is not indirect in "
"dimension %d"
,
i
);
"dimension %d"
,
dim
);
goto
fail
;
goto
fail
;
}
else
if
(
buf
->
suboffsets
)
{
}
else
if
(
buf
->
suboffsets
)
{
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
...
@@ -253,30 +204,51 @@ static int __Pyx_ValidateAndInit_memviewslice(
...
@@ -253,30 +204,51 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
}
}
}
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
/* Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
ptr may not be set to NULL but may be uninitialized? */
ptr may not be set to NULL but may be uninitialized? */
if
(
spec
&
__Pyx_MEMVIEW_DIRECT
)
{
if
(
spec
&
__Pyx_MEMVIEW_DIRECT
)
{
if
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
>=
0
)
{
if
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
dim
]
>=
0
)
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"Buffer not compatible with direct access in dimension %d."
,
i
);
"Buffer not compatible with direct access "
"in dimension %d."
,
dim
);
goto
fail
;
goto
fail
;
}
}
}
}
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
!
buf
->
suboffsets
||
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
<
0
))
{
if
(
!
buf
->
suboffsets
||
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
dim
]
<
0
))
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"Buffer is not indirectly accessisble in dimension %d."
,
i
);
"Buffer is not indirectly accessisble "
"in dimension %d."
,
dim
);
goto
fail
;
goto
fail
;
}
}
}
}
}
if
(
buf
->
strides
)
{
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
)
{
if
(
c_or_f_flag
&
__Pyx_IS_F_CONTIG
)
{
Py_ssize_t
stride
=
1
;
Py_ssize_t
stride
=
1
;
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
])
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
]
&&
buf
->
shape
[
i
]
>
1
)
{
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not fortran contiguous."
);
"Buffer not fortran contiguous."
);
goto
fail
;
goto
fail
;
...
@@ -285,8 +257,9 @@ static int __Pyx_ValidateAndInit_memviewslice(
...
@@ -285,8 +257,9 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
}
}
else
if
(
c_or_f_flag
&
__Pyx_IS_C_CONTIG
)
{
}
else
if
(
c_or_f_flag
&
__Pyx_IS_C_CONTIG
)
{
Py_ssize_t
stride
=
1
;
Py_ssize_t
stride
=
1
;
for
(
i
=
ndim
-
1
;
i
>-
1
;
i
--
)
{
for
(
i
=
ndim
-
1
;
i
>-
1
;
i
--
)
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
])
{
if
(
stride
*
buf
->
itemsize
!=
buf
->
strides
[
i
]
&&
buf
->
shape
[
i
]
>
1
)
{
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
"Buffer not C contiguous."
);
"Buffer not C contiguous."
);
goto
fail
;
goto
fail
;
...
@@ -294,8 +267,83 @@ static int __Pyx_ValidateAndInit_memviewslice(
...
@@ -294,8 +267,83 @@ static int __Pyx_ValidateAndInit_memviewslice(
stride
=
stride
*
buf
->
shape
[
i
];
stride
=
stride
*
buf
->
shape
[
i
];
}
}
}
}
return
1
;
fail:
return
0
;
}
static
int
__Pyx_ValidateAndInit_memviewslice
(
int
*
axes_specs
,
int
c_or_f_flag
,
int
buf_flags
,
int
ndim
,
__Pyx_TypeInfo
*
dtype
,
__Pyx_BufFmt_StackElem
stack
[],
__Pyx_memviewslice
*
memviewslice
,
PyObject
*
original_obj
)
{
struct
__pyx_memoryview_obj
*
memview
,
*
new_memview
;
__Pyx_RefNannyDeclarations
Py_buffer
*
buf
;
int
i
,
spec
=
0
,
retval
=
-
1
;
__Pyx_BufFmt_Context
ctx
;
int
from_memoryview
=
__pyx_memoryview_check
(
original_obj
);
__Pyx_RefNannySetupContext
(
"ValidateAndInit_memviewslice"
,
0
);
if
(
from_memoryview
&&
__pyx_typeinfo_cmp
(
dtype
,
((
struct
__pyx_memoryview_obj
*
)
original_obj
)
->
typeinfo
))
{
/* We have a matching dtype, skip format parsing */
memview
=
(
struct
__pyx_memoryview_obj
*
)
original_obj
;
new_memview
=
NULL
;
}
else
{
memview
=
(
struct
__pyx_memoryview_obj
*
)
__pyx_memoryview_new
(
original_obj
,
buf_flags
,
0
,
dtype
);
new_memview
=
memview
;
if
(
unlikely
(
!
memview
))
goto
fail
;
}
buf
=
&
memview
->
view
;
if
(
buf
->
ndim
!=
ndim
)
{
PyErr_Format
(
PyExc_ValueError
,
"Buffer has wrong number of dimensions (expected %d, got %d)"
,
ndim
,
buf
->
ndim
);
goto
fail
;
}
if
(
new_memview
)
{
__Pyx_BufFmt_Init
(
&
ctx
,
stack
,
dtype
);
if
(
!
__Pyx_BufFmt_CheckString
(
&
ctx
,
buf
->
format
))
goto
fail
;
}
}
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)"
,
buf
->
itemsize
,
(
buf
->
itemsize
>
1
)
?
"s"
:
""
,
dtype
->
name
,
dtype
->
size
,
(
dtype
->
size
>
1
)
?
"s"
:
""
);
goto
fail
;
}
/* Check axes */
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
spec
=
axes_specs
[
i
];
if
(
!
__pyx_check_strides
(
buf
,
i
,
ndim
,
spec
))
goto
fail
;
if
(
!
__pyx_check_suboffsets
(
buf
,
i
,
ndim
,
spec
))
goto
fail
;
}
/* 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
,
if
(
unlikely
(
__Pyx_init_memviewslice
(
memview
,
ndim
,
memviewslice
,
new_memview
!=
NULL
)
==
-
1
))
{
new_memview
!=
NULL
)
==
-
1
))
{
goto
fail
;
goto
fail
;
...
...
tests/memoryview/relaxed_strides.pyx
0 → 100644
View file @
9dc28bd4
# 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