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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
4b9a1ff7
Commit
4b9a1ff7
authored
Dec 23, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor memoryview copying + support overlapping memory
parent
50bd1a47
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
465 additions
and
323 deletions
+465
-323
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+8
-7
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+51
-219
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+23
-37
Cython/Utility/MemoryView.pyx
Cython/Utility/MemoryView.pyx
+226
-0
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+125
-59
tests/run/memoryviewattrs.pyx
tests/run/memoryviewattrs.pyx
+32
-1
No files found.
Cython/Compiler/ExprNodes.py
View file @
4b9a1ff7
...
...
@@ -2954,13 +2954,14 @@ class IndexNode(ExprNode):
self
.
extra_index_params
(),
code
.
error_goto
(
self
.
pos
)))
def
generate_memoryviewslice_copy_code
(
self
,
rhs
,
code
,
op
=
""
):
assert
isinstance
(
self
.
index
,
EllipsisNode
)
def
generate_memoryviewslice_copy_code
(
self
,
rhs
,
code
):
import
MemoryView
util_code
=
MemoryView
.
CopyContentsFuncUtilCode
(
rhs
.
type
,
self
.
type
)
func_name
=
util_code
.
copy_contents_name
code
.
putln
(
code
.
error_goto_if_neg
(
"%s(&%s, &%s)"
%
(
func_name
,
rhs
.
result
(),
self
.
base
.
result
()),
self
.
pos
))
code
.
globalstate
.
use_utility_code
(
util_code
)
code
.
putln
(
code
.
error_goto_if_neg
(
"%s(&%s, &%s, %d)"
%
(
MemoryView
.
copy_src_to_dst_cname
(),
rhs
.
result
(),
self
.
base
.
result
(),
self
.
type
.
ndim
),
self
.
pos
))
def
generate_buffer_setitem_code
(
self
,
rhs
,
code
,
op
=
""
):
# Used from generate_assignment_code and InPlaceAssignmentNode
...
...
@@ -4347,7 +4348,7 @@ class AttributeNode(ExprNode):
self
.
type
=
self
.
obj
.
type
return
else
:
obj_type
.
declare_attribute
(
self
.
attribute
,
env
)
obj_type
.
declare_attribute
(
self
.
attribute
,
env
,
self
.
pos
)
entry
=
obj_type
.
scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
entry
.
is_member
:
entry
=
None
...
...
Cython/Compiler/MemoryView.py
View file @
4b9a1ff7
...
...
@@ -384,235 +384,66 @@ def get_memoryview_flag(access, packing):
assert
(
access
,
packing
)
==
(
'direct'
,
'contig'
),
(
access
,
packing
)
return
'contiguous'
def
get_copy_func_name
(
to_memview
):
base
=
"__Pyx_BufferNew_%s_From_%s"
if
to_memview
.
is_c_contig
:
return
base
%
(
'C'
,
to_memview
.
specialization_suffix
())
def
get_is_contig_func_name
(
c_or_f
,
ndim
):
return
"__pyx_memviewslice_is_%s_contig%d"
%
(
c_or_f
,
ndim
)
def
get_is_contig_utility
(
c_contig
,
ndim
):
C
=
dict
(
context
,
ndim
=
ndim
)
if
c_contig
:
utility
=
load_memview_c_utility
(
"MemviewSliceIsCContig"
,
C
,
requires
=
[
is_contig_utility
])
else
:
return
base
%
(
'F'
,
to_memview
.
specialization_suffix
())
def
get_copy_contents_name
(
from_mvs
,
to_mvs
):
assert
from_mvs
.
dtype
==
to_mvs
.
dtype
return
'__Pyx_BufferCopyContents_%s_to_%s'
%
(
from_mvs
.
specialization_suffix
(),
to_mvs
.
specialization_suffix
())
def
get_is_contig_func_name
(
c_or_f
):
return
"__pyx_memviewslice_is_%s_contig"
%
c_or_f
copy_to_template
=
'''
static int %(copy_to_name)s(const __Pyx_memviewslice from_mvs, __Pyx_memviewslice to_mvs) {
/* ensure from_mvs & to_mvs have the same shape & dtype */
}
'''
class
CopyContentsFuncUtilCode
(
object
):
requires
=
None
def
__init__
(
self
,
from_memview
,
to_memview
):
self
.
from_memview
=
from_memview
self
.
to_memview
=
to_memview
self
.
copy_contents_name
=
get_copy_contents_name
(
from_memview
,
to_memview
)
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
CopyContentsFuncUtilCode
):
return
False
return
other
.
copy_contents_name
==
self
.
copy_contents_name
def
__hash__
(
self
):
return
hash
(
self
.
copy_contents_name
)
def
get_tree
(
self
):
pass
def
put_code
(
self
,
output
):
code
=
output
[
'utility_code_def'
]
proto
=
output
[
'utility_code_proto'
]
func_decl
,
func_impl
=
\
get_copy_contents_func
(
self
.
from_memview
,
self
.
to_memview
,
self
.
copy_contents_name
)
utility
=
load_memview_c_utility
(
"MemviewSliceIsFContig"
,
C
,
requires
=
[
is_contig_utility
])
proto
.
put
(
func_decl
)
code
.
put
(
func_impl
)
return
utility
class
CopyFuncUtilCode
(
object
):
def
copy_src_to_dst_cname
():
return
"__pyx_memoryview_copy_contents"
requires
=
None
def
__init__
(
self
,
from_memview
,
to_memview
):
if
from_memview
.
dtype
!=
to_memview
.
dtype
:
raise
ValueError
(
"dtypes must be the same!"
)
if
len
(
from_memview
.
axes
)
!=
len
(
to_memview
.
axes
):
raise
ValueError
(
"number of dimensions must be same"
)
if
not
(
to_memview
.
is_c_contig
or
to_memview
.
is_f_contig
):
raise
ValueError
(
"to_memview must be c or f contiguous."
)
for
(
access
,
packing
)
in
from_memview
.
axes
:
if
access
!=
'direct'
:
raise
NotImplementedError
(
"cannot handle 'full' or 'ptr' access at this time."
)
self
.
from_memview
=
from_memview
self
.
to_memview
=
to_memview
self
.
copy_func_name
=
get_copy_func_name
(
to_memview
)
self
.
requires
=
[
CopyContentsFuncUtilCode
(
from_memview
,
to_memview
)]
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
CopyFuncUtilCode
):
return
False
return
other
.
copy_func_name
==
self
.
copy_func_name
def
__hash__
(
self
):
return
hash
(
self
.
copy_func_name
)
def
get_tree
(
self
):
pass
def
put_code
(
self
,
output
):
code
=
output
[
'utility_code_def'
]
proto
=
output
[
'utility_code_proto'
]
def
copy_c_or_fortran_cname
(
memview
):
if
memview
.
is_c_contig
:
c_or_f
=
'c'
else
:
c_or_f
=
'f'
proto
.
put
(
Buffer
.
dedent
(
"""
\
static __Pyx_memviewslice %s(const __Pyx_memviewslice from_mvs); /* proto */
"""
%
self
.
copy_func_name
))
return
"__pyx_memoryview_copy_slice_%s_%s"
%
(
memview
.
specialization_suffix
(),
c_or_f
)
copy_contents_name
=
get_copy_contents_name
(
self
.
from_memview
,
self
.
to_memview
)
def
get_copy_new_utility
(
pos
,
from_memview
,
to_memview
):
if
from_memview
.
dtype
!=
to_memview
.
dtype
:
return
error
(
pos
,
"dtypes must be the same!"
)
if
len
(
from_memview
.
axes
)
!=
len
(
to_memview
.
axes
):
return
error
(
pos
,
"number of dimensions must be same"
)
if
not
(
to_memview
.
is_c_contig
or
to_memview
.
is_f_contig
):
return
error
(
pos
,
"to_memview must be c or f contiguous."
)
if
self
.
to_memview
.
is_c_contig
:
mode
=
'c'
contig_flag
=
memview_c_contiguous
elif
self
.
to_memview
.
is_f_contig
:
mode
=
'fortran'
contig_flag
=
memview_f_contiguous
for
(
access
,
packing
)
in
from_memview
.
axes
:
if
access
!=
'direct'
:
return
error
(
pos
,
"cannot handle 'full' or 'ptr' access at this time."
)
C
=
dict
(
if
to_memview
.
is_c_contig
:
mode
=
'c'
contig_flag
=
memview_c_contiguous
elif
to_memview
.
is_f_contig
:
mode
=
'fortran'
contig_flag
=
memview_f_contiguous
return
load_memview_c_utility
(
"CopyContentsUtility"
,
context
=
dict
(
context
,
copy_name
=
self
.
copy_func_name
,
mode
=
mode
,
sizeof_dtype
=
"sizeof(%s)"
%
self
.
from
_memview
.
dtype
.
declaration_code
(
''
),
dtype_decl
=
to
_memview
.
dtype
.
declaration_code
(
''
),
contig_flag
=
contig_flag
,
copy_contents_name
=
copy_contents_name
)
_
,
copy_code
=
TempitaUtilityCode
.
load_as_string
(
"MemviewSliceCopyTemplate"
,
from_file
=
"MemoryView_C.c"
,
context
=
C
)
code
.
put
(
copy_code
)
def
get_copy_contents_func
(
from_mvs
,
to_mvs
,
cfunc_name
):
assert
from_mvs
.
dtype
==
to_mvs
.
dtype
assert
len
(
from_mvs
.
axes
)
==
len
(
to_mvs
.
axes
)
ndim
=
len
(
from_mvs
.
axes
)
# XXX: we only support direct access for now.
for
(
access
,
packing
)
in
from_mvs
.
axes
:
if
access
!=
'direct'
:
raise
NotImplementedError
(
"currently only direct access is supported."
)
code_decl
=
(
"static int %(cfunc_name)s(const __Pyx_memviewslice *from_mvs,"
"__Pyx_memviewslice *to_mvs); /* proto */"
%
{
'cfunc_name'
:
cfunc_name
})
code_impl
=
'''
static int %(cfunc_name)s(const __Pyx_memviewslice *from_mvs, __Pyx_memviewslice *to_mvs) {
char *to_buf = (char *)to_mvs->data;
char *from_buf = (char *)from_mvs->data;
struct __pyx_memoryview_obj *temp_memview = 0;
char *temp_data = 0;
int ndim_idx = 0;
for(ndim_idx=0; ndim_idx<%(ndim)d; ndim_idx++) {
if(from_mvs->shape[ndim_idx] != to_mvs->shape[ndim_idx]) {
PyErr_Format(PyExc_ValueError,
"memoryview shapes not the same in dimension %%d", ndim_idx);
return -1;
}
}
'''
%
{
'cfunc_name'
:
cfunc_name
,
'ndim'
:
ndim
}
# raise NotImplementedError("put in shape checking code here!!!")
INDENT
=
" "
dtype_decl
=
from_mvs
.
dtype
.
declaration_code
(
""
)
last_idx
=
ndim
-
1
if
to_mvs
.
is_c_contig
or
to_mvs
.
is_f_contig
:
if
to_mvs
.
is_c_contig
:
start
,
stop
,
step
=
0
,
ndim
,
1
elif
to_mvs
.
is_f_contig
:
start
,
stop
,
step
=
ndim
-
1
,
-
1
,
-
1
for
i
,
idx
in
enumerate
(
range
(
start
,
stop
,
step
)):
# the crazy indexing is to account for the fortran indexing.
# 'i' always goes up from zero to ndim-1.
# 'idx' is the same as 'i' for c_contig, and goes from ndim-1 to 0 for f_contig.
# this makes the loop code below identical in both cases.
code_impl
+=
INDENT
+
"Py_ssize_t i%d = 0, idx%d = 0;
\
n
"
%
(
i
,
i
)
code_impl
+=
INDENT
+
"Py_ssize_t stride%(i)d = from_mvs->strides[%(idx)d];
\
n
"
%
{
'i'
:
i
,
'idx'
:
idx
}
code_impl
+=
INDENT
+
"Py_ssize_t shape%(i)d = from_mvs->shape[%(idx)d];
\
n
"
%
{
'i'
:
i
,
'idx'
:
idx
}
code_impl
+=
"
\
n
"
# put down the nested for-loop.
for
k
in
range
(
ndim
):
code_impl
+=
INDENT
*
(
k
+
1
)
+
"for(i%(k)d=0; i%(k)d<shape%(k)d; i%(k)d++) {
\
n
"
%
{
'k'
:
k
}
if
k
>=
1
:
code_impl
+=
INDENT
*
(
k
+
2
)
+
"idx%(k)d = i%(k)d * stride%(k)d + idx%(km1)d;
\
n
"
%
{
'k'
:
k
,
'km1'
:
k
-
1
}
else
:
code_impl
+=
INDENT
*
(
k
+
2
)
+
"idx%(k)d = i%(k)d * stride%(k)d;
\
n
"
%
{
'k'
:
k
}
# the inner part of the loop.
code_impl
+=
INDENT
*
(
ndim
+
1
)
+
"memcpy(to_buf, from_buf+idx%(last_idx)d, sizeof(%(dtype_decl)s));
\
n
"
%
locals
()
code_impl
+=
INDENT
*
(
ndim
+
1
)
+
"to_buf += sizeof(%(dtype_decl)s);
\
n
"
%
locals
()
else
:
code_impl
+=
INDENT
+
"/* 'f' prefix is for the 'from' memview, 't' prefix is for the 'to' memview */
\
n
"
for
i
in
range
(
ndim
):
code_impl
+=
INDENT
+
"char *fi%d = 0, *ti%d = 0, *end%d = 0;
\
n
"
%
(
i
,
i
,
i
)
code_impl
+=
INDENT
+
"Py_ssize_t fstride%(i)d = from_mvs->strides[%(i)d];
\
n
"
%
{
'i'
:
i
}
code_impl
+=
INDENT
+
"Py_ssize_t fshape%(i)d = from_mvs->shape[%(i)d];
\
n
"
%
{
'i'
:
i
}
code_impl
+=
INDENT
+
"Py_ssize_t tstride%(i)d = to_mvs->strides[%(i)d];
\
n
"
%
{
'i'
:
i
}
# code_impl += INDENT+"Py_ssize_t tshape%(i)d = to_mvs->shape[%(i)d];\n" % {'i':i}
code_impl
+=
INDENT
+
"end0 = fshape0 * fstride0 + from_mvs->data;
\
n
"
code_impl
+=
INDENT
+
"for(fi0=from_buf, ti0=to_buf; fi0 < end0; fi0 += fstride0, ti0 += tstride0) {
\
n
"
for
i
in
range
(
1
,
ndim
):
code_impl
+=
INDENT
*
(
i
+
1
)
+
"end%(i)d = fshape%(i)d * fstride%(i)d + fi%(im1)d;
\
n
"
%
{
'i'
:
i
,
'im1'
:
i
-
1
}
code_impl
+=
INDENT
*
(
i
+
1
)
+
"for(fi%(i)d=fi%(im1)d, ti%(i)d=ti%(im1)d; fi%(i)d < end%(i)d; fi%(i)d += fstride%(i)d, ti%(i)d += tstride%(i)d) {
\
n
"
%
{
'i'
:
i
,
'im1'
:
i
-
1
}
code_impl
+=
INDENT
*
(
ndim
+
1
)
+
"*(%(dtype_decl)s*)(ti%(last_idx)d) = *(%(dtype_decl)s*)(fi%(last_idx)d);
\
n
"
%
locals
()
# for-loop closing braces
for
k
in
range
(
ndim
-
1
,
-
1
,
-
1
):
code_impl
+=
INDENT
*
(
k
+
1
)
+
"}
\
n
"
# init to_mvs->data and to_mvs shape/strides/suboffsets arrays.
code_impl
+=
INDENT
+
"temp_memview = to_mvs->memview;
\
n
"
code_impl
+=
INDENT
+
"temp_data = to_mvs->data;
\
n
"
code_impl
+=
INDENT
+
"to_mvs->memview = 0; to_mvs->data = 0;
\
n
"
code_impl
+=
INDENT
+
"if(unlikely(-1 == __Pyx_init_memviewslice(temp_memview, %d, to_mvs))) {
\
n
"
%
(
ndim
,)
code_impl
+=
INDENT
*
2
+
"return -1;
\
n
"
code_impl
+=
INDENT
+
"}
\
n
"
code_impl
+=
INDENT
+
"return 0;
\
n
"
code_impl
+=
'}
\
n
'
return
code_decl
,
code_impl
ndim
=
to_memview
.
ndim
,
func_cname
=
copy_c_or_fortran_cname
(
to_memview
)),
requires
=
[
copy_contents_new_utility
])
def
get_axes_specs
(
env
,
axes
):
'''
get_axes_specs(env, axes) -> list of (access, packing) specs for each axis.
access is one of 'full', 'ptr' or 'direct'
packing is one of 'contig', 'strided' or 'follow'
'''
...
...
@@ -905,10 +736,8 @@ typeinfo_to_format_code = load_memview_cy_utility(
"BufferFormatFromTypeInfo"
,
requires
=
[
Buffer
.
_typeinfo_to_format_code
])
is_contig_utility
=
load_memview_c_utility
(
"MemviewSliceIsContig"
,
context
)
is_c_contig_utility
=
load_memview_c_utility
(
"MemviewSliceIsCContig"
,
context
,
requires
=
[
is_contig_utility
])
is_f_contig_utility
=
load_memview_c_utility
(
"MemviewSliceIsFContig"
,
context
,
requires
=
[
is_contig_utility
])
overlapping_utility
=
load_memview_c_utility
(
"OverlappingSlices"
,
context
)
copy_contents_new_utility
=
load_memview_c_utility
(
"MemviewSliceCopyTemplate"
,
context
)
view_utility_code
=
load_memview_cy_utility
(
"View.MemoryView"
,
...
...
@@ -916,7 +745,10 @@ view_utility_code = load_memview_cy_utility(
requires
=
[
Buffer
.
GetAndReleaseBufferUtilityCode
(),
Buffer
.
buffer_struct_declare_code
,
Buffer
.
empty_bufstruct_utility
,
memviewslice_init_code
],
memviewslice_init_code
,
is_contig_utility
,
overlapping_utility
,
copy_contents_new_utility
],
)
cython_array_utility_code
=
load_memview_cy_utility
(
...
...
Cython/Compiler/PyrexTypes.py
View file @
4b9a1ff7
...
...
@@ -510,7 +510,7 @@ class MemoryViewSliceType(PyrexType):
return
True
def
declare_attribute
(
self
,
attribute
,
env
):
def
declare_attribute
(
self
,
attribute
,
env
,
pos
):
import
MemoryView
,
Options
scope
=
self
.
scope
...
...
@@ -518,24 +518,24 @@ class MemoryViewSliceType(PyrexType):
if
attribute
==
'shape'
:
scope
.
declare_var
(
'shape'
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
None
,
Options
.
buffer_max_dims
),
pos
,
cname
=
'shape'
,
is_cdef
=
1
)
elif
attribute
==
'strides'
:
scope
.
declare_var
(
'strides'
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
None
,
Options
.
buffer_max_dims
),
pos
,
cname
=
'strides'
,
is_cdef
=
1
)
elif
attribute
==
'suboffsets'
:
scope
.
declare_var
(
'suboffsets'
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
None
,
Options
.
buffer_max_dims
),
pos
,
cname
=
'suboffsets'
,
is_cdef
=
1
)
...
...
@@ -544,40 +544,32 @@ class MemoryViewSliceType(PyrexType):
to_axes_c
=
[(
'direct'
,
'contig'
)]
to_axes_f
=
[(
'direct'
,
'contig'
)]
if
ndim
-
1
:
if
ndim
-
1
:
to_axes_c
=
[(
'direct'
,
'follow'
)]
*
(
ndim
-
1
)
+
to_axes_c
to_axes_f
=
to_axes_f
+
[(
'direct'
,
'follow'
)]
*
(
ndim
-
1
)
to_memview_c
=
MemoryViewSliceType
(
self
.
dtype
,
to_axes_c
)
to_memview_f
=
MemoryViewSliceType
(
self
.
dtype
,
to_axes_f
)
cython_name_c
,
cython_name_f
=
"copy"
,
"copy_fortran"
copy_name_c
,
copy_name_f
=
(
MemoryView
.
get_copy_func_name
(
to_memview_c
),
MemoryView
.
get_copy_func_name
(
to_memview_f
))
for
(
to_memview
,
cython_name
,
copy_name
)
in
((
to_memview_c
,
cython_name_c
,
copy_name_c
),
(
to_memview_f
,
cython_name_f
,
copy_name_f
)):
for
to_memview
,
cython_name
in
[(
to_memview_c
,
"copy"
),
(
to_memview_f
,
"copy_fortran"
)]:
entry
=
scope
.
declare_cfunction
(
cython_name
,
CFuncType
(
self
,
[
CFuncTypeArg
(
"memviewslice"
,
self
,
None
)]),
pos
=
None
,
defining
=
1
,
cname
=
copy_name
)
CFuncType
(
self
,
[
CFuncTypeArg
(
"memviewslice"
,
self
,
None
)]),
pos
=
pos
,
defining
=
1
,
cname
=
MemoryView
.
copy_c_or_fortran_cname
(
to_memview
))
entry
.
utility_code_definition
=
\
MemoryView
.
CopyFuncUtilCode
(
self
,
to_memview
)
#
entry.utility_code_definition = \
env
.
use_utility_code
(
MemoryView
.
get_copy_new_utility
(
pos
,
self
,
to_memview
)
)
MemoryView
.
use_cython_array_utility_code
(
env
)
elif
attribute
in
(
"is_c_contig"
,
"is_f_contig"
):
# is_c_contig and is_f_contig functions
for
(
c_or_f
,
cython_name
)
in
((
'c'
,
'is_c_contig'
),
(
'f
ortran
'
,
'is_f_contig'
)):
for
(
c_or_f
,
cython_name
)
in
((
'c'
,
'is_c_contig'
),
(
'f'
,
'is_f_contig'
)):
is_contig_name
=
\
MemoryView
.
get_is_contig_func_name
(
c_or_f
)
MemoryView
.
get_is_contig_func_name
(
c_or_f
,
self
.
ndim
)
cfunctype
=
CFuncType
(
return_type
=
c_int_type
,
...
...
@@ -587,14 +579,12 @@ class MemoryViewSliceType(PyrexType):
entry
=
scope
.
declare_cfunction
(
cython_name
,
cfunctype
,
pos
=
None
,
defining
=
1
,
cname
=
is_contig_name
)
pos
=
pos
,
defining
=
1
,
cname
=
is_contig_name
)
if
attribute
==
'is_c_contig'
:
entry
.
utility_code_definition
=
MemoryView
.
is_c_contig_utility
else
:
entry
.
utility_code_definition
=
MemoryView
.
is_f_contig_utility
entry
.
utility_code_definition
=
MemoryView
.
get_is_contig_utility
(
attribute
==
'is_c_contig'
,
self
.
ndim
)
return
True
...
...
@@ -604,10 +594,6 @@ class MemoryViewSliceType(PyrexType):
def
can_coerce_to_pyobject
(
self
,
env
):
return
True
#def global_init_code(self, entry, code):
# code.putln("%s.data = NULL;" % entry.cname)
# code.putln("%s.memview = NULL;" % entry.cname)
def
check_for_null_code
(
self
,
cname
):
return
cname
+
'.memview'
...
...
Cython/Utility/MemoryView.pyx
View file @
4b9a1ff7
...
...
@@ -237,6 +237,11 @@ cdef extern from *:
PyBUF_STRIDES
PyBUF_INDIRECT
cdef
extern
from
"stdlib.h"
:
void
*
malloc
(
size_t
)
nogil
void
free
(
void
*
)
nogil
void
*
memcpy
(
void
*
dest
,
void
*
src
,
size_t
n
)
nogil
@
cname
(
'__pyx_MemviewEnum'
)
cdef
class
Enum
(
object
):
cdef
object
name
...
...
@@ -891,6 +896,7 @@ cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst):
@
cname
(
'__pyx_memoryview_copy'
)
cdef
memoryview_copy
(
memoryview
memview
):
"Create a new memoryview object"
cdef
{{
memviewslice_name
}}
memviewslice
cdef
object
(
*
to_object_func
)(
char
*
)
cdef
int
(
*
to_dtype_func
)(
char
*
,
object
)
except
0
...
...
@@ -907,6 +913,226 @@ cdef memoryview_copy(memoryview memview):
return
memoryview_fromslice
(
&
memviewslice
,
memview
.
view
.
ndim
,
to_object_func
,
to_dtype_func
)
#
### Copy the contents of a memoryview slices
#
cdef
extern
from
*
:
int
slice_is_contig
"__pyx_memviewslice_is_contig"
(
{{
memviewslice_name
}}
*
mvs
,
char
order
,
int
ndim
)
nogil
int
slices_overlap
"__pyx_slices_overlap"
({{
memviewslice_name
}}
*
slice1
,
{{
memviewslice_name
}}
*
slice2
,
int
ndim
,
size_t
itemsize
)
nogil
cdef
Py_ssize_t
abs_py_ssize_t
(
Py_ssize_t
arg
)
nogil
:
if
arg
<
0
:
return
-
arg
else
:
return
arg
@
cname
(
'__pyx_get_best_slice_order'
)
cdef
char
get_best_order
({{
memviewslice_name
}}
*
mslice
,
int
ndim
)
nogil
:
"""
Figure out the best memory access order for a given slice.
"""
cdef
int
i
cdef
Py_ssize_t
c_stride
=
0
cdef
Py_ssize_t
f_stride
=
0
for
i
in
range
(
ndim
-
1
,
-
1
,
-
1
):
if
mslice
.
shape
[
i
]
>
1
:
c_stride
=
mslice
.
strides
[
i
]
for
i
in
range
(
ndim
):
if
mslice
.
shape
[
i
]
>
1
:
f_stride
=
mslice
.
strides
[
i
]
if
abs_py_ssize_t
(
c_stride
)
<=
abs_py_ssize_t
(
f_stride
):
return
'C'
else
:
return
'F'
cdef
void
_copy_strided_to_strided
(
char
*
src_data
,
Py_ssize_t
*
strides1
,
char
*
dst_data
,
Py_ssize_t
*
strides2
,
Py_ssize_t
*
shape
,
int
ndim
,
size_t
itemsize
)
nogil
:
cdef
Py_ssize_t
i
,
extent
,
stride1
,
stride2
extent
=
shape
[
0
]
stride1
=
strides1
[
0
]
stride2
=
strides2
[
0
]
if
ndim
==
1
:
if
stride1
>
0
and
stride2
>
0
and
<
size_t
>
stride1
==
itemsize
==
<
size_t
>
stride2
:
memcpy
(
dst_data
,
src_data
,
itemsize
*
extent
)
else
:
for
i
in
range
(
extent
):
memcpy
(
dst_data
,
src_data
,
itemsize
)
src_data
+=
stride1
dst_data
+=
stride2
else
:
for
i
in
range
(
extent
):
_copy_strided_to_strided
(
src_data
,
strides1
+
1
,
dst_data
,
strides2
+
1
,
shape
+
1
,
ndim
-
1
,
itemsize
)
src_data
+=
stride1
dst_data
+=
stride2
cdef
void
copy_strided_to_strided
({{
memviewslice_name
}}
*
src
,
{{
memviewslice_name
}}
*
dst
,
int
ndim
,
size_t
itemsize
)
nogil
:
_copy_strided_to_strided
(
src
.
data
,
src
.
strides
,
dst
.
data
,
dst
.
strides
,
src
.
shape
,
ndim
,
itemsize
)
{{
for
strided_to_contig
in
(
True
,
False
)}}
{{
if
strided_to_contig
}}
{{
py
:
func_name
=
"copy_strided_to_contig"
}}
{{
else
}}
{{
py
:
func_name
=
"copy_contig_to_strided"
}}
{{
endif
}}
@
cname
(
'__pyx_{{func_name}}'
)
cdef
char
*
{{
func_name
}}(
char
*
strided
,
char
*
contig
,
Py_ssize_t
*
shape
,
Py_ssize_t
*
strides
,
int
ndim
,
size_t
itemsize
)
nogil
:
"""
Copy contiguous data to strided memory, or strided memory to contiguous data.
The shape and strides are given only for the strided data.
"""
cdef
Py_ssize_t
i
,
extent
,
stride
cdef
void
*
src
,
*
dst
stride
=
strides
[
0
]
extent
=
shape
[
0
]
{{
if
strided_to_contig
}}
src
=
strided
dst
=
contig
{{
else
}}
src
=
contig
dst
=
strided
{{
endif
}}
if
ndim
==
1
:
# inner dimension, copy data
if
stride
>
0
and
<
size_t
>
stride
==
itemsize
:
memcpy
(
dst
,
src
,
itemsize
*
extent
)
contig
+=
itemsize
*
extent
else
:
for
i
in
range
(
extent
):
{{
if
strided_to_contig
}}
memcpy
(
contig
,
strided
,
itemsize
)
{{
else
}}
memcpy
(
strided
,
contig
,
itemsize
)
{{
endif
}}
contig
+=
itemsize
strided
+=
stride
else
:
for
i
in
range
(
extent
):
contig
=
{{
func_name
}}(
strided
,
contig
,
shape
+
1
,
strides
+
1
,
ndim
-
1
,
itemsize
)
strided
+=
stride
return
contig
{{
endfor
}}
@
cname
(
'__pyx_memoryview_slice_get_size'
)
cdef
Py_ssize_t
slice_get_size
({{
memviewslice_name
}}
*
src
,
int
ndim
)
nogil
:
"Return the size of the memory occupied by the slice in number of bytes"
cdef
int
i
cdef
Py_ssize_t
size
=
src
.
memview
.
view
.
itemsize
for
i
in
range
(
ndim
):
size
*=
src
.
shape
[
i
]
return
size
@
cname
(
'__pyx_memoryview_copy_data_to_temp'
)
cdef
void
*
copy_data_to_temp
({{
memviewslice_name
}}
*
src
,
char
order
,
int
ndim
)
nogil
except
NULL
:
"""
Copy a direct slice to temporary contiguous memory. The caller should free
the result when done.
"""
cdef
int
i
cdef
void
*
result
cdef
size_t
itemsize
=
src
.
memview
.
view
.
itemsize
cdef
size_t
size
=
slice_get_size
(
src
,
ndim
)
result
=
malloc
(
size
)
if
not
result
:
with
gil
:
raise
MemoryError
if
slice_is_contig
(
src
,
order
,
ndim
):
memcpy
(
result
,
src
.
data
,
size
)
else
:
copy_strided_to_contig
(
src
.
data
,
<
char
*>
result
,
src
.
shape
,
src
.
strides
,
ndim
,
itemsize
)
return
result
@
cname
(
'__pyx_memoryview_copy_contents'
)
cdef
int
memoryview_copy_contents
({{
memviewslice_name
}}
*
src
,
{{
memviewslice_name
}}
*
dst
,
int
ndim
)
nogil
except
-
1
:
"""
Copy memory from slice src to slice dst.
Check for overlapping memory and verify the shapes.
This function DOES NOT verify ndim and itemsize (either the compiler
or the caller should do that)
"""
cdef
void
*
tmpdata
cdef
size_t
itemsize
=
src
.
memview
.
view
.
itemsize
cdef
int
i
,
direct_copy
cdef
char
order
=
get_best_order
(
src
,
ndim
)
cdef
{{
memviewslice_name
}}
src_copy
,
dst_copy
for
i
in
range
(
ndim
):
if
src
.
shape
[
i
]
!=
dst
.
shape
[
i
]:
with
gil
:
raise
ValueError
(
"memoryview shapes are not the same in dimension %d, "
"got %d and %d"
%
(
i
,
src
.
shape
[
i
],
dst
.
shape
[
i
]))
if
slices_overlap
(
src
,
dst
,
ndim
,
itemsize
):
# slices overlap, copy to temp, copy temp to dst
if
not
slice_is_contig
(
src
,
order
,
ndim
):
order
=
get_best_order
(
dst
,
ndim
)
tmpdata
=
copy_data_to_temp
(
src
,
order
,
ndim
)
copy_contig_to_strided
(
dst
.
data
,
<
char
*>
tmpdata
,
dst
.
shape
,
dst
.
strides
,
ndim
,
itemsize
)
free
(
tmpdata
)
return
0
# See if both slices have equal contiguity
if
slice_is_contig
(
src
,
'C'
,
ndim
):
direct_copy
=
slice_is_contig
(
dst
,
'C'
,
ndim
)
elif
slice_is_contig
(
src
,
'F'
,
ndim
):
direct_copy
=
slice_is_contig
(
dst
,
'F'
,
ndim
)
else
:
direct_copy
=
False
if
direct_copy
:
# Contiguous slices with same order
memcpy
(
dst
.
data
,
src
.
data
,
slice_get_size
(
src
,
ndim
))
return
0
# Slices are not overlapping and not contiguous
if
order
==
'F'
==
get_best_order
(
dst
,
ndim
):
# see if both slices have Fortran order, transpose them to match our
# C-style indexing order
if
src
!=
&
src_copy
:
src_copy
=
src
[
0
]
src
=
&
src_copy
if
dst
!=
&
dst_copy
:
dst_copy
=
dst
[
0
]
dst
=
&
dst_copy
transpose_memslice
(
src
)
transpose_memslice
(
dst
)
copy_strided_to_strided
(
src
,
dst
,
ndim
,
itemsize
)
return
0
############### BufferFormatFromTypeInfo ###############
cdef
extern
from
*
:
ctypedef
struct
__Pyx_StructField
...
...
Cython/Utility/MemoryView_C.c
View file @
4b9a1ff7
...
...
@@ -37,7 +37,8 @@ static int __Pyx_init_memviewslice(
int
ndim
,
__Pyx_memviewslice
*
memviewslice
);
static
int
CYTHON_INLINE
__pyx_add_acquisition_count
(
struct
{{
memview_struct_name
}}
*
memview
);
static
int
CYTHON_INLINE
__pyx_del_acquisition_count
(
struct
{{
memview_struct_name
}}
*
memview
);
#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__)
static
CYTHON_INLINE
void
__Pyx_INC_MEMVIEW
({{
memviewslice_name
}}
*
,
int
,
int
);
...
...
@@ -210,11 +211,11 @@ no_fail:
return
retval
;
}
static
int
__Pyx_init_memviewslice
(
struct
__pyx_memoryview_obj
*
memview
,
int
ndim
,
__Pyx_memviewslice
*
memviewslice
)
{
static
int
__Pyx_init_memviewslice
(
struct
__pyx_memoryview_obj
*
memview
,
int
ndim
,
{{
memviewslice_name
}}
*
memviewslice
)
{
__Pyx_RefNannyDeclarations
int
i
,
retval
=-
1
;
Py_buffer
*
buf
=
&
memview
->
view
;
...
...
@@ -242,7 +243,7 @@ static int __Pyx_init_memviewslice(
memviewslice
->
memview
=
memview
;
memviewslice
->
data
=
(
char
*
)
buf
->
buf
;
memview
->
acquisition_count
++
;
__pyx_add_acquisition_count
(
memview
)
;
retval
=
0
;
goto
no_fail
;
...
...
@@ -275,6 +276,27 @@ static CYTHON_INLINE void __pyx_fatalerror(const char *fmt, ...) {
va_end
(
vargs
);
}
static
int
CYTHON_INLINE
__pyx_add_acquisition_count
(
struct
{{
memview_struct_name
}}
*
memview
)
{
int
result
;
PyThread_acquire_lock
(
memview
->
lock
,
1
);
result
=
memview
->
acquisition_count
++
;
PyThread_release_lock
(
memview
->
lock
);
return
result
;
}
static
int
CYTHON_INLINE
__pyx_del_acquisition_count
(
struct
{{
memview_struct_name
}}
*
memview
)
{
int
result
;
PyThread_acquire_lock
(
memview
->
lock
,
1
);
result
=
memview
->
acquisition_count
--
;
PyThread_release_lock
(
memview
->
lock
);
return
result
;
}
static
CYTHON_INLINE
void
__Pyx_INC_MEMVIEW
({{
memviewslice_name
}}
*
memslice
,
int
have_gil
,
int
lineno
)
{
int
first_time
;
...
...
@@ -286,9 +308,7 @@ static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice,
__pyx_fatalerror
(
"Acquisition count is %d (line %d)"
,
memview
->
acquisition_count
,
lineno
);
PyThread_acquire_lock
(
memview
->
lock
,
1
);
first_time
=
(
memview
->
acquisition_count
++
==
0
);
PyThread_release_lock
(
memview
->
lock
);
first_time
=
__pyx_add_acquisition_count
(
memview
)
==
0
;
if
(
first_time
)
{
if
(
have_gil
)
{
...
...
@@ -313,10 +333,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
__pyx_fatalerror
(
"Acquisition count is %d (line %d)"
,
memview
->
acquisition_count
,
lineno
);
PyThread_acquire_lock
(
memview
->
lock
,
1
);
last_time
=
(
memview
->
acquisition_count
--
==
1
);
PyThread_release_lock
(
memview
->
lock
);
last_time
=
__pyx_del_acquisition_count
(
memview
)
==
1
;
memslice
->
data
=
NULL
;
if
(
last_time
)
{
if
(
have_gil
)
{
...
...
@@ -331,32 +348,39 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
}
}
////////// MemviewSliceCopyTemplate //////////
static
__Pyx_memviewslice
{{
copy_name
}}(
const
__Pyx_memviewslice
from_mvs
)
{
////////// MemviewSliceCopyTemplate.proto //////////
static
{{
memviewslice_name
}}
__pyx_memoryview_copy_new_contig
(
const
__Pyx_memviewslice
*
from_mvs
,
const
char
*
mode
,
int
ndim
,
size_t
sizeof_dtype
,
int
contig_flag
);
////////// MemviewSliceCopyTemplate //////////
static
{{
memviewslice_name
}}
__pyx_memoryview_copy_new_contig
(
const
__Pyx_memviewslice
*
from_mvs
,
const
char
*
mode
,
int
ndim
,
size_t
sizeof_dtype
,
int
contig_flag
)
{
__Pyx_RefNannyDeclarations
int
i
;
__Pyx_memviewslice
new_mvs
=
{{
memslice_init
}};
struct
__pyx_memoryview_obj
*
from_memview
=
from_mvs
.
memview
;
struct
__pyx_memoryview_obj
*
from_memview
=
from_mvs
->
memview
;
Py_buffer
*
buf
=
&
from_memview
->
view
;
PyObject
*
shape_tuple
=
0
;
PyObject
*
temp_int
=
0
;
struct
__pyx_array_obj
*
array_obj
=
0
;
struct
__pyx_memoryview_obj
*
memview_obj
=
0
;
char
*
mode
=
(
char
*
)
"{{mode}}"
;
PyObject
*
shape_tuple
=
NULL
;
PyObject
*
temp_int
=
NULL
;
struct
__pyx_array_obj
*
array_obj
=
NULL
;
struct
__pyx_memoryview_obj
*
memview_obj
=
NULL
;
__Pyx_RefNannySetupContext
(
"
{{copy_name}}
"
);
__Pyx_RefNannySetupContext
(
"
__pyx_memoryview_copy_new_contig
"
);
shape_tuple
=
PyTuple_New
(
(
Py_ssize_t
)(
buf
->
ndim
)
);
shape_tuple
=
PyTuple_New
(
ndim
);
if
(
unlikely
(
!
shape_tuple
))
{
goto
fail
;
}
__Pyx_GOTREF
(
shape_tuple
);
for
(
i
=
0
;
i
<
buf
->
ndim
;
i
++
)
{
temp_int
=
PyInt_FromLong
(
buf
->
shape
[
i
]);
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
temp_int
=
PyInt_FromLong
(
from_mvs
->
shape
[
i
]);
if
(
unlikely
(
!
temp_int
))
{
goto
fail
;
}
else
{
...
...
@@ -364,36 +388,31 @@ static __Pyx_memviewslice {{copy_name}}(const __Pyx_memviewslice from_mvs) {
}
}
array_obj
=
__pyx_array_new
(
shape_tuple
,
{{
sizeof_dtype
}},
buf
->
format
,
mode
,
NULL
);
array_obj
=
__pyx_array_new
(
shape_tuple
,
sizeof_dtype
,
buf
->
format
,
(
char
*
)
mode
,
NULL
);
if
(
unlikely
(
!
array_obj
))
{
goto
fail
;
}
__Pyx_GOTREF
(
array_obj
);
memview_obj
=
(
struct
__pyx_memoryview_obj
*
)
__pyx_memoryview_new
(
(
PyObject
*
)
array_obj
,
{{
contig_flag
}}
);
if
(
unlikely
(
!
memview_obj
))
{
(
PyObject
*
)
array_obj
,
contig_flag
);
if
(
unlikely
(
!
memview_obj
))
goto
fail
;
}
/* initialize new_mvs */
if
(
unlikely
(
-
1
==
__Pyx_init_memviewslice
(
memview_obj
,
buf
->
ndim
,
&
new_mvs
)))
{
PyErr_SetString
(
PyExc_RuntimeError
,
"Could not initialize new memoryviewslice object."
);
if
(
unlikely
(
__Pyx_init_memviewslice
(
memview_obj
,
ndim
,
&
new_mvs
)
<
0
))
goto
fail
;
}
if
(
unlikely
(
-
1
==
{{
copy_contents_name
}}(
&
from_mvs
,
&
new_mvs
)))
{
/* PyErr_SetString(PyExc_RuntimeError,
"Could not copy contents of memoryview slice."); */
if
(
unlikely
(
__pyx_memoryview_copy_contents
(
({{
memviewslice_name
}}
*
)
from_mvs
,
&
new_mvs
,
ndim
)
<
0
))
goto
fail
;
}
goto
no_fail
;
fail:
__Pyx_XDECREF
(
new_mvs
.
memview
);
new_mvs
.
memview
=
0
;
new_mvs
.
data
=
0
;
__Pyx_XDECREF
(
new_mvs
.
memview
);
new_mvs
.
memview
=
NULL
;
new_mvs
.
data
=
NULL
;
no_fail:
__Pyx_XDECREF
(
shape_tuple
);
shape_tuple
=
0
;
__Pyx_GOTREF
(
temp_int
);
...
...
@@ -401,27 +420,84 @@ no_fail:
__Pyx_XDECREF
(
array_obj
);
array_obj
=
0
;
__Pyx_RefNannyFinishContext
();
return
new_mvs
;
}
////////// CopyContentsUtility.proto /////////
#define {{func_cname}}(slice) \
__pyx_memoryview_copy_new_contig(&slice, "{{mode}}", {{ndim}}, \
sizeof({{dtype_decl}}), {{contig_flag}})
////////// OverlappingSlices.proto //////////
static
int
__pyx_slices_overlap
({{
memviewslice_name
}}
*
slice1
,
{{
memviewslice_name
}}
*
slice2
,
int
ndim
,
size_t
itemsize
);
////////// OverlappingSlices //////////
/* Based on numpy's core/src/multiarray/array_assign.c */
/* Gets a half-open range [start, end) which contains the array data */
static
void
__pyx_get_array_memory_extents
({{
memviewslice_name
}}
*
slice
,
void
**
out_start
,
void
**
out_end
,
int
ndim
,
size_t
itemsize
)
{
char
*
start
,
*
end
;
int
i
;
start
=
end
=
slice
->
data
;
for
(
i
=
0
;
i
<
ndim
;
i
++
)
{
Py_ssize_t
stride
=
slice
->
strides
[
i
];
Py_ssize_t
extent
=
slice
->
shape
[
i
];
if
(
extent
==
0
)
{
*
out_start
=
*
out_end
=
start
;
return
;
}
else
{
if
(
stride
>
0
)
end
+=
stride
*
(
extent
-
1
);
else
start
+=
stride
*
(
extent
-
1
);
}
}
/* Return a half-open range */
*
out_start
=
start
;
*
out_end
=
end
+
itemsize
;
}
/* Returns 1 if the arrays have overlapping data, 0 otherwise */
static
int
__pyx_slices_overlap
({{
memviewslice_name
}}
*
slice1
,
{{
memviewslice_name
}}
*
slice2
,
int
ndim
,
size_t
itemsize
)
{
void
*
start1
,
*
end1
,
*
start2
,
*
end2
;
__pyx_get_array_memory_extents
(
slice1
,
&
start1
,
&
end1
,
ndim
,
itemsize
);
__pyx_get_array_memory_extents
(
slice2
,
&
start2
,
&
end2
,
ndim
,
itemsize
);
return
(
start1
<
end2
)
&&
(
start2
<
end1
);
}
////////// MemviewSliceIsCContig.proto //////////
//@requires MemviewSliceIsContig
static
int
__pyx_memviewslice_is_c_contig
(
const
{{
memviewslice_name
}});
#define __pyx_memviewslice_is_c_contig{{ndim}}(slice) \
__pyx_memviewslice_is_contig(&slice, 'C', {{ndim}})
////////// MemviewSliceIsFContig.proto //////////
//@requires MemviewSliceIsContig
static
int
__pyx_memviewslice_is_fortran_contig
(
const
{{
memviewslice_name
}});
#define __pyx_memviewslice_is_f_contig{{ndim}}(slice) \
__pyx_memviewslice_is_contig(&slice, 'F', {{ndim}})
////////// MemviewSliceIsContig.proto //////////
static
int
__pyx_memviewslice_is_contig
(
const
{{
memviewslice_name
}}
*
mvs
,
char
order
);
char
order
,
int
ndim
);
////////// MemviewSliceIsContig //////////
static
int
__pyx_memviewslice_is_contig
(
const
{{
memviewslice_name
}}
*
mvs
,
char
order
)
{
static
int
__pyx_memviewslice_is_contig
(
const
{{
memviewslice_name
}}
*
mvs
,
char
order
,
int
ndim
)
{
int
i
,
index
,
step
,
start
;
int
ndim
=
mvs
->
memview
->
view
.
ndim
;
Py_ssize_t
itemsize
=
mvs
->
memview
->
view
.
itemsize
;
if
(
order
==
'F'
)
{
...
...
@@ -443,16 +519,6 @@ static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs,
return
1
;
}
////////// MemviewSliceIsCContig //////////
static
int
__pyx_memviewslice_is_c_contig
(
const
{{
memviewslice_name
}}
mvs
)
{
return
__pyx_memviewslice_is_contig
(
&
mvs
,
'C'
);
}
////////// MemviewSliceIsFContig //////////
static
int
__pyx_memviewslice_is_fortran_contig
(
const
{{
memviewslice_name
}}
mvs
)
{
return
__pyx_memviewslice_is_contig
(
&
mvs
,
'F'
);
}
/////////////// MemviewSliceIndex ///////////////
static
CYTHON_INLINE
char
*
...
...
tests/run/memoryviewattrs.pyx
View file @
4b9a1ff7
...
...
@@ -74,6 +74,37 @@ def test_copy_to():
print
to_data
[
i
],
print
@
testcase
def
test_overlapping_copy
():
"""
>>> test_overlapping_copy()
"""
cdef
int
i
,
array
[
10
]
for
i
in
range
(
10
):
array
[
i
]
=
i
cdef
int
[:]
slice
=
array
slice
[...]
=
slice
[::
-
1
]
for
i
in
range
(
10
):
assert
slice
[
i
]
==
10
-
1
-
i
@
testcase
def
test_partly_overlapping
():
"""
>>> test_partly_overlapping()
"""
cdef
int
i
,
array
[
10
]
for
i
in
range
(
10
):
array
[
i
]
=
i
cdef
int
[:]
slice
=
array
cdef
int
[:]
slice2
=
slice
[:
5
]
slice2
[...]
=
slice
[
4
:
9
]
for
i
in
range
(
5
):
assert
slice2
[
i
]
==
i
+
4
@
testcase
@
cython
.
nonecheck
(
True
)
def
test_nonecheck1
():
...
...
@@ -140,7 +171,7 @@ def test_copy_mismatch():
>>> test_copy_mismatch()
Traceback (most recent call last):
...
ValueError: memoryview shapes
not the same in dimension 0
ValueError: memoryview shapes
are not the same in dimension 0, got 1 and 2
'''
cdef
int
[:,:,::
1
]
mv1
=
array
((
2
,
2
,
3
),
sizeof
(
int
),
'i'
)
cdef
int
[:,:,::
1
]
mv2
=
array
((
1
,
2
,
3
),
sizeof
(
int
),
'i'
)
...
...
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