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
155a4ef5
Commit
155a4ef5
authored
Aug 09, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support slicing memoryview slices
parent
917cce5e
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
505 additions
and
85 deletions
+505
-85
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+139
-27
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+225
-14
Cython/Compiler/Pipeline.py
Cython/Compiler/Pipeline.py
+5
-2
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+15
-4
Cython/Compiler/UtilityCode.py
Cython/Compiler/UtilityCode.py
+1
-1
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+4
-7
tests/run/cythonarray.pyx
tests/run/cythonarray.pyx
+2
-21
tests/run/cythonarrayutil.pxi
tests/run/cythonarrayutil.pxi
+26
-0
tests/run/memslice.pyx
tests/run/memslice.pyx
+88
-9
No files found.
Cython/Compiler/ExprNodes.py
View file @
155a4ef5
...
@@ -2266,6 +2266,10 @@ class IndexNode(ExprNode):
...
@@ -2266,6 +2266,10 @@ class IndexNode(ExprNode):
# writable)
# writable)
writable_needed
=
False
writable_needed
=
False
# Whether we are indexing or slicing a memoryviewslice
memslice_index
=
False
memslice_slice
=
False
def
__init__
(
self
,
pos
,
index
,
*
args
,
**
kw
):
def
__init__
(
self
,
pos
,
index
,
*
args
,
**
kw
):
ExprNode
.
__init__
(
self
,
pos
,
index
=
index
,
*
args
,
**
kw
)
ExprNode
.
__init__
(
self
,
pos
,
index
=
index
,
*
args
,
**
kw
)
self
.
_index
=
index
self
.
_index
=
index
...
@@ -2286,8 +2290,11 @@ class IndexNode(ExprNode):
...
@@ -2286,8 +2290,11 @@ class IndexNode(ExprNode):
return
self
.
base
.
is_ephemeral
()
return
self
.
base
.
is_ephemeral
()
def
is_simple
(
self
):
def
is_simple
(
self
):
if
self
.
is_buffer_access
:
if
self
.
is_buffer_access
or
self
.
memslice_index
:
return
False
return
False
elif
self
.
memslice_slice
:
return
True
base
=
self
.
base
base
=
self
.
base
return
(
base
.
is_simple
()
and
self
.
index
.
is_simple
()
return
(
base
.
is_simple
()
and
self
.
index
.
is_simple
()
and
base
.
type
and
(
base
.
type
.
is_ptr
or
base
.
type
.
is_array
))
and
base
.
type
and
(
base
.
type
.
is_ptr
or
base
.
type
.
is_array
))
...
@@ -2377,7 +2384,13 @@ class IndexNode(ExprNode):
...
@@ -2377,7 +2384,13 @@ class IndexNode(ExprNode):
# For buffers, self.index is packed out on the initial analysis, and
# For buffers, self.index is packed out on the initial analysis, and
# when cloning self.indices is copied.
# when cloning self.indices is copied.
self
.
is_buffer_access
=
False
self
.
is_buffer_access
=
False
# a[...] = b
self
.
is_memoryviewslice_access
=
False
self
.
is_memoryviewslice_access
=
False
# incomplete indexing, Ellipsis indexing or slicing
self
.
memslice_slice
=
False
# integer indexing
self
.
memslice_index
=
False
self
.
base
.
analyse_types
(
env
)
self
.
base
.
analyse_types
(
env
)
if
self
.
base
.
type
.
is_error
:
if
self
.
base
.
type
.
is_error
:
...
@@ -2402,18 +2415,84 @@ class IndexNode(ExprNode):
...
@@ -2402,18 +2415,84 @@ class IndexNode(ExprNode):
is_memslice
=
self
.
base
.
type
.
is_memoryviewslice
is_memslice
=
self
.
base
.
type
.
is_memoryviewslice
if
(
is_memslice
and
not
self
.
indices
and
isinstance
(
self
.
index
,
EllipsisNode
)):
memoryviewslice_access
=
True
elif
self
.
base
.
type
.
is_buffer
or
is_memslice
:
if
self
.
indices
:
if
self
.
indices
:
indices
=
self
.
indices
indices
=
self
.
indices
else
:
elif
isinstance
(
self
.
index
,
TupleNode
):
if
isinstance
(
self
.
index
,
TupleNode
):
indices
=
self
.
index
.
args
indices
=
self
.
index
.
args
else
:
else
:
indices
=
[
self
.
index
]
indices
=
[
self
.
index
]
if
(
is_memslice
and
not
self
.
indices
and
isinstance
(
self
.
index
,
EllipsisNode
)):
# Memoryviewslice copying
memoryviewslice_access
=
True
elif
is_memslice
:
# memoryviewslice indexing or slicing
import
MemoryView
skip_child_analysis
=
True
indices
=
MemoryView
.
unellipsify
(
indices
,
self
.
base
.
type
.
ndim
)
self
.
memslice_index
=
len
(
indices
)
==
self
.
base
.
type
.
ndim
axes
=
[]
index_type
=
PyrexTypes
.
c_py_ssize_t_type
new_indices
=
[]
if
len
(
indices
)
>
self
.
base
.
type
.
ndim
:
self
.
type
=
error_type
return
error
(
indices
[
self
.
base
.
type
.
ndim
].
pos
,
"Too many indices specified for type %s"
%
self
.
base
.
type
)
suboffsets_dim
=
-
1
for
i
,
index
in
enumerate
(
indices
[:]):
index
.
analyse_types
(
env
)
access
,
packing
=
self
.
base
.
type
.
axes
[
i
]
if
isinstance
(
index
,
SliceNode
):
suboffsets_dim
=
i
self
.
memslice_slice
=
True
axes
.
append
((
access
,
'strided'
))
# Coerce start, stop and step to temps of the right type
for
attr
in
(
'start'
,
'stop'
,
'step'
):
value
=
getattr
(
index
,
attr
)
if
not
value
.
is_none
:
value
=
value
.
coerce_to
(
index_type
,
env
)
value
=
value
.
coerce_to_temp
(
env
)
setattr
(
index
,
attr
,
value
)
new_indices
.
append
(
value
)
elif
index
.
type
.
is_int
:
self
.
memslice_index
=
True
index
=
index
.
coerce_to
(
index_type
,
env
).
coerce_to_temp
(
index_type
)
indices
[
i
]
=
index
new_indices
.
append
(
index
)
if
access
in
(
'ptr'
,
'generic'
)
and
i
!=
0
:
# If this dimension is to disappear, then how do we
# indicate that we need to dereference in this dimension
# if the previous dimension is already indirect, or if
# the previous dimension was direct but also indexed?
# Basically only a[i, j, k, :] can work, as you can
# set the base pointer to start in the fourth dimension
self
.
type
=
error_type
return
error
(
index
.
pos
,
"Indexing of non-leading indirect or generic "
"dimensions not supported yet, "
"try slicing with i:i+1"
)
else
:
self
.
type
=
error_type
return
error
(
index
.
pos
,
"Invalid index for memoryview specified"
)
self
.
memslice_index
=
self
.
memslice_index
and
not
self
.
memslice_slice
self
.
original_indices
=
indices
self
.
indices
=
new_indices
elif
self
.
base
.
type
.
is_buffer
:
# Buffer indexing
if
len
(
indices
)
==
self
.
base
.
type
.
ndim
:
if
len
(
indices
)
==
self
.
base
.
type
.
ndim
:
buffer_access
=
True
buffer_access
=
True
skip_child_analysis
=
True
skip_child_analysis
=
True
...
@@ -2430,7 +2509,7 @@ class IndexNode(ExprNode):
...
@@ -2430,7 +2509,7 @@ class IndexNode(ExprNode):
self
.
nogil
=
env
.
nogil
self
.
nogil
=
env
.
nogil
if
buffer_access
:
if
buffer_access
or
self
.
memslice_index
:
if
self
.
base
.
type
.
is_memoryviewslice
and
not
self
.
base
.
is_name
:
if
self
.
base
.
type
.
is_memoryviewslice
and
not
self
.
base
.
is_name
:
self
.
base
=
self
.
base
.
coerce_to_temp
(
env
)
self
.
base
=
self
.
base
.
coerce_to_temp
(
env
)
...
@@ -2459,6 +2538,11 @@ class IndexNode(ExprNode):
...
@@ -2459,6 +2538,11 @@ class IndexNode(ExprNode):
if
getting
:
if
getting
:
error
(
self
.
pos
,
"memoryviews currently support setting only."
)
error
(
self
.
pos
,
"memoryviews currently support setting only."
)
elif
self
.
memslice_slice
:
self
.
is_temp
=
True
self
.
type
=
PyrexTypes
.
MemoryViewSliceType
(
self
.
base
.
type
.
dtype
,
axes
)
else
:
else
:
base_type
=
self
.
base
.
type
base_type
=
self
.
base
.
type
if
isinstance
(
self
.
index
,
TupleNode
):
if
isinstance
(
self
.
index
,
TupleNode
):
...
@@ -2533,7 +2617,7 @@ class IndexNode(ExprNode):
...
@@ -2533,7 +2617,7 @@ class IndexNode(ExprNode):
gil_message
=
"Indexing Python object"
gil_message
=
"Indexing Python object"
def
nogil_check
(
self
,
env
):
def
nogil_check
(
self
,
env
):
if
self
.
is_buffer_access
:
if
self
.
is_buffer_access
or
self
.
memslice_index
:
if
env
.
directives
[
'boundscheck'
]:
if
env
.
directives
[
'boundscheck'
]:
error
(
self
.
pos
,
"Cannot check buffer index bounds without gil; use boundscheck(False) directive"
)
error
(
self
.
pos
,
"Cannot check buffer index bounds without gil; use boundscheck(False) directive"
)
return
return
...
@@ -2599,7 +2683,7 @@ class IndexNode(ExprNode):
...
@@ -2599,7 +2683,7 @@ class IndexNode(ExprNode):
i
.
free_temps
(
code
)
i
.
free_temps
(
code
)
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
if
self
.
is_buffer_access
:
if
self
.
is_buffer_access
or
self
.
memslice_index
:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
self
.
put_nonecheck
(
code
)
self
.
put_nonecheck
(
code
)
buffer_entry
,
self
.
buffer_ptr_code
=
self
.
buffer_lookup_code
(
code
)
buffer_entry
,
self
.
buffer_ptr_code
=
self
.
buffer_lookup_code
(
code
)
...
@@ -2607,6 +2691,10 @@ class IndexNode(ExprNode):
...
@@ -2607,6 +2691,10 @@ class IndexNode(ExprNode):
# is_temp is True, so must pull out value and incref it.
# is_temp is True, so must pull out value and incref it.
code
.
putln
(
"%s = *%s;"
%
(
self
.
result
(),
self
.
buffer_ptr_code
))
code
.
putln
(
"%s = *%s;"
%
(
self
.
result
(),
self
.
buffer_ptr_code
))
code
.
putln
(
"__Pyx_INCREF((PyObject*)%s);"
%
self
.
result
())
code
.
putln
(
"__Pyx_INCREF((PyObject*)%s);"
%
self
.
result
())
elif
self
.
memslice_slice
:
self
.
put_memoryviewslice_slice_code
(
code
)
elif
self
.
is_temp
:
elif
self
.
is_temp
:
if
self
.
type
.
is_pyobject
:
if
self
.
type
.
is_pyobject
:
if
self
.
index
.
type
.
is_int
:
if
self
.
index
.
type
.
is_int
:
...
@@ -2677,7 +2765,7 @@ class IndexNode(ExprNode):
...
@@ -2677,7 +2765,7 @@ class IndexNode(ExprNode):
self
.
extra_index_params
(),
self
.
extra_index_params
(),
code
.
error_goto
(
self
.
pos
)))
code
.
error_goto
(
self
.
pos
)))
def
generate_memoryviewslice_
setitem
_code
(
self
,
rhs
,
code
,
op
=
""
):
def
generate_memoryviewslice_
copy
_code
(
self
,
rhs
,
code
,
op
=
""
):
assert
isinstance
(
self
.
index
,
EllipsisNode
)
assert
isinstance
(
self
.
index
,
EllipsisNode
)
import
MemoryView
import
MemoryView
util_code
=
MemoryView
.
CopyContentsFuncUtilCode
(
rhs
.
type
,
self
.
type
)
util_code
=
MemoryView
.
CopyContentsFuncUtilCode
(
rhs
.
type
,
self
.
type
)
...
@@ -2687,7 +2775,7 @@ class IndexNode(ExprNode):
...
@@ -2687,7 +2775,7 @@ class IndexNode(ExprNode):
def
generate_buffer_setitem_code
(
self
,
rhs
,
code
,
op
=
""
):
def
generate_buffer_setitem_code
(
self
,
rhs
,
code
,
op
=
""
):
# Used from generate_assignment_code and InPlaceAssignmentNode
# Used from generate_assignment_code and InPlaceAssignmentNode
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
if
code
.
globalstate
.
directives
[
'nonecheck'
]
and
not
self
.
memslice_index
:
self
.
put_nonecheck
(
code
)
self
.
put_nonecheck
(
code
)
buffer_entry
,
ptrexpr
=
self
.
buffer_lookup_code
(
code
)
buffer_entry
,
ptrexpr
=
self
.
buffer_lookup_code
(
code
)
...
@@ -2712,10 +2800,13 @@ class IndexNode(ExprNode):
...
@@ -2712,10 +2800,13 @@ class IndexNode(ExprNode):
def
generate_assignment_code
(
self
,
rhs
,
code
):
def
generate_assignment_code
(
self
,
rhs
,
code
):
self
.
generate_subexpr_evaluation_code
(
code
)
self
.
generate_subexpr_evaluation_code
(
code
)
if
self
.
is_buffer_access
:
if
self
.
is_buffer_access
or
self
.
memslice_index
:
self
.
generate_buffer_setitem_code
(
rhs
,
code
)
self
.
generate_buffer_setitem_code
(
rhs
,
code
)
elif
self
.
memslice_slice
:
error
(
rhs
.
pos
,
"Slice assignment not supported yet"
)
#self.generate_memoryviewslice_setslice_code(rhs, code)
elif
self
.
is_memoryviewslice_access
:
elif
self
.
is_memoryviewslice_access
:
self
.
generate_memoryviewslice_
setitem
_code
(
rhs
,
code
)
self
.
generate_memoryviewslice_
copy
_code
(
rhs
,
code
)
elif
self
.
type
.
is_pyobject
:
elif
self
.
type
.
is_pyobject
:
self
.
generate_setitem_code
(
rhs
.
py_result
(),
code
)
self
.
generate_setitem_code
(
rhs
.
py_result
(),
code
)
else
:
else
:
...
@@ -2750,6 +2841,23 @@ class IndexNode(ExprNode):
...
@@ -2750,6 +2841,23 @@ class IndexNode(ExprNode):
self
.
generate_subexpr_disposal_code
(
code
)
self
.
generate_subexpr_disposal_code
(
code
)
self
.
free_subexpr_temps
(
code
)
self
.
free_subexpr_temps
(
code
)
def
buffer_entry
(
self
):
import
Buffer
,
MemoryView
if
self
.
base
.
is_name
:
entry
=
self
.
base
.
entry
else
:
assert
self
.
base
.
is_temp
cname
=
self
.
base
.
result
()
entry
=
Symtab
.
Entry
(
cname
,
cname
,
self
.
base
.
type
,
self
.
base
.
pos
)
if
entry
.
type
.
is_buffer
:
buffer_entry
=
Buffer
.
BufferEntry
(
entry
)
else
:
buffer_entry
=
MemoryView
.
MemoryViewSliceBufferEntry
(
entry
)
return
buffer_entry
def
buffer_lookup_code
(
self
,
code
):
def
buffer_lookup_code
(
self
,
code
):
# Assign indices to temps
# Assign indices to temps
index_temps
=
[
code
.
funcstate
.
allocate_temp
(
i
.
type
,
manage_ref
=
False
)
index_temps
=
[
code
.
funcstate
.
allocate_temp
(
i
.
type
,
manage_ref
=
False
)
...
@@ -2761,21 +2869,13 @@ class IndexNode(ExprNode):
...
@@ -2761,21 +2869,13 @@ class IndexNode(ExprNode):
# Generate buffer access code using these temps
# Generate buffer access code using these temps
import
Buffer
,
MemoryView
import
Buffer
,
MemoryView
if
self
.
base
.
is_name
:
buffer_entry
=
self
.
buffer_entry
()
entry
=
self
.
base
.
entry
else
:
assert
self
.
base
.
is_temp
cname
=
self
.
base
.
result
()
entry
=
Symtab
.
Entry
(
cname
,
cname
,
self
.
base
.
type
,
self
.
base
.
pos
)
if
entry
.
type
.
is_buffer
:
if
buffer_entry
.
type
.
is_buffer
:
buffer_entry
=
Buffer
.
BufferEntry
(
entry
)
negative_indices
=
entry
.
type
.
negative_indices
negative_indices
=
entry
.
type
.
negative_indices
else
:
else
:
buffer_entry
=
MemoryView
.
MemoryViewSliceBufferEntry
(
entry
)
negative_indices
=
Buffer
.
buffer_defaults
[
'negative_indices'
]
negative_indices
=
Buffer
.
buffer_defaults
[
'negative_indices'
]
return
buffer_entry
,
Buffer
.
put_buffer_lookup_code
(
return
buffer_entry
,
Buffer
.
put_buffer_lookup_code
(
entry
=
buffer_entry
,
entry
=
buffer_entry
,
index_signeds
=
[
i
.
type
.
signed
for
i
in
self
.
indices
],
index_signeds
=
[
i
.
type
.
signed
for
i
in
self
.
indices
],
...
@@ -2784,6 +2884,14 @@ class IndexNode(ExprNode):
...
@@ -2784,6 +2884,14 @@ class IndexNode(ExprNode):
pos
=
self
.
pos
,
code
=
code
,
pos
=
self
.
pos
,
code
=
code
,
negative_indices
=
negative_indices
)
negative_indices
=
negative_indices
)
def
put_memoryviewslice_slice_code
(
self
,
code
):
buffer_entry
=
self
.
buffer_entry
()
buffer_entry
.
generate_buffer_slice_code
(
code
,
self
.
original_indices
,
self
.
base
.
type
,
self
.
type
,
self
.
result
())
def
put_nonecheck
(
self
,
code
):
def
put_nonecheck
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
raise_noneindex_error_utility_code
)
code
.
globalstate
.
use_utility_code
(
raise_noneindex_error_utility_code
)
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
"%s == Py_None"
)
%
self
.
base
.
result_as
(
PyrexTypes
.
py_object_type
))
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
"%s == Py_None"
)
%
self
.
base
.
result_as
(
PyrexTypes
.
py_object_type
))
...
@@ -2791,6 +2899,7 @@ class IndexNode(ExprNode):
...
@@ -2791,6 +2899,7 @@ class IndexNode(ExprNode):
code
.
putln
(
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
"}"
)
code
.
putln
(
"}"
)
class
SliceIndexNode
(
ExprNode
):
class
SliceIndexNode
(
ExprNode
):
# 2-element slice indexing
# 2-element slice indexing
#
#
...
@@ -3928,6 +4037,9 @@ class AttributeNode(ExprNode):
...
@@ -3928,6 +4037,9 @@ class AttributeNode(ExprNode):
if
obj_type
.
has_attributes
:
if
obj_type
.
has_attributes
:
entry
=
None
entry
=
None
if
obj_type
.
attributes_known
():
if
obj_type
.
attributes_known
():
if
(
obj_type
.
is_memoryviewslice
and
not
obj_type
.
scope
.
lookup_here
(
self
.
attribute
)):
obj_type
.
declare_attribute
(
self
.
attribute
)
entry
=
obj_type
.
scope
.
lookup_here
(
self
.
attribute
)
entry
=
obj_type
.
scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
entry
.
is_member
:
if
entry
and
entry
.
is_member
:
entry
=
None
entry
=
None
...
...
Cython/Compiler/MemoryView.py
View file @
155a4ef5
...
@@ -104,11 +104,11 @@ def put_assign_to_memviewslice(lhs_cname, rhs_cname, memviewslicetype, code,
...
@@ -104,11 +104,11 @@ def put_assign_to_memviewslice(lhs_cname, rhs_cname, memviewslicetype, code,
code
.
putln
(
"%s.memview = %s.memview;"
%
(
lhs_cname
,
rhs_cname
))
code
.
putln
(
"%s.memview = %s.memview;"
%
(
lhs_cname
,
rhs_cname
))
code
.
putln
(
"%s.data = %s.data;"
%
(
lhs_cname
,
rhs_cname
))
code
.
putln
(
"%s.data = %s.data;"
%
(
lhs_cname
,
rhs_cname
))
ndim
=
len
(
memviewslicetype
.
axes
)
for
i
in
range
(
memviewslicetype
.
ndim
):
for
i
in
range
(
ndim
):
tup
=
(
lhs_cname
,
i
,
rhs_cname
,
i
)
code
.
putln
(
"%s.shape[%d] = %s.shape[%d];"
%
(
lhs_cname
,
i
,
rhs_cname
,
i
)
)
code
.
putln
(
"%s.shape[%d] = %s.shape[%d];"
%
tup
)
code
.
putln
(
"%s.strides[%d] = %s.strides[%d];"
%
(
lhs_cname
,
i
,
rhs_cname
,
i
)
)
code
.
putln
(
"%s.strides[%d] = %s.strides[%d];"
%
tup
)
code
.
putln
(
"%s.suboffsets[%d] = %s.suboffsets[%d];"
%
(
lhs_cname
,
i
,
rhs_cname
,
i
)
)
code
.
putln
(
"%s.suboffsets[%d] = %s.suboffsets[%d];"
%
tup
)
def
get_buf_flags
(
specs
):
def
get_buf_flags
(
specs
):
is_c_contig
,
is_f_contig
=
is_cf_contig
(
specs
)
is_c_contig
,
is_f_contig
=
is_cf_contig
(
specs
)
...
@@ -182,14 +182,18 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
...
@@ -182,14 +182,18 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
return
self
.
_for_all_ndim
(
"%s.shape[%d]"
)
return
self
.
_for_all_ndim
(
"%s.shape[%d]"
)
def
generate_buffer_lookup_code
(
self
,
code
,
index_cnames
):
def
generate_buffer_lookup_code
(
self
,
code
,
index_cnames
):
axes
=
[(
dim
,
index_cnames
[
dim
],
access
,
packing
)
for
dim
,
(
access
,
packing
)
in
enumerate
(
self
.
type
.
axes
)]
return
self
.
_generate_buffer_lookup_code
(
code
,
axes
)
def
_generate_buffer_lookup_code
(
self
,
code
,
axes
,
cast_result
=
True
):
bufp
=
self
.
buf_ptr
bufp
=
self
.
buf_ptr
type_decl
=
self
.
type
.
dtype
.
declaration_code
(
""
)
type_decl
=
self
.
type
.
dtype
.
declaration_code
(
""
)
for
dim
,
(
access
,
packing
)
in
enumerate
(
self
.
type
.
axes
)
:
for
dim
,
index
,
access
,
packing
in
axes
:
shape
=
"%s.shape[%d]"
%
(
self
.
cname
,
dim
)
shape
=
"%s.shape[%d]"
%
(
self
.
cname
,
dim
)
stride
=
"%s.strides[%d]"
%
(
self
.
cname
,
dim
)
stride
=
"%s.strides[%d]"
%
(
self
.
cname
,
dim
)
suboffset
=
"%s.suboffsets[%d]"
%
(
self
.
cname
,
dim
)
suboffset
=
"%s.suboffsets[%d]"
%
(
self
.
cname
,
dim
)
index
=
index_cnames
[
dim
]
flag
=
get_memoryview_flag
(
access
,
packing
)
flag
=
get_memoryview_flag
(
access
,
packing
)
...
@@ -219,8 +223,215 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
...
@@ -219,8 +223,215 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
bufp
=
'( /* dim=%d */ %s )'
%
(
dim
,
bufp
)
bufp
=
'( /* dim=%d */ %s )'
%
(
dim
,
bufp
)
if
cast_result
:
return
"((%s *) %s)"
%
(
type_decl
,
bufp
)
return
"((%s *) %s)"
%
(
type_decl
,
bufp
)
return
bufp
def
generate_buffer_slice_code
(
self
,
code
,
indices
,
type
,
dst_type
,
dst
):
"""
Generate code for a new memoryview slice.
indices An index in the indices list is either a SliceNode where
start/stop and step are converted to temps of type Py_ssize_t, or a
temp integer index of type Py_ssize_t.
type is the type that is sliced
dst_type is the resulting type
dst is the result memoryview slice temp
For every dimension we do the following:
ensure 0 <= start < n and 0 <= stop <= n
if every dimension is direct:
keep track of possible offsets, set data * to
mslice[0, 0, 0, ...] after the loop
else:
keep a variable 'dim' that
if < 0
indicates the data *
else
indicates suboffsets[dim]
now set shape, strides and suboffsets according to start/stop/step
add the slice or indexing offset to data * or to suboffsets[dim]
update the dim variable if necessary
"""
axes
=
[]
temps
=
[]
dtype
=
PyrexTypes
.
c_py_ssize_t_type
def
put_bounds_code
(
r
,
start
):
"ensure that start 0 <= r < n"
code
.
putln
(
"if (%s < 0) {"
%
r
)
code
.
putln
(
"%s += %s;"
%
(
r
,
shape
))
code
.
putln
(
"if (%s < 0) %s = 0;"
%
(
r
,
r
))
if
start
:
code
.
putln
(
"} else if (%s >= %s) %s = %s - 1;"
%
(
r
,
shape
,
r
,
shape
))
else
:
code
.
putln
(
"} else if (%s > %s) %s = %s;"
%
(
r
,
shape
,
r
,
shape
))
def
update_dim
():
"if we are indirect, update our dim index"
if
access
in
(
'ptr'
,
'generic'
):
if
access
==
'generic'
:
code
.
put
(
"if (%s >= 0)"
%
suboffset
)
code
.
putln
(
"%s = %d;"
%
(
offset_dim
,
dst_dim
))
all_direct
=
True
for
access
,
packing
in
type
.
axes
:
all_direct
=
all_direct
and
access
==
'direct'
if
not
all_direct
:
break
if
not
all_direct
:
offset_dim
=
code
.
funcstate
.
allocate_temp
(
PyrexTypes
.
c_int_type
,
False
)
code
.
putln
(
"%s = -1;"
%
(
offset_dim
,))
code
.
putln
(
"%s.data = %s.data;"
%
(
dst
,
self
.
cname
))
dst_dim
=
0
for
dim
,
index
in
enumerate
(
indices
):
goto_err
=
code
.
error_goto
(
index
.
pos
)
shape
=
"%s.shape[%d]"
%
(
self
.
cname
,
dim
)
stride
=
"%s.strides[%d]"
%
(
self
.
cname
,
dim
)
suboffset
=
"%s.suboffsets[%d]"
%
(
self
.
cname
,
dim
)
dst_shape
=
"%s.shape[%d]"
%
(
dst
,
dst_dim
)
dst_stride
=
"%s.strides[%d]"
%
(
dst
,
dst_dim
)
dst_suboffset
=
"%s.suboffsets[%d]"
%
(
dst
,
dst_dim
)
access
,
packing
=
type
.
axes
[
dim
]
if
isinstance
(
index
,
ExprNodes
.
SliceNode
):
# slice or part of ellipsis
start
=
stop
=
step
=
None
dst_dim
+=
1
# First fix the bounds
if
not
index
.
start
.
is_none
:
start
=
index
.
start
.
result
()
put_bounds_code
(
start
,
start
=
True
)
if
not
index
.
stop
.
is_none
:
stop
=
index
.
stop
.
result
()
put_bounds_code
(
stop
,
start
=
False
)
# Compute the new strides
if
not
index
.
step
.
is_none
:
step
=
index
.
step
.
result
()
code
.
putln
(
"%s = %s * %s;"
%
(
dst_stride
,
stride
,
step
))
else
:
code
.
putln
(
"%s = %s;"
%
(
dst_stride
,
stride
))
# Take care of suboffsets
code
.
putln
(
"%s = %s;"
%
(
dst_suboffset
,
suboffset
))
# If start or stop is not specified, then we need to set
# them according to step
if
not
start
or
not
stop
:
if
step
:
code
.
putln
(
"if (%s > 0) {"
%
step
)
if
not
start
:
start
=
code
.
funcstate
.
allocate_temp
(
dtype
,
False
)
temps
.
append
(
start
)
code
.
putln
(
"%s = 0;"
%
start
)
if
not
stop
:
stop
=
code
.
funcstate
.
allocate_temp
(
dtype
,
False
)
temps
.
append
(
stop
)
code
.
putln
(
"%s = %s;"
%
(
stop
,
shape
))
code
.
putln
(
"} else {"
)
if
start
:
code
.
putln
(
"%s = %s - 1;"
%
(
start
,
shape
))
if
stop
:
code
.
putln
(
"%s = -1;"
%
stop
)
code
.
putln
(
"}"
)
else
:
if
not
start
:
start
=
"0"
if
not
stop
:
stop
=
shape
d
=
dict
(
locals
(),
step
=
step
or
"1"
)
# Take care of shape
code
.
putln
(
"%(dst_shape)s = (%(stop)s - %(start)s) / %(step)s;"
%
d
)
code
.
putln
(
"if (%(dst_shape)s && (%(stop)s - %(start)s) %% %(step)s) %(dst_shape)s++;"
%
d
)
code
.
putln
(
"if (%(dst_shape)s < 0) %(dst_shape)s = 0;"
%
d
)
# Take care of slicing offsets
if
start
!=
"0"
:
if
all_direct
:
axes
.
append
([
dim
,
start
,
access
,
packing
])
else
:
offset
=
"%s * %s"
%
(
start
,
stride
)
d
=
dict
(
dim
=
offset_dim
,
dst
=
dst
,
offset
=
offset
)
code
.
putln
(
"if (%(dim)s < 0) %(dst)s.data += %(offset)s;"
%
d
)
code
.
putln
(
"else %(dst)s.suboffsets[%(dim)s] += %(offset)s;"
%
d
)
else
:
# integer index (or object converted to integer index)
# Note: this dimension disappears
assert
access
==
'direct'
r
=
index
.
result
()
# Bounds checking with error
code
.
globalstate
.
use_utility_code
(
Buffer
.
raise_indexerror_code
)
out_of_bounds
=
"%s < 0 || %s >= %s"
%
(
r
,
r
,
shape
)
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
out_of_bounds
))
code
.
putln
(
'__Pyx_RaiseBufferIndexError(%d);'
%
dim
)
code
.
putln
(
code
.
error_goto
(
index
.
pos
))
code
.
putln
(
"}"
)
if
all_direct
:
axes
.
append
([
dim
,
index
.
result
(),
access
,
packing
])
else
:
add_slice_offset
(
r
)
# Take care of data * for direct access in all dimensions
if
all_direct
:
bufp
=
self
.
_generate_buffer_lookup_code
(
code
,
axes
,
cast_result
=
False
)
code
.
putln
(
"%s.data = %s;"
%
(
dst
,
bufp
))
# Finally take care of memview
code
.
putln
(
"%s.memview = %s.memview;"
%
(
dst
,
self
.
cname
))
for
temp
in
temps
:
code
.
funcstate
.
release_temp
(
temp
)
def
unellipsify
(
indices
,
ndim
):
result
=
[]
seen_ellipsis
=
False
for
index
in
indices
:
if
isinstance
(
index
,
ExprNodes
.
EllipsisNode
):
none
=
ExprNodes
.
NoneNode
(
index
.
pos
)
full_slice
=
ExprNodes
.
SliceNode
(
index
.
pos
,
start
=
none
,
stop
=
none
,
step
=
none
)
if
seen_ellipsis
:
result
.
append
(
full_slice
)
else
:
nslices
=
ndim
-
len
(
indices
)
+
1
result
.
extend
([
full_slice
]
*
nslices
)
seen_ellipsis
=
True
else
:
result
.
append
(
index
)
return
result
def
get_memoryview_flag
(
access
,
packing
):
def
get_memoryview_flag
(
access
,
packing
):
if
access
==
'full'
and
packing
in
(
'strided'
,
'follow'
):
if
access
==
'full'
and
packing
in
(
'strided'
,
'follow'
):
return
'generic'
return
'generic'
...
...
Cython/Compiler/Pipeline.py
View file @
155a4ef5
...
@@ -192,7 +192,6 @@ def create_pipeline(context, mode, exclude_classes=()):
...
@@ -192,7 +192,6 @@ def create_pipeline(context, mode, exclude_classes=()):
FinalOptimizePhase
(
context
),
FinalOptimizePhase
(
context
),
GilCheck
(),
GilCheck
(),
UseUtilityCodeDefinitions
(
context
),
UseUtilityCodeDefinitions
(
context
),
# PrintTree(),
]
]
filtered_stages
=
[]
filtered_stages
=
[]
for
s
in
stages
:
for
s
in
stages
:
...
@@ -293,7 +292,9 @@ def insert_into_pipeline(pipeline, transform, before=None, after=None):
...
@@ -293,7 +292,9 @@ def insert_into_pipeline(pipeline, transform, before=None, after=None):
# Running a pipeline
# Running a pipeline
#
#
def
run_pipeline
(
pipeline
,
source
):
def
run_pipeline
(
pipeline
,
source
,
printtree
=
True
):
from
Cython.Compiler.Visitor
import
PrintTree
error
=
None
error
=
None
data
=
source
data
=
source
try
:
try
:
...
@@ -303,6 +304,8 @@ def run_pipeline(pipeline, source):
...
@@ -303,6 +304,8 @@ def run_pipeline(pipeline, source):
if
DebugFlags
.
debug_verbose_pipeline
:
if
DebugFlags
.
debug_verbose_pipeline
:
t
=
time
()
t
=
time
()
print
"Entering pipeline phase %r"
%
phase
print
"Entering pipeline phase %r"
%
phase
if
not
printtree
and
isinstance
(
phase
,
PrintTree
):
continue
data
=
phase
(
data
)
data
=
phase
(
data
)
if
DebugFlags
.
debug_verbose_pipeline
:
if
DebugFlags
.
debug_verbose_pipeline
:
print
" %.3f seconds"
%
(
time
()
-
t
)
print
" %.3f seconds"
%
(
time
()
-
t
)
...
...
Cython/Compiler/PyrexTypes.py
View file @
155a4ef5
...
@@ -414,8 +414,7 @@ class MemoryViewSliceType(PyrexType):
...
@@ -414,8 +414,7 @@ class MemoryViewSliceType(PyrexType):
def
attributes_known
(
self
):
def
attributes_known
(
self
):
if
self
.
scope
is
None
:
if
self
.
scope
is
None
:
import
Symtab
import
Symtab
,
MemoryView
,
Options
self
.
scope
=
scope
=
Symtab
.
CClassScope
(
self
.
scope
=
scope
=
Symtab
.
CClassScope
(
'mvs_class_'
+
self
.
specialization_suffix
(),
'mvs_class_'
+
self
.
specialization_suffix
(),
...
@@ -424,8 +423,17 @@ class MemoryViewSliceType(PyrexType):
...
@@ -424,8 +423,17 @@ class MemoryViewSliceType(PyrexType):
scope
.
parent_type
=
self
scope
.
parent_type
=
self
scope
.
declare_var
(
'_data'
,
c_char_ptr_type
,
None
,
cname
=
'data'
,
is_cdef
=
1
)
scope
.
declare_var
(
'_data'
,
c_char_ptr_type
,
None
,
cname
=
'data'
,
is_cdef
=
1
)
return
True
def
declare_attribute
(
self
,
attribute
):
import
MemoryView
,
Options
scope
=
self
.
scope
if
attribute
==
'shape'
:
scope
.
declare_var
(
'shape'
,
scope
.
declare_var
(
'shape'
,
c_array_type
(
c_py_ssize_t_type
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
Options
.
buffer_max_dims
),
...
@@ -433,6 +441,7 @@ class MemoryViewSliceType(PyrexType):
...
@@ -433,6 +441,7 @@ class MemoryViewSliceType(PyrexType):
cname
=
'shape'
,
cname
=
'shape'
,
is_cdef
=
1
)
is_cdef
=
1
)
elif
attribute
==
'strides'
:
scope
.
declare_var
(
'strides'
,
scope
.
declare_var
(
'strides'
,
c_array_type
(
c_py_ssize_t_type
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
Options
.
buffer_max_dims
),
...
@@ -440,6 +449,7 @@ class MemoryViewSliceType(PyrexType):
...
@@ -440,6 +449,7 @@ class MemoryViewSliceType(PyrexType):
cname
=
'strides'
,
cname
=
'strides'
,
is_cdef
=
1
)
is_cdef
=
1
)
elif
attribute
==
'suboffsets'
:
scope
.
declare_var
(
'suboffsets'
,
scope
.
declare_var
(
'suboffsets'
,
c_array_type
(
c_py_ssize_t_type
,
c_array_type
(
c_py_ssize_t_type
,
Options
.
buffer_max_dims
),
Options
.
buffer_max_dims
),
...
@@ -447,6 +457,7 @@ class MemoryViewSliceType(PyrexType):
...
@@ -447,6 +457,7 @@ class MemoryViewSliceType(PyrexType):
cname
=
'suboffsets'
,
cname
=
'suboffsets'
,
is_cdef
=
1
)
is_cdef
=
1
)
elif
attribute
in
(
"copy"
,
"copy_fortran"
):
ndim
=
len
(
self
.
axes
)
ndim
=
len
(
self
.
axes
)
to_axes_c
=
[(
'direct'
,
'contig'
)]
to_axes_c
=
[(
'direct'
,
'contig'
)]
...
...
Cython/Compiler/UtilityCode.py
View file @
155a4ef5
...
@@ -118,7 +118,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
...
@@ -118,7 +118,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
pipeline
=
Pipeline
.
insert_into_pipeline
(
pipeline
,
scope_transform
,
pipeline
=
Pipeline
.
insert_into_pipeline
(
pipeline
,
scope_transform
,
before
=
transform
)
before
=
transform
)
(
err
,
tree
)
=
Pipeline
.
run_pipeline
(
pipeline
,
tree
)
(
err
,
tree
)
=
Pipeline
.
run_pipeline
(
pipeline
,
tree
,
printtree
=
False
)
assert
not
err
,
err
assert
not
err
,
err
return
tree
return
tree
...
...
Cython/Utility/MemoryView_C.c
View file @
155a4ef5
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
typedef
struct
{
typedef
struct
{
struct
{{
memview_struct_name
}}
*
memview
;
struct
{{
memview_struct_name
}}
*
memview
;
/* For convenience and faster access */
char
*
data
;
char
*
data
;
Py_ssize_t
shape
[{{
max_dims
}}];
Py_ssize_t
shape
[{{
max_dims
}}];
Py_ssize_t
strides
[{{
max_dims
}}];
Py_ssize_t
strides
[{{
max_dims
}}];
...
@@ -30,9 +29,6 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *);
...
@@ -30,9 +29,6 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *);
#define __Pyx_IS_C_CONTIG 1
#define __Pyx_IS_C_CONTIG 1
#define __Pyx_IS_F_CONTIG 2
#define __Pyx_IS_F_CONTIG 2
/* #define __PYX_MEMSLICE_GETDATA(SLICE) ((char *) SLICE->memview->view->buf) */
static
int
__Pyx_ValidateAndInit_memviewslice
(
struct
__pyx_memoryview_obj
*
memview
,
static
int
__Pyx_ValidateAndInit_memviewslice
(
struct
__pyx_memoryview_obj
*
memview
,
int
*
axes_specs
,
int
c_or_f_flag
,
int
ndim
,
__Pyx_TypeInfo
*
dtype
,
int
*
axes_specs
,
int
c_or_f_flag
,
int
ndim
,
__Pyx_TypeInfo
*
dtype
,
__Pyx_BufFmt_StackElem
stack
[],
__Pyx_memviewslice
*
memviewslice
);
__Pyx_BufFmt_StackElem
stack
[],
__Pyx_memviewslice
*
memviewslice
);
...
@@ -170,7 +166,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
...
@@ -170,7 +166,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
}
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
spec
&
__Pyx_MEMVIEW_PTR
)
{
if
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
<
0
)
{
if
(
!
buf
->
suboffsets
||
(
buf
->
suboffsets
&&
buf
->
suboffsets
[
i
]
<
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."
,
i
);
goto
fail
;
goto
fail
;
...
@@ -287,7 +283,6 @@ static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice,
...
@@ -287,7 +283,6 @@ static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice,
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
if
(
!
memview
)
if
(
!
memview
)
return
;
/* allow uninitialized memoryview assignment */
return
;
/* allow uninitialized memoryview assignment */
/* __pyx_fatalerror("memoryslice is not initialized (line %d)", lineno); */
if
(
memview
->
acquisition_count
<=
0
)
if
(
memview
->
acquisition_count
<=
0
)
__pyx_fatalerror
(
"Acquisition count is %d (line %d)"
,
__pyx_fatalerror
(
"Acquisition count is %d (line %d)"
,
...
@@ -324,6 +319,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
...
@@ -324,6 +319,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
last_time
=
(
memview
->
acquisition_count
--
==
1
);
last_time
=
(
memview
->
acquisition_count
--
==
1
);
PyThread_release_lock
(
memview
->
lock
);
PyThread_release_lock
(
memview
->
lock
);
memslice
->
data
=
NULL
;
if
(
last_time
)
{
if
(
last_time
)
{
if
(
have_gil
)
{
if
(
have_gil
)
{
Py_CLEAR
(
memslice
->
memview
);
Py_CLEAR
(
memslice
->
memview
);
...
@@ -332,6 +328,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
...
@@ -332,6 +328,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
Py_CLEAR
(
memslice
->
memview
);
Py_CLEAR
(
memslice
->
memview
);
PyGILState_Release
(
_gilstate
);
PyGILState_Release
(
_gilstate
);
}
}
}
else
{
memslice
->
memview
=
NULL
;
memslice
->
memview
=
NULL
;
}
}
}
}
...
...
tests/run/cythonarray.pyx
View file @
155a4ef5
...
@@ -5,7 +5,8 @@ from __future__ import unicode_literals
...
@@ -5,7 +5,8 @@ from __future__ import unicode_literals
from
cython
cimport
array
from
cython
cimport
array
cimport
cython
as
cy
cimport
cython
as
cy
from
libc.stdlib
cimport
malloc
,
free
include
"cythonarrayutil.pxi"
def
contiguity
():
def
contiguity
():
'''
'''
...
@@ -67,26 +68,6 @@ def dont_allocate_buffer():
...
@@ -67,26 +68,6 @@ def dont_allocate_buffer():
result
.
callback_free_data
=
callback
result
.
callback_free_data
=
callback
result
=
None
result
=
None
cdef
void
callback
(
char
*
data
):
print
"callback called %d"
%
<
long
>
data
cdef
create_array
(
shape
,
mode
):
cdef
array
result
=
array
(
shape
,
itemsize
=
sizeof
(
int
),
format
=
'i'
,
mode
=
mode
)
cdef
int
*
data
=
<
int
*>
result
.
data
cdef
int
i
,
j
,
cidx
,
fidx
for
i
in
range
(
shape
[
0
]):
for
j
in
range
(
shape
[
1
]):
cidx
=
i
*
shape
[
1
]
+
j
fidx
=
i
+
j
*
shape
[
0
]
if
mode
==
'fortran'
:
data
[
fidx
]
=
cidx
else
:
data
[
cidx
]
=
cidx
return
result
def
test_cython_array_getbuffer
():
def
test_cython_array_getbuffer
():
"""
"""
>>> test_cython_array_getbuffer()
>>> test_cython_array_getbuffer()
...
...
tests/run/cythonarrayutil.pxi
0 → 100644
View file @
155a4ef5
from
libc.stdlib
cimport
malloc
,
free
cimport
cython
cdef
void
callback
(
char
*
data
):
print
"callback called %d"
%
<
long
>
data
def
create_array
(
shape
,
mode
,
use_callback
=
False
):
cdef
cython
.
array
result
=
cython
.
array
(
shape
,
itemsize
=
sizeof
(
int
),
format
=
'i'
,
mode
=
mode
)
cdef
int
*
data
=
<
int
*>
result
.
data
cdef
int
i
,
j
,
cidx
,
fidx
for
i
in
range
(
shape
[
0
]):
for
j
in
range
(
shape
[
1
]):
cidx
=
i
*
shape
[
1
]
+
j
fidx
=
i
+
j
*
shape
[
0
]
if
mode
==
'fortran'
:
data
[
fidx
]
=
cidx
else
:
data
[
cidx
]
=
cidx
if
use_callback
:
result
.
callback_free_data
=
callback
return
result
tests/run/memslice.pyx
View file @
155a4ef5
...
@@ -23,6 +23,7 @@ def testcase(func):
...
@@ -23,6 +23,7 @@ def testcase(func):
include
"mockbuffers.pxi"
include
"mockbuffers.pxi"
include
"cythonarrayutil.pxi"
#
#
# Buffer acquire and release tests
# Buffer acquire and release tests
...
@@ -1083,12 +1084,14 @@ def buffer_nogil():
...
@@ -1083,12 +1084,14 @@ def buffer_nogil():
#
#
### Test cdef functions
### Test cdef functions
#
#
cdef
cdef
_function
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
ObjectMockBuffer
(
None
,
[[
"spam"
],[
"ham"
],[
"eggs"
]])):
objs
=
[[
"spam"
],
[
"ham"
],
[
"eggs"
]]
cdef
cdef
_function
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
ObjectMockBuffer
(
None
,
objs
)):
print
'cdef called'
print
'cdef called'
print
buf1
[
6
],
buf2
[
1
,
0
]
print
buf1
[
6
],
buf2
[
1
,
0
]
buf2
[
1
,
0
]
=
"eggs"
buf2
[
1
,
0
]
=
"eggs"
@
testcase
def
test_cdef_function
(
o1
,
o2
=
None
):
def
test_cdef_function
(
o1
,
o2
=
None
):
"""
"""
>>> A = IntMockBuffer("A", range(10))
>>> A = IntMockBuffer("A", range(10))
...
@@ -1101,19 +1104,22 @@ def test_cdef_function(o1, o2=None):
...
@@ -1101,19 +1104,22 @@ def test_cdef_function(o1, o2=None):
cdef called
cdef called
6 eggs
6 eggs
released A
released A
>>> B = ObjectMockBuffer("B", range(25), shape=(5, 5))
>>> L = [[x] for x in range(25)]
>>> B = ObjectMockBuffer("B", L, shape=(5, 5))
>>> test_cdef_function(A, B)
>>> test_cdef_function(A, B)
acquired A
acquired A
acquired B
cdef called
cdef called
6 eggs
6 eggs
released A
released A
released B
acquired A
acquired A
acquired B
cdef called
cdef called
6 eggs
6 eggs
released A
released A
acquired A
acquired B
cdef called
6 1
released A
released B
released B
"""
"""
cdef
_function
(
o1
)
cdef
_function
(
o1
)
...
@@ -1122,15 +1128,15 @@ def test_cdef_function(o1, o2=None):
...
@@ -1122,15 +1128,15 @@ def test_cdef_function(o1, o2=None):
if
o2
:
if
o2
:
cdef
_function
(
o1
,
o2
)
cdef
_function
(
o1
,
o2
)
cdef
int
[:]
global_A
=
IntMockBuffer
(
"A"
,
range
(
10
))
cdef
int
[:]
global_A
=
IntMockBuffer
(
"Global_A"
,
range
(
10
))
cdef
object
[::
view
.
indirect
,
:]
global_B
=
ObjectMockBuffer
(
cdef
object
[::
view
.
indirect
,
:]
global_B
=
ObjectMockBuffer
(
None
,
objs
)
None
,
[[
"spam"
],[
"ham"
],[
"eggs"
]])
cdef
cdef
_function2
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
global_B
):
cdef
cdef
_function2
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
global_B
):
print
'cdef2 called'
print
'cdef2 called'
print
buf1
[
6
],
buf2
[
1
,
0
]
print
buf1
[
6
],
buf2
[
1
,
0
]
buf2
[
1
,
0
]
=
"eggs"
buf2
[
1
,
0
]
=
"eggs"
@
testcase
def
test_cdef_function2
():
def
test_cdef_function2
():
"""
"""
>>> test_cdef_function2()
>>> test_cdef_function2()
...
@@ -1151,3 +1157,76 @@ def test_cdef_function2():
...
@@ -1151,3 +1157,76 @@ def test_cdef_function2():
print
global_B
[
1
,
0
]
print
global_B
[
1
,
0
]
cdef
_function2
(
global_A
,
global_B
)
cdef
_function2
(
global_A
,
global_B
)
@
testcase
def
test_slicing
(
arg
):
"""
Test simple slicing
>>> test_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
acquired A
3 9 2
1232 -44 4
-1 -1 -1
released A
Test direct slicing, negative slice oob in dim 2
>>> test_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
acquired A
0 0 2
48 -12 4
-1 -1 -1
released A
Test indirect slicing
>>> L = [[range(k * 12 + j * 4, k * 12 + j * 4 + 4) for j in xrange(3)] for k in xrange(5)]
>>> test_slicing(IntMockBuffer("A", L, shape=(5, 3, 4)))
acquired A
2 0 2
8 -4 4
0 0 -1
released A
"""
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
a
=
arg
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
print
b
.
shape
[
0
],
b
.
shape
[
1
],
b
.
shape
[
2
]
print
b
.
strides
[
0
],
b
.
strides
[
1
],
b
.
strides
[
2
]
print
b
.
suboffsets
[
0
],
b
.
suboffsets
[
1
],
b
.
suboffsets
[
2
]
cdef
int
i
,
j
,
k
for
i
in
range
(
b
.
shape
[
0
]):
for
j
in
range
(
b
.
shape
[
1
]):
for
k
in
range
(
b
.
shape
[
2
]):
itemA
=
a
[
2
+
2
*
i
,
-
4
-
j
,
1
+
k
]
itemB
=
b
[
i
,
j
,
k
]
assert
itemA
==
itemB
,
(
i
,
j
,
k
,
itemA
,
itemB
)
@
testcase
def
test_slicing_and_indexing
(
arg
):
"""
>>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5))
>>> test_slicing_and_indexing(a)
acquired A
5 2
60 8
126 113
[111]
released A
"""
cdef
int
[:,
:,
:]
a
=
arg
cdef
int
[:,
:]
b
=
a
[
-
5
:,
1
,
1
::
2
]
cdef
int
[:,
:]
c
=
b
[
4
:
1
:
-
1
,
::
-
1
]
cdef
int
[:]
d
=
c
[
2
,
1
:
2
]
print
b
.
shape
[
0
],
b
.
shape
[
1
]
print
b
.
strides
[
0
],
b
.
strides
[
1
]
cdef
int
i
,
j
for
i
in
range
(
b
.
shape
[
0
]):
for
j
in
range
(
b
.
shape
[
1
]):
itemA
=
a
[
-
5
+
i
,
1
,
1
+
2
*
j
]
itemB
=
b
[
i
,
j
]
assert
itemA
==
itemB
,
(
i
,
j
,
itemA
,
itemB
)
print
c
[
1
,
1
],
c
[
2
,
0
]
print
[
d
[
i
]
for
i
in
range
(
d
.
shape
[
0
])]
\ 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