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
Xavier Thompson
cython
Commits
b7e14b9a
Commit
b7e14b9a
authored
Aug 19, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cimport cython in CyUtility, more tests, nogil slicing
parent
8105941c
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
561 additions
and
340 deletions
+561
-340
Cython/Compiler/Code.pxd
Cython/Compiler/Code.pxd
+2
-0
Cython/Compiler/CythonScope.py
Cython/Compiler/CythonScope.py
+10
-5
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+14
-14
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+64
-180
Cython/Compiler/UtilityCode.py
Cython/Compiler/UtilityCode.py
+10
-5
Cython/Utility/MemoryView.pyx
Cython/Utility/MemoryView.pyx
+218
-88
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+2
-2
tests/run/memoryview.pyx
tests/run/memoryview.pyx
+112
-19
tests/run/memslice.pyx
tests/run/memslice.pyx
+113
-13
tests/run/numpy_memoryview.pyx
tests/run/numpy_memoryview.pyx
+16
-14
No files found.
Cython/Compiler/Code.pxd
View file @
b7e14b9a
...
@@ -13,6 +13,8 @@ cdef class UtilityCode(UtilityCodeBase):
...
@@ -13,6 +13,8 @@ cdef class UtilityCode(UtilityCodeBase):
cdef
public
dict
_cache
cdef
public
dict
_cache
cdef
public
list
specialize_list
cdef
public
list
specialize_list
cdef
public
object
proto_block
cdef
public
object
proto_block
cdef
public
object
name
cdef
public
object
file
cpdef
put_code
(
self
,
output
)
cpdef
put_code
(
self
,
output
)
...
...
Cython/Compiler/CythonScope.py
View file @
b7e14b9a
...
@@ -75,10 +75,13 @@ class CythonScope(ModuleScope):
...
@@ -75,10 +75,13 @@ class CythonScope(ModuleScope):
Creates some entries for testing purposes and entries for
Creates some entries for testing purposes and entries for
cython.array() and for cython.view.*.
cython.array() and for cython.view.*.
"""
"""
cython_testscope_utility_code
.
declare_in_scope
(
self
)
cython_testscope_utility_code
.
declare_in_scope
(
cython_test_extclass_utility_code
.
declare_in_scope
(
self
)
self
,
cython_scope
=
self
)
cython_test_extclass_utility_code
.
declare_in_scope
(
self
,
cython_scope
=
self
)
MemoryView
.
cython_array_utility_code
.
declare_in_scope
(
self
)
MemoryView
.
cython_array_utility_code
.
declare_in_scope
(
self
,
cython_scope
=
self
)
#
#
# The view sub-scope
# The view sub-scope
...
@@ -88,9 +91,11 @@ class CythonScope(ModuleScope):
...
@@ -88,9 +91,11 @@ class CythonScope(ModuleScope):
viewscope
.
is_cython_builtin
=
True
viewscope
.
is_cython_builtin
=
True
viewscope
.
pxd_file_loaded
=
True
viewscope
.
pxd_file_loaded
=
True
cythonview_testscope_utility_code
.
declare_in_scope
(
viewscope
)
cythonview_testscope_utility_code
.
declare_in_scope
(
viewscope
,
cython_scope
=
self
)
view_utility_scope
=
MemoryView
.
view_utility_code
.
declare_in_scope
(
viewscope
)
view_utility_scope
=
MemoryView
.
view_utility_code
.
declare_in_scope
(
viewscope
,
cython_scope
=
self
)
# MemoryView.memview_fromslice_utility_code.from_scope = view_utility_scope
# MemoryView.memview_fromslice_utility_code.from_scope = view_utility_scope
# MemoryView.memview_fromslice_utility_code.declare_in_scope(viewscope)
# MemoryView.memview_fromslice_utility_code.declare_in_scope(viewscope)
...
...
Cython/Compiler/ExprNodes.py
View file @
b7e14b9a
...
@@ -2432,7 +2432,8 @@ class IndexNode(ExprNode):
...
@@ -2432,7 +2432,8 @@ class IndexNode(ExprNode):
import
MemoryView
import
MemoryView
skip_child_analysis
=
True
skip_child_analysis
=
True
indices
=
MemoryView
.
unellipsify
(
indices
,
self
.
base
.
type
.
ndim
)
have_slices
,
indices
=
MemoryView
.
unellipsify
(
indices
,
self
.
base
.
type
.
ndim
)
self
.
memslice_index
=
len
(
indices
)
==
self
.
base
.
type
.
ndim
self
.
memslice_index
=
len
(
indices
)
==
self
.
base
.
type
.
ndim
axes
=
[]
axes
=
[]
...
@@ -2462,24 +2463,19 @@ class IndexNode(ExprNode):
...
@@ -2462,24 +2463,19 @@ class IndexNode(ExprNode):
value
=
getattr
(
index
,
attr
)
value
=
getattr
(
index
,
attr
)
if
not
value
.
is_none
:
if
not
value
.
is_none
:
value
=
value
.
coerce_to
(
index_type
,
env
)
value
=
value
.
coerce_to
(
index_type
,
env
)
value
=
value
.
coerce_to_temp
(
env
)
#
value = value.coerce_to_temp(env)
setattr
(
index
,
attr
,
value
)
setattr
(
index
,
attr
,
value
)
new_indices
.
append
(
value
)
new_indices
.
append
(
value
)
elif
index
.
type
.
is_int
:
elif
index
.
type
.
is_int
:
self
.
memslice_index
=
True
self
.
memslice_index
=
True
index
=
index
.
coerce_to
(
index_type
,
env
).
coerce_to_temp
(
index
=
index
.
coerce_to
(
index_type
,
env
)
\
index_type
)
#.coerce_to_temp(
# index_type)
indices
[
i
]
=
index
indices
[
i
]
=
index
new_indices
.
append
(
index
)
new_indices
.
append
(
index
)
if
access
in
(
'ptr'
,
'generic'
)
and
i
!=
0
:
if
access
in
(
'ptr'
,
'generic'
)
and
i
!=
0
and
have_slices
:
# 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
self
.
type
=
error_type
return
error
(
index
.
pos
,
return
error
(
index
.
pos
,
"Indexing of non-leading indirect or generic "
"Indexing of non-leading indirect or generic "
...
@@ -2494,6 +2490,8 @@ class IndexNode(ExprNode):
...
@@ -2494,6 +2490,8 @@ class IndexNode(ExprNode):
self
.
original_indices
=
indices
self
.
original_indices
=
indices
self
.
indices
=
new_indices
self
.
indices
=
new_indices
self
.
env
=
env
elif
self
.
base
.
type
.
is_buffer
:
elif
self
.
base
.
type
.
is_buffer
:
# Buffer indexing
# Buffer indexing
if
len
(
indices
)
==
self
.
base
.
type
.
ndim
:
if
len
(
indices
)
==
self
.
base
.
type
.
ndim
:
...
@@ -2893,7 +2891,8 @@ class IndexNode(ExprNode):
...
@@ -2893,7 +2891,8 @@ class IndexNode(ExprNode):
self
.
original_indices
,
self
.
original_indices
,
self
.
base
.
type
,
self
.
base
.
type
,
self
.
type
,
self
.
type
,
self
.
result
())
self
.
result
(),
have_gil
=
not
self
.
env
.
nogil
)
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
)
...
@@ -4092,8 +4091,9 @@ class AttributeNode(ExprNode):
...
@@ -4092,8 +4091,9 @@ class AttributeNode(ExprNode):
def
nogil_check
(
self
,
env
):
def
nogil_check
(
self
,
env
):
if
self
.
is_py_attr
:
if
self
.
is_py_attr
:
self
.
gil_error
()
self
.
gil_error
()
import
MemoryView
elif
self
.
type
.
is_memoryviewslice
:
MemoryView
.
err_if_nogil_initialized_check
(
self
.
pos
,
env
,
'attribute'
)
import
MemoryView
MemoryView
.
err_if_nogil_initialized_check
(
self
.
pos
,
env
,
'attribute'
)
gil_message
=
"Accessing Python attribute"
gil_message
=
"Accessing Python attribute"
...
...
Cython/Compiler/MemoryView.py
View file @
b7e14b9a
...
@@ -228,189 +228,72 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
...
@@ -228,189 +228,72 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
return
bufp
return
bufp
def
generate_buffer_slice_code
(
self
,
code
,
indices
,
type
,
dst_type
,
dst
):
def
generate_buffer_slice_code
(
self
,
code
,
indices
,
type
,
dst_type
,
dst
,
have_gil
):
"""
slicefunc
=
"__pyx_memoryview_slice_memviewslice"
Generate code for a new memoryview slice.
new_ndim
=
0
cname
=
self
.
cname
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
suboffset_dim
=
code
.
funcstate
.
allocate_temp
(
PyrexTypes
.
c_int_type
,
temp integer index of type Py_ssize_t.
False
)
type is the type that is sliced
index_code
=
(
"%(slicefunc)s(&%(cname)s, &%(dst)s, %(have_gil)d, "
dst_type is the resulting type
"%(dim)d, %(new_ndim)d, &%(suboffset_dim)s, "
dst is the result memoryview slice temp
"%(idx)s, 0, 0, 0, 0, 0, 0)"
)
For every dimension we do the following:
slice_code
=
(
"%(slicefunc)s(&%(cname)s, &%(dst)s, %(have_gil)d, "
"/* dim */ %(dim)d, "
ensure 0 <= start < n and 0 <= stop <= n
"/* new_ndim */ %(new_ndim)d, "
"/* suboffset_dim */ &%(suboffset_dim)s, "
if every dimension is direct:
"/* start */ %(start)s, "
keep track of possible offsets, set data * to
"/* stop */ %(stop)s, "
mslice[0, 0, 0, ...] after the loop
"/* step */ %(step)s, "
else:
"/* have_start */ %(have_start)d, "
keep a variable 'dim' that
"/* have_stop */ %(have_stop)d, "
if < 0
"/* have_step */ %(have_step)d, "
indicates the data *
"/* is_slice */ 1)"
)
else
indicates suboffsets[dim]
def
generate_slice_call
(
expr
):
pos
=
index
.
pos
now set shape, strides and suboffsets according to start/stop/step
if
have_gil
:
add the slice or indexing offset to data * or to suboffsets[dim]
code
.
putln
(
code
.
error_goto_if
(
expr
,
pos
))
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
:
else
:
code
.
putln
(
"} else if (%s > %s) %s = %s;"
%
(
r
,
shape
,
r
,
shape
))
code
.
putln
(
"{"
)
code
.
putln
(
"const char *__pyx_t_result = %s;"
%
expr
)
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
):
code
.
putln
(
"if (unlikely(__pyx_t_result)) {"
)
# slice or part of ellipsis
code
.
put_ensure_gil
()
code
.
putln
(
"PyErr_Format(PyExc_IndexError, "
"__pyx_t_result, %d)"
%
dim
)
code
.
put_release_ensured_gil
()
code
.
putln
(
code
.
goto_error
(
pos
))
code
.
putln
(
"}"
)
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
(
"}"
)
code
.
putln
(
"}"
)
if
all_direct
:
code
.
putln
(
"%s = -1;"
%
suboffset_dim
)
axes
.
append
([
dim
,
index
.
result
(),
access
,
packing
])
code
.
putln
(
"%(dst)s.data = %(cname)s.data;"
%
locals
())
else
:
code
.
putln
(
"%(dst)s.memview = %(cname)s.memview;"
%
locals
())
add_slice_offset
(
r
)
# Take care of data * for direct access in all dimensions
for
dim
,
index
in
enumerate
(
indices
):
if
all_direct
:
if
not
isinstance
(
index
,
ExprNodes
.
SliceNode
):
bufp
=
self
.
_generate_buffer_lookup_code
(
code
,
axes
,
idx
=
index
.
result
()
cast_result
=
False
)
generate_slice_call
(
index_code
%
locals
())
code
.
putln
(
"%s.data = %s;"
%
(
dst
,
bufp
))
else
:
d
=
{}
for
s
in
"start stop step"
.
split
():
idx
=
getattr
(
index
,
s
)
have_idx
=
d
[
'have_'
+
s
]
=
not
idx
.
is_none
if
have_idx
:
d
[
s
]
=
idx
.
result
()
else
:
d
[
s
]
=
"0"
# Finally take care of memview
d
.
update
(
locals
())
code
.
putln
(
"%s.memview = %s.memview;"
%
(
dst
,
self
.
cname
))
generate_slice_call
(
slice_code
%
d
)
new_ndim
+=
1
for
temp
in
temps
:
code
.
funcstate
.
release_temp
(
suboffset_dim
)
code
.
funcstate
.
release_temp
(
temp
)
def
empty_slice
(
pos
):
def
empty_slice
(
pos
):
none
=
ExprNodes
.
NoneNode
(
pos
)
none
=
ExprNodes
.
NoneNode
(
pos
)
...
@@ -420,10 +303,13 @@ def empty_slice(pos):
...
@@ -420,10 +303,13 @@ def empty_slice(pos):
def
unellipsify
(
indices
,
ndim
):
def
unellipsify
(
indices
,
ndim
):
result
=
[]
result
=
[]
seen_ellipsis
=
False
seen_ellipsis
=
False
have_slices
=
False
for
index
in
indices
:
for
index
in
indices
:
if
isinstance
(
index
,
ExprNodes
.
EllipsisNode
):
if
isinstance
(
index
,
ExprNodes
.
EllipsisNode
):
have_slices
=
True
full_slice
=
empty_slice
(
index
.
pos
)
full_slice
=
empty_slice
(
index
.
pos
)
if
seen_ellipsis
:
if
seen_ellipsis
:
result
.
append
(
full_slice
)
result
.
append
(
full_slice
)
else
:
else
:
...
@@ -431,13 +317,15 @@ def unellipsify(indices, ndim):
...
@@ -431,13 +317,15 @@ def unellipsify(indices, ndim):
result
.
extend
([
full_slice
]
*
nslices
)
result
.
extend
([
full_slice
]
*
nslices
)
seen_ellipsis
=
True
seen_ellipsis
=
True
else
:
else
:
have_slices
=
have_slices
or
isinstance
(
index
,
ExprNodes
.
SliceNode
)
result
.
append
(
index
)
result
.
append
(
index
)
if
len
(
result
)
<
ndim
:
if
len
(
result
)
<
ndim
:
have_slices
=
True
nslices
=
ndim
-
len
(
result
)
nslices
=
ndim
-
len
(
result
)
result
.
extend
([
empty_slice
(
indices
[
-
1
].
pos
)]
*
nslices
)
result
.
extend
([
empty_slice
(
indices
[
-
1
].
pos
)]
*
nslices
)
return
result
return
have_slices
,
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'
):
...
@@ -885,10 +773,6 @@ view_constant_to_access_packing = {
...
@@ -885,10 +773,6 @@ view_constant_to_access_packing = {
'indirect_contiguous'
:
(
'ptr'
,
'contig'
),
'indirect_contiguous'
:
(
'ptr'
,
'contig'
),
}
}
def
get_access_packing
(
view_scope_constant
):
if
view_scope_constant
.
name
==
'generic'
:
return
'full'
,
def
validate_axes_specs
(
positions
,
specs
):
def
validate_axes_specs
(
positions
,
specs
):
packing_specs
=
(
'contig'
,
'strided'
,
'follow'
)
packing_specs
=
(
'contig'
,
'strided'
,
'follow'
)
...
...
Cython/Compiler/UtilityCode.py
View file @
b7e14b9a
...
@@ -9,6 +9,7 @@ class NonManglingModuleScope(Symtab.ModuleScope):
...
@@ -9,6 +9,7 @@ class NonManglingModuleScope(Symtab.ModuleScope):
def
__init__
(
self
,
prefix
,
*
args
,
**
kw
):
def
__init__
(
self
,
prefix
,
*
args
,
**
kw
):
self
.
prefix
=
prefix
self
.
prefix
=
prefix
self
.
cython_scope
=
None
Symtab
.
ModuleScope
.
__init__
(
self
,
*
args
,
**
kw
)
Symtab
.
ModuleScope
.
__init__
(
self
,
*
args
,
**
kw
)
def
add_imported_entry
(
self
,
name
,
entry
,
pos
):
def
add_imported_entry
(
self
,
name
,
entry
,
pos
):
...
@@ -31,9 +32,12 @@ class CythonUtilityCodeContext(StringParseContext):
...
@@ -31,9 +32,12 @@ class CythonUtilityCodeContext(StringParseContext):
def
find_module
(
self
,
module_name
,
relative_to
=
None
,
pos
=
None
,
def
find_module
(
self
,
module_name
,
relative_to
=
None
,
pos
=
None
,
need_pxd
=
1
):
need_pxd
=
1
):
if
module_name
!=
self
.
module_name
:
if
module_name
!=
self
.
module_name
:
raise
AssertionError
(
"Not yet supporting any cimports/includes "
if
module_name
not
in
self
.
modules
:
"from string code snippets"
)
raise
AssertionError
(
"Only the cython cimport is supported."
)
else
:
return
self
.
modules
[
module_name
]
if
self
.
scope
is
None
:
if
self
.
scope
is
None
:
self
.
scope
=
NonManglingModuleScope
(
self
.
prefix
,
self
.
scope
=
NonManglingModuleScope
(
self
.
prefix
,
...
@@ -78,7 +82,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
...
@@ -78,7 +82,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
self
.
requires
=
requires
or
[]
self
.
requires
=
requires
or
[]
self
.
from_scope
=
from_scope
self
.
from_scope
=
from_scope
def
get_tree
(
self
,
entries_only
=
False
):
def
get_tree
(
self
,
entries_only
=
False
,
cython_scope
=
None
):
from
AnalysedTreeTransforms
import
AutoTestDictTransform
from
AnalysedTreeTransforms
import
AutoTestDictTransform
# The AutoTestDictTransform creates the statement "__test__ = {}",
# The AutoTestDictTransform creates the statement "__test__ = {}",
# which when copied into the main ModuleNode overwrites
# which when copied into the main ModuleNode overwrites
...
@@ -88,6 +92,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
...
@@ -88,6 +92,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
import
Pipeline
,
ParseTreeTransforms
import
Pipeline
,
ParseTreeTransforms
context
=
CythonUtilityCodeContext
(
self
.
name
)
context
=
CythonUtilityCodeContext
(
self
.
name
)
context
.
prefix
=
self
.
prefix
context
.
prefix
=
self
.
prefix
context
.
cython_scope
=
cython_scope
#context = StringParseContext(self.name)
#context = StringParseContext(self.name)
tree
=
parse_from_strings
(
self
.
name
,
self
.
impl
,
context
=
context
,
tree
=
parse_from_strings
(
self
.
name
,
self
.
impl
,
context
=
context
,
allow_struct_enum_decorator
=
True
)
allow_struct_enum_decorator
=
True
)
...
@@ -125,13 +130,13 @@ class CythonUtilityCode(Code.UtilityCodeBase):
...
@@ -125,13 +130,13 @@ class CythonUtilityCode(Code.UtilityCodeBase):
def
put_code
(
self
,
output
):
def
put_code
(
self
,
output
):
pass
pass
def
declare_in_scope
(
self
,
dest_scope
,
used
=
False
):
def
declare_in_scope
(
self
,
dest_scope
,
used
=
False
,
cython_scope
=
None
):
"""
"""
Declare all entries from the utility code in dest_scope. Code will only
Declare all entries from the utility code in dest_scope. Code will only
be included for used entries. If module_name is given, declare the
be included for used entries. If module_name is given, declare the
type entries with that name.
type entries with that name.
"""
"""
tree
=
self
.
get_tree
(
entries_only
=
True
)
tree
=
self
.
get_tree
(
entries_only
=
True
,
cython_scope
=
cython_scope
)
entries
=
tree
.
scope
.
entries
entries
=
tree
.
scope
.
entries
entries
.
pop
(
'__name__'
)
entries
.
pop
(
'__name__'
)
...
...
Cython/Utility/MemoryView.pyx
View file @
b7e14b9a
...
@@ -165,6 +165,8 @@ cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *
...
@@ -165,6 +165,8 @@ cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *
########## View.MemoryView ##########
########## View.MemoryView ##########
import
cython
# from cpython cimport ...
# from cpython cimport ...
cdef
extern
from
"Python.h"
:
cdef
extern
from
"Python.h"
:
int
PyIndex_Check
(
object
)
int
PyIndex_Check
(
object
)
...
@@ -245,7 +247,6 @@ cdef class memoryview(object):
...
@@ -245,7 +247,6 @@ cdef class memoryview(object):
cdef
char
*
itemp
=
<
char
*>
self
.
view
.
buf
cdef
char
*
itemp
=
<
char
*>
self
.
view
.
buf
for
dim
,
idx
in
enumerate
(
index
):
for
dim
,
idx
in
enumerate
(
index
):
_check_index
(
idx
)
itemp
=
pybuffer_index
(
&
self
.
view
,
itemp
,
idx
,
dim
)
itemp
=
pybuffer_index
(
&
self
.
view
,
itemp
,
idx
,
dim
)
return
itemp
return
itemp
...
@@ -255,13 +256,13 @@ cdef class memoryview(object):
...
@@ -255,13 +256,13 @@ cdef class memoryview(object):
if
index
is
Ellipsis
:
if
index
is
Ellipsis
:
return
self
return
self
have_slices
,
ind
ex
=
_unellipsify
(
index
,
self
.
view
.
ndim
)
have_slices
,
ind
ices
=
_unellipsify
(
index
,
self
.
view
.
ndim
)
cdef
char
*
itemp
cdef
char
*
itemp
if
have_slices
:
if
have_slices
:
return
pybuffer_slice
(
self
,
index
)
return
memview_slice
(
self
,
indices
)
else
:
else
:
itemp
=
self
.
get_item_pointer
(
ind
ex
)
itemp
=
self
.
get_item_pointer
(
ind
ices
)
return
self
.
convert_item_to_object
(
itemp
)
return
self
.
convert_item_to_object
(
itemp
)
@
cname
(
'__pyx_memoryview_setitem'
)
@
cname
(
'__pyx_memoryview_setitem'
)
...
@@ -355,12 +356,11 @@ cdef class memoryview(object):
...
@@ -355,12 +356,11 @@ cdef class memoryview(object):
cdef
memoryview_cwrapper
(
object
o
,
int
flags
):
cdef
memoryview_cwrapper
(
object
o
,
int
flags
):
return
memoryview
(
o
,
flags
)
return
memoryview
(
o
,
flags
)
cdef
_check_index
(
index
):
if
not
PyIndex_Check
(
index
):
raise
TypeError
(
"Cannot index with %s"
%
type
(
index
))
cdef
tuple
_unellipsify
(
object
index
,
int
ndim
):
cdef
tuple
_unellipsify
(
object
index
,
int
ndim
):
"""
Replace all ellipses with full slices and fill incomplete indices with
full slices.
"""
if
not
isinstance
(
index
,
tuple
):
if
not
isinstance
(
index
,
tuple
):
tup
=
(
index
,)
tup
=
(
index
,)
else
:
else
:
...
@@ -373,11 +373,14 @@ cdef tuple _unellipsify(object index, int ndim):
...
@@ -373,11 +373,14 @@ cdef tuple _unellipsify(object index, int ndim):
if
item
is
Ellipsis
:
if
item
is
Ellipsis
:
if
not
seen_ellipsis
:
if
not
seen_ellipsis
:
result
.
extend
([
slice
(
None
)]
*
(
ndim
-
len
(
tup
)
+
1
))
result
.
extend
([
slice
(
None
)]
*
(
ndim
-
len
(
tup
)
+
1
))
result
.
extend
(
tup
[
idx
+
1
:])
seen_ellipsis
=
True
else
:
else
:
result
.
append
(
slice
(
None
))
result
.
append
(
slice
(
None
))
have_slices
=
True
have_slices
=
True
else
:
else
:
if
not
isinstance
(
item
,
slice
)
and
not
PyIndex_Check
(
item
):
raise
TypeError
(
"Cannot index with type '%s'"
%
type
(
item
))
have_slices
=
have_slices
or
isinstance
(
item
,
slice
)
have_slices
=
have_slices
or
isinstance
(
item
,
slice
)
result
.
append
(
item
)
result
.
append
(
item
)
...
@@ -385,102 +388,212 @@ cdef tuple _unellipsify(object index, int ndim):
...
@@ -385,102 +388,212 @@ cdef tuple _unellipsify(object index, int ndim):
if
nslices
:
if
nslices
:
result
.
extend
([
slice
(
None
)]
*
nslices
)
result
.
extend
([
slice
(
None
)]
*
nslices
)
for
idx
in
tup
:
return
have_slices
or
nslices
,
tuple
(
result
)
if
isinstance
(
idx
,
slice
):
return
True
,
tup
return
False
,
tup
#
### Slicing a memoryview
#
@
cname
(
'__pyx_pybuffer_slice'
)
@
cname
(
'__pyx_memview_slice'
)
cdef
memoryview
pybuffer_slice
(
memoryview
memview
,
object
indices
):
cdef
memoryview
memview_slice
(
memoryview
memview
,
object
indices
):
cdef
Py_ssize_t
idx
,
dim
,
new_dim
=
0
,
suboffset_dim
=
-
1
cdef
int
new_ndim
=
0
,
suboffset_dim
=
-
1
,
dim
cdef
Py_ssize_t
shape
,
stride
cdef
bint
negative_step
cdef
bint
negative_step
cdef
int
new_ndim
=
0
cdef
{{
memviewslice_name
}}
dst
,
src
cdef
{{
memviewslice_name
}}
dst
cdef
{{
memviewslice_name
}}
*
p_src
for
dim
,
index
in
enumerate
(
indices
):
cdef
_memoryviewslice
memviewsliceobj
shape
=
memview
.
view
.
shape
[
dim
]
stride
=
memview
.
view
.
strides
[
dim
]
assert
memview
.
view
.
ndim
>
0
if
isinstance
(
memview
,
_memoryviewslice
):
memviewsliceobj
=
memview
p_src
=
&
memviewsliceobj
.
from_slice
else
:
create_slice
(
memview
,
&
src
)
p_src
=
&
src
# Note: don't use variable src at this point
# SubNote: we should be able to declare variables in blocks...
# memoryview_fromslice() will inc our dst slice
dst
.
memview
=
p_src
.
memview
dst
.
data
=
p_src
.
data
for
dim
,
index
in
enumerate
(
indices
):
if
PyIndex_Check
(
index
):
if
PyIndex_Check
(
index
):
idx
=
index
slice_memviewslice
(
p_src
,
&
dst
,
True
,
dim
,
new_ndim
,
&
suboffset_dim
,
if
idx
<
0
:
index
,
0
,
0
,
0
,
0
,
0
,
False
)
idx
+=
shape
if
not
0
<=
idx
<
shape
:
raise
IndexError
(
"Index out of bounds (axis %d)"
%
dim
)
else
:
else
:
# index is a slice
slice_memviewslice
(
p_src
,
&
dst
,
True
,
dim
,
new_ndim
,
&
suboffset_dim
,
index
.
start
or
0
,
index
.
stop
or
0
,
index
.
step
or
0
,
index
.
start
is
not
None
,
index
.
stop
is
not
None
,
index
.
step
is
not
None
,
True
)
new_ndim
+=
1
new_ndim
+=
1
start
,
stop
,
step
=
index
.
start
,
index
.
stop
,
index
.
step
if
isinstance
(
memview
,
_memoryviewslice
):
negative_step
=
step
and
step
<
0
return
memoryview_fromslice
(
&
dst
,
new_ndim
,
memviewsliceobj
.
to_object_func
,
memviewsliceobj
.
to_dtype_func
)
else
:
return
memoryview_fromslice
(
&
dst
,
new_ndim
,
NULL
,
NULL
)
# set some defaults
#
if
not
start
:
### Slicing in a single dimension of a memoryviewslice
if
negative_step
:
#
start
=
shape
-
1
else
:
start
=
0
if
not
stop
:
cdef
extern
from
"stdlib.h"
:
if
negative_step
:
void
abort
()
nogil
stop
=
-
1
else
:
cdef
extern
from
"stdio.h"
:
stop
=
shape
ctypedef
struct
FILE
FILE
*
stderr
int
fputs
(
char
*
s
,
FILE
*
stream
)
cdef
extern
from
"pystate.h"
:
void
PyThreadState_Get
()
nogil
# These are not actually nogil, but we check for the GIL before calling them
void
PyErr_SetString
(
PyObject
*
type
,
char
*
msg
)
nogil
PyObject
*
PyErr_Format
(
PyObject
*
exc
,
char
*
msg
,
...)
nogil
cdef
:
char
*
ERR_OOB
=
"Index out of bounds (axis %d)"
char
*
ERR_STEP
=
"Step must not be zero (axis %d)"
char
*
ERR_INDIRECT_GIL
=
(
"Cannot make indirect dimension %d disappear "
"through indexing, consider slicing with %d:%d"
)
char
*
ERR_INDIRECT_NOGIL
=
(
"Cannot make indirect dimension %d disappear "
"through indexing"
)
PyObject
*
exc
=
<
PyObject
*>
IndexError
@
cname
(
'__pyx_memoryview_slice_memviewslice'
)
cdef
char
*
slice_memviewslice
({{
memviewslice_name
}}
*
src
,
{{
memviewslice_name
}}
*
dst
,
bint
have_gil
,
int
dim
,
int
new_ndim
,
int
*
suboffset_dim
,
Py_ssize_t
start
,
Py_ssize_t
stop
,
Py_ssize_t
step
,
int
have_start
,
int
have_stop
,
int
have_step
,
bint
is_slice
)
nogil
except
*
:
"""
Create a new slice dst given slice src.
have_gil - if true, the GIL must be held and exceptions may be raised
dim - the current src dimension (indexing will make dimensions
disappear)
new_dim - the new dst dimension
suboffset_dim - pointer to a single int initialized to -1 to keep track of
where slicing offsets should be added
"""
# check our bounds
cdef
:
Py_ssize_t
shape
,
stride
,
suboffset
Py_ssize_t
new_shape
bint
negative_step
if
have_gil
:
# Assert the GIL
PyThreadState_Get
()
shape
=
src
.
shape
[
dim
]
stride
=
src
.
strides
[
dim
]
suboffset
=
src
.
suboffsets
[
dim
]
if
not
is_slice
:
# index is a normal integer-like index
if
start
<
0
:
start
+=
shape
if
not
0
<=
start
<
shape
:
if
have_gil
:
PyErr_Format
(
exc
,
ERR_OOB
,
dim
)
return
ERR_OOB
else
:
# index is a slice
negative_step
=
have_step
!=
0
and
step
<
0
if
have_step
and
step
==
0
:
if
have_gil
:
# ValueError might be more appropriate, but this will make it consistent
# with nogil slicing
PyErr_SetString
(
exc
,
ERR_STEP
)
return
ERR_STEP
# check our bounds and set defaults
if
have_start
:
if
start
<
0
:
if
start
<
0
:
start
+=
shape
start
+=
shape
if
start
<
0
:
if
start
<
0
:
start
=
0
start
=
0
elif
start
>=
shape
:
elif
start
>=
shape
:
if
negative_step
:
start
=
shape
-
1
else
:
start
=
shape
else
:
if
negative_step
:
start
=
shape
-
1
start
=
shape
-
1
else
:
start
=
0
if
have_stop
:
if
stop
<
0
:
if
stop
<
0
:
stop
+=
shape
stop
+=
shape
if
stop
<
0
:
if
stop
<
0
:
stop
=
0
stop
=
0
elif
stop
>
shape
:
elif
stop
>
shape
:
stop
=
shape
stop
=
shape
else
:
if
negative_step
:
stop
=
-
1
else
:
stop
=
shape
step
=
step
or
1
if
not
have_step
:
step
=
1
# shape/strides/suboffsets
# len = ceil( (stop - start) / step )
dst
.
strides
[
new_dim
]
=
stride
*
step
with
cython
.
cdivision
(
True
):
dst
.
shape
[
new_dim
]
=
(
stop
-
start
)
/
step
new_shape
=
(
stop
-
start
)
//
step
if
(
stop
-
start
)
%
step
:
dst
.
shape
[
new_dim
]
+=
1
dst
.
suboffsets
[
new_dim
]
=
memview
.
view
.
suboffsets
[
dim
]
# set this for the slicing offset
if
(
stop
-
start
)
%
step
:
if
negative_step
:
new_shape
+=
1
idx
=
stop
else
:
idx
=
start
# Add the slicing or idexing offsets to the right suboffset or base data *
if
new_shape
<
0
:
if
suboffset_dim
<
0
:
new_shape
=
0
dst
.
data
+=
idx
*
stride
else
:
dst
.
suboffsets
[
suboffset_dim
]
+=
idx
*
stride
if
memview
.
view
.
suboffsets
[
dim
]:
# shape/strides/suboffsets
if
PyIndex_Check
(
index
):
dst
.
strides
[
new_ndim
]
=
stride
*
step
raise
IndexError
(
dst
.
shape
[
new_ndim
]
=
new_shape
"Cannot make indirect dimension %d disappear through "
dst
.
suboffsets
[
new_ndim
]
=
suboffset
"indexing, consider slicing with %d:%d"
%
(
dim
,
idx
,
idx
+
1
))
suboffset_dim
=
new_dim
cdef
_memoryviewslice
memviewsliceobj
# Add the slicing or idexing offsets to the right suboffset or base data *
if
isinstance
(
memview
,
_memoryviewslice
):
if
suboffset_dim
[
0
]
<
0
:
memviewsliceobj
=
memview
dst
.
data
+=
start
*
stride
return
memoryview_fromslice
(
&
dst
,
new_dim
,
memviewsliceobj
.
to_object_func
,
memviewsliceobj
.
to_dtype_func
)
else
:
else
:
return
memoryview_fromslice
(
&
dst
,
new_dim
,
NULL
,
NULL
)
dst
.
suboffsets
[
suboffset_dim
[
0
]]
+=
start
*
stride
if
suboffset
>=
0
:
if
not
is_slice
:
if
have_gil
:
PyErr_Format
(
exc
,
ERR_INDIRECT_GIL
,
dim
,
start
,
start
+
1
)
return
ERR_INDIRECT_NOGIL
else
:
suboffset_dim
[
0
]
=
new_ndim
return
NULL
#
### Index a memoryview
#
@
cname
(
'__pyx_pybuffer_index'
)
@
cname
(
'__pyx_pybuffer_index'
)
cdef
char
*
pybuffer_index
(
Py_buffer
*
view
,
char
*
bufp
,
Py_ssize_t
index
,
cdef
char
*
pybuffer_index
(
Py_buffer
*
view
,
char
*
bufp
,
Py_ssize_t
index
,
int
dim
)
except
NULL
:
int
dim
)
except
NULL
:
...
@@ -511,13 +624,16 @@ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
...
@@ -511,13 +624,16 @@ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
return
resultp
return
resultp
#
### Creating new memoryview objects from slices and memoryviews
#
@
cname
(
'__pyx_memoryviewslice'
)
@
cname
(
'__pyx_memoryviewslice'
)
cdef
class
_memoryviewslice
(
memoryview
):
cdef
class
_memoryviewslice
(
memoryview
):
"Internal class for passing memory
view slices to Python"
"Internal class for passing memoryview slices to Python"
# We need this to keep our shape/strides/suboffset pointers valid
# We need this to keep our shape/strides/suboffset pointers valid
cdef
{{
memviewslice_name
}}
from_slice
cdef
{{
memviewslice_name
}}
from_slice
# We need this only to print it's class
es
name
# We need this only to print it's class
'
name
cdef
object
from_object
cdef
object
from_object
cdef
object
(
*
to_object_func
)(
char
*
)
cdef
object
(
*
to_object_func
)(
char
*
)
...
@@ -550,9 +666,12 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
...
@@ -550,9 +666,12 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
object
(
*
to_object_func
)(
char
*
),
object
(
*
to_object_func
)(
char
*
),
int
(
*
to_dtype_func
)(
char
*
,
object
)
except
0
):
int
(
*
to_dtype_func
)(
char
*
,
object
)
except
0
):
cdef
_memoryviewslice
result
cdef
int
i
assert
0
<
ndim
<=
memviewslice
.
memview
.
view
.
ndim
,
(
ndim
,
memviewslice
.
memview
.
view
.
ndim
)
assert
0
<
ndim
<=
memviewslice
.
memview
.
view
.
ndim
,
(
ndim
,
memviewslice
.
memview
.
view
.
ndim
)
cdef
_memoryviewslice
result
=
_memoryviewslice
(
None
,
0
)
result
=
_memoryviewslice
(
None
,
0
)
result
.
from_slice
=
memviewslice
[
0
]
result
.
from_slice
=
memviewslice
[
0
]
__PYX_INC_MEMVIEW
(
memviewslice
,
1
)
__PYX_INC_MEMVIEW
(
memviewslice
,
1
)
...
@@ -560,30 +679,41 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
...
@@ -560,30 +679,41 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
result
.
from_object
=
<
object
>
memviewslice
.
memview
.
obj
result
.
from_object
=
<
object
>
memviewslice
.
memview
.
obj
result
.
view
=
memviewslice
.
memview
.
view
result
.
view
=
memviewslice
.
memview
.
view
result
.
view
.
shape
=
<
Py_ssize_t
*>
&
result
.
from_slice
.
shape
result
.
view
.
buf
=
<
void
*>
memviewslice
.
data
result
.
view
.
strides
=
<
Py_ssize_t
*>
result
.
from_slice
.
strides
result
.
view
.
suboffsets
=
<
Py_ssize_t
*>
&
result
.
from_slice
.
suboffsets
result
.
view
.
ndim
=
ndim
result
.
view
.
ndim
=
ndim
result
.
view
.
shape
=
<
Py_ssize_t
*>
result
.
from_slice
.
shape
result
.
view
.
strides
=
<
Py_ssize_t
*>
result
.
from_slice
.
strides
result
.
view
.
suboffsets
=
<
Py_ssize_t
*>
result
.
from_slice
.
suboffsets
result
.
view
.
len
=
result
.
view
.
itemsize
for
i
in
range
(
ndim
):
result
.
view
.
len
*=
result
.
view
.
shape
[
i
]
result
.
to_object_func
=
to_object_func
result
.
to_object_func
=
to_object_func
result
.
to_dtype_func
=
to_dtype_func
result
.
to_dtype_func
=
to_dtype_func
return
result
return
result
@
cname
(
'__pyx_memoryview_create_slice'
)
cdef
void
create_slice
(
memoryview
memview
,
{{
memviewslice_name
}}
*
dst
):
cdef
int
dim
dst
.
memview
=
<
__pyx_memoryview
*>
memview
dst
.
data
=
<
char
*>
memview
.
view
.
buf
for
dim
in
range
(
memview
.
view
.
ndim
):
dst
.
shape
[
dim
]
=
memview
.
view
.
shape
[
dim
]
dst
.
strides
[
dim
]
=
memview
.
view
.
strides
[
dim
]
dst
.
suboffsets
[
dim
]
=
memview
.
view
.
suboffsets
[
dim
]
@
cname
(
'__pyx_memoryview_copy'
)
cdef
memoryview_copy
(
memoryview
memview
):
cdef
memoryview_copy
(
memoryview
memview
):
cdef
{{
memviewslice_name
}}
memviewslice
cdef
{{
memviewslice_name
}}
memviewslice
cdef
int
dim
cdef
object
(
*
to_object_func
)(
char
*
)
cdef
object
(
*
to_object_func
)(
char
*
)
cdef
int
(
*
to_dtype_func
)(
char
*
,
object
)
except
0
cdef
int
(
*
to_dtype_func
)(
char
*
,
object
)
except
0
memviewslice
.
memview
=
<
__pyx_memoryview
*>
memview
create_slice
(
memview
,
&
memviewslice
)
memviewslice
.
data
=
<
char
*>
memview
.
view
.
buf
# Copy all of these as from_slice will
for
dim
in
range
(
memview
.
view
.
ndim
):
memviewslice
.
shape
[
dim
]
=
memview
.
view
.
shape
[
dim
]
memviewslice
.
strides
[
dim
]
=
memview
.
view
.
strides
[
dim
]
memviewslice
.
suboffsets
[
dim
]
=
memview
.
view
.
suboffsets
[
dim
]
if
isinstance
(
memview
,
_memoryviewslice
):
if
isinstance
(
memview
,
_memoryviewslice
):
to_object_func
=
(
<
_memoryviewslice
>
memview
).
to_object_func
to_object_func
=
(
<
_memoryviewslice
>
memview
).
to_object_func
...
...
Cython/Utility/MemoryView_C.c
View file @
b7e14b9a
...
@@ -284,7 +284,7 @@ static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice,
...
@@ -284,7 +284,7 @@ static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice,
if
(
!
memview
)
if
(
!
memview
)
return
;
/* allow uninitialized memoryview assignment */
return
;
/* allow uninitialized memoryview assignment */
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)"
,
memview
->
acquisition_count
,
lineno
);
memview
->
acquisition_count
,
lineno
);
...
@@ -463,4 +463,4 @@ int {{set_function}}(const char *itemp, PyObject *obj) {
...
@@ -463,4 +463,4 @@ int {{set_function}}(const char *itemp, PyObject *obj) {
Py_DECREF
(
*
(
PyObject
**
)
itemp
);
Py_DECREF
(
*
(
PyObject
**
)
itemp
);
*
(
PyObject
**
)
itemp
=
obj
;
*
(
PyObject
**
)
itemp
=
obj
;
return
1
;
return
1
;
}
}
\ No newline at end of file
tests/run/memoryview.pyx
View file @
b7e14b9a
...
@@ -588,40 +588,122 @@ def assign_temporary_to_object(object[:] mslice):
...
@@ -588,40 +588,122 @@ def assign_temporary_to_object(object[:] mslice):
buf
=
mslice
buf
=
mslice
buf
[
1
]
=
{
3
-
2
:
2
+
(
2
*
4
)
-
2
}
buf
[
1
]
=
{
3
-
2
:
2
+
(
2
*
4
)
-
2
}
def
test_slicing
(
arg
):
def
print_int_offsets
(
*
args
):
for
item
in
args
:
print
item
/
sizeof
(
int
),
print
def
test_generic_slicing
(
arg
):
"""
"""
Test simple slicing
Test simple slicing
>>> test_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
>>> test_
generic_
slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
acquired A
acquired A
3 9 2
(3, 9, 2)
1232 -44 4
308 -11 1
-1 -1 -1
-1 -1 -1
released A
released A
Test direct slicing, negative slice oob in dim 2
Test direct slicing, negative slice oob in dim 2
>>> test_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
>>> test_
generic_
slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
acquired A
acquired A
0 0 2
(0, 0, 2)
48 -12 4
12 -3 1
-1 -1 -1
-1 -1 -1
released A
released A
Test indirect slicing
Test indirect slicing
>>> L = [[range(k * 12 + j * 4, k * 12 + j * 4 + 4) for j in xrange(3)] for k in xrange(5)]
>>> 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)))
>>> test_
generic_
slicing(IntMockBuffer("A", L, shape=(5, 3, 4)))
acquired A
acquired A
2 0 2
(2, 0, 2)
8 -4 4
0 1 -1
0 0 -1
released A
released A
>>> stride1 = 21 * 14
>>> stride2 = 21
>>> L = [[range(k * stride1 + j * stride2, k * stride1 + j * stride2 + 21) for j in xrange(14)] for k in xrange(9)]
>>> test_generic_slicing(IntMockBuffer("A", L, shape=(9, 14, 21)))
acquired A
(3, 9, 2)
20 1 -1
released A
"""
"""
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
_a
=
arg
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
_a
=
arg
a
=
_a
a
=
_a
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
print
b
.
shape
[
0
],
b
.
shape
[
1
],
b
.
shape
[
2
]
print
b
.
shape
print
b
.
strides
[
0
],
b
.
strides
[
1
],
b
.
strides
[
2
]
if
b
.
suboffsets
[
0
]
<
0
:
print
b
.
suboffsets
[
0
],
b
.
suboffsets
[
1
],
b
.
suboffsets
[
2
]
print_int_offsets
(
*
b
.
strides
)
print_int_offsets
(
*
b
.
suboffsets
)
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
)
def
test_indirect_slicing
(
arg
):
"""
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_indirect_slicing(IntMockBuffer("A", L, shape=(5, 3, 4)))
acquired A
(5, 3, 2)
0 0 -1
58
released A
>>> stride1 = 21 * 14
>>> stride2 = 21
>>> L = [[range(k * stride1 + j * stride2, k * stride1 + j * stride2 + 21) for j in xrange(14)] for k in xrange(9)]
>>> test_indirect_slicing(IntMockBuffer("A", L, shape=(9, 14, 21)))
acquired A
(5, 14, 3)
0 16 -1
2412
released A
"""
cdef
int
[::
view
.
indirect
,
::
view
.
indirect
,
:]
_a
=
arg
a
=
_a
b
=
a
[
-
5
:,
...,
-
5
:
100
:
2
]
print
b
.
shape
print_int_offsets
(
*
b
.
suboffsets
)
print
b
[
4
,
2
,
1
]
def
test_direct_slicing
(
arg
):
"""
Fused types would be convenient to test this stuff!
Test simple slicing
>>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
acquired A
(3, 9, 2)
308 -11 1
-1 -1 -1
released A
Test direct slicing, negative slice oob in dim 2
>>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
acquired A
(0, 0, 2)
12 -3 1
-1 -1 -1
released A
"""
cdef
int
[:,
:,
:]
_a
=
arg
a
=
_a
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
print
b
.
shape
print_int_offsets
(
*
b
.
strides
)
print_int_offsets
(
*
b
.
suboffsets
)
cdef
int
i
,
j
,
k
cdef
int
i
,
j
,
k
for
i
in
range
(
b
.
shape
[
0
]):
for
i
in
range
(
b
.
shape
[
0
]):
...
@@ -631,13 +713,14 @@ def test_slicing(arg):
...
@@ -631,13 +713,14 @@ def test_slicing(arg):
itemB
=
b
[
i
,
j
,
k
]
itemB
=
b
[
i
,
j
,
k
]
assert
itemA
==
itemB
,
(
i
,
j
,
k
,
itemA
,
itemB
)
assert
itemA
==
itemB
,
(
i
,
j
,
k
,
itemA
,
itemB
)
def
test_slicing_and_indexing
(
arg
):
def
test_slicing_and_indexing
(
arg
):
"""
"""
>>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5))
>>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5))
>>> test_slicing_and_indexing(a)
>>> test_slicing_and_indexing(a)
acquired A
acquired A
5 2
(5, 2)
60 8
15 2
126 113
126 113
[111]
[111]
released A
released A
...
@@ -648,8 +731,8 @@ def test_slicing_and_indexing(arg):
...
@@ -648,8 +731,8 @@ def test_slicing_and_indexing(arg):
c
=
b
[
4
:
1
:
-
1
,
::
-
1
]
c
=
b
[
4
:
1
:
-
1
,
::
-
1
]
d
=
c
[
2
,
1
:
2
]
d
=
c
[
2
,
1
:
2
]
print
b
.
shape
[
0
],
b
.
shape
[
1
]
print
b
.
shape
print
b
.
strides
[
0
],
b
.
strides
[
1
]
print
_int_offsets
(
*
b
.
strides
)
cdef
int
i
,
j
cdef
int
i
,
j
for
i
in
range
(
b
.
shape
[
0
]):
for
i
in
range
(
b
.
shape
[
0
]):
...
@@ -659,4 +742,14 @@ def test_slicing_and_indexing(arg):
...
@@ -659,4 +742,14 @@ def test_slicing_and_indexing(arg):
assert
itemA
==
itemB
,
(
i
,
j
,
itemA
,
itemB
)
assert
itemA
==
itemB
,
(
i
,
j
,
itemA
,
itemB
)
print
c
[
1
,
1
],
c
[
2
,
0
]
print
c
[
1
,
1
],
c
[
2
,
0
]
print
[
d
[
i
]
for
i
in
range
(
d
.
shape
[
0
])]
print
[
d
[
i
]
for
i
in
range
(
d
.
shape
[
0
])]
\ No newline at end of file
def
test_oob
():
"""
>>> test_oob()
Traceback (most recent call last):
...
IndexError: Index out of bounds (axis 1)
"""
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
print
a
[:,
20
]
tests/run/memslice.pyx
View file @
b7e14b9a
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
cimport
cython
from
cython
cimport
view
from
cython
cimport
view
__test__
=
{}
__test__
=
{}
...
@@ -1158,40 +1159,127 @@ def test_cdef_function2():
...
@@ -1158,40 +1159,127 @@ def test_cdef_function2():
cdef
_function2
(
global_A
,
global_B
)
cdef
_function2
(
global_A
,
global_B
)
def
print_int_offsets
(
*
args
):
for
item
in
args
:
print
item
/
sizeof
(
int
),
print
@
testcase
@
testcase
def
test_slicing
(
arg
):
def
test_
generic_
slicing
(
arg
):
"""
"""
Test simple slicing
Test simple slicing
>>> test_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
>>> test_
generic_
slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
acquired A
acquired A
3 9 2
3 9 2
1232 -44 4
308 -11 1
-1 -1 -1
-1 -1 -1
released A
released A
Test direct slicing, negative slice oob in dim 2
Test direct slicing, negative slice oob in dim 2
>>> test_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
>>> test_
generic_
slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
acquired A
acquired A
0 0 2
0 0 2
48 -12 4
12 -3 1
-1 -1 -1
-1 -1 -1
released A
released A
Test indirect slicing
Test indirect slicing
>>> L = [[range(k * 12 + j * 4, k * 12 + j * 4 + 4) for j in xrange(3)] for k in xrange(5)]
>>> 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)))
>>> test_
generic_
slicing(IntMockBuffer("A", L, shape=(5, 3, 4)))
acquired A
acquired A
2 0 2
2 0 2
8 -4 4
0 1 -1
0 0 -1
released A
>>> stride1 = 21 * 14
>>> stride2 = 21
>>> L = [[range(k * stride1 + j * stride2, k * stride1 + j * stride2 + 21) for j in xrange(14)] for k in xrange(9)]
>>> test_generic_slicing(IntMockBuffer("A", L, shape=(9, 14, 21)))
acquired A
3 9 2
20 1 -1
released A
released A
"""
"""
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
a
=
arg
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
a
=
arg
cdef
int
[::
view
.
generic
,
::
view
.
generic
,
:]
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
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
.
shape
[
0
],
b
.
shape
[
1
],
b
.
shape
[
2
]
print
b
.
strides
[
0
],
b
.
strides
[
1
],
b
.
strides
[
2
]
if
b
.
suboffsets
[
0
]
<
0
:
print
b
.
suboffsets
[
0
],
b
.
suboffsets
[
1
],
b
.
suboffsets
[
2
]
print_int_offsets
(
b
.
strides
[
0
],
b
.
strides
[
1
],
b
.
strides
[
2
])
print_int_offsets
(
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_indirect_slicing
(
arg
):
"""
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_indirect_slicing(IntMockBuffer("A", L, shape=(5, 3, 4)))
acquired A
5 3 2
0 0 -1
58
56
released A
>>> stride1 = 21 * 14
>>> stride2 = 21
>>> L = [[range(k * stride1 + j * stride2, k * stride1 + j * stride2 + 21) for j in xrange(14)] for k in xrange(9)]
>>> test_indirect_slicing(IntMockBuffer("A", L, shape=(9, 14, 21)))
acquired A
5 14 3
0 16 -1
2412
2410
released A
"""
cdef
int
[::
view
.
indirect
,
::
view
.
indirect
,
:]
a
=
arg
cdef
int
[::
view
.
indirect
,
::
view
.
indirect
,
:]
b
=
a
[
-
5
:,
...,
-
5
:
100
:
2
]
cdef
int
[::
view
.
indirect
,
::
view
.
indirect
]
c
=
b
[...,
0
]
print
b
.
shape
[
0
],
b
.
shape
[
1
],
b
.
shape
[
2
]
print_int_offsets
(
b
.
suboffsets
[
0
],
b
.
suboffsets
[
1
],
b
.
suboffsets
[
2
])
print
b
[
4
,
2
,
1
]
print
c
[
4
,
2
]
@
testcase
def
test_direct_slicing
(
arg
):
"""
Fused types would be convenient to test this stuff!
Test simple slicing
>>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
acquired A
3 9 2
308 -11 1
-1 -1 -1
released A
Test direct slicing, negative slice oob in dim 2
>>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
acquired A
0 0 2
12 -3 1
-1 -1 -1
released A
"""
cdef
int
[:,
:,
::
1
]
a
=
arg
cdef
int
[:,
:,
:]
b
=
a
[
2
:
8
:
2
,
-
4
:
1
:
-
1
,
1
:
3
]
print
b
.
shape
[
0
],
b
.
shape
[
1
],
b
.
shape
[
2
]
print_int_offsets
(
b
.
strides
[
0
],
b
.
strides
[
1
],
b
.
strides
[
2
])
print_int_offsets
(
b
.
suboffsets
[
0
],
b
.
suboffsets
[
1
],
b
.
suboffsets
[
2
])
cdef
int
i
,
j
,
k
cdef
int
i
,
j
,
k
for
i
in
range
(
b
.
shape
[
0
]):
for
i
in
range
(
b
.
shape
[
0
]):
...
@@ -1208,7 +1296,7 @@ def test_slicing_and_indexing(arg):
...
@@ -1208,7 +1296,7 @@ def test_slicing_and_indexing(arg):
>>> test_slicing_and_indexing(a)
>>> test_slicing_and_indexing(a)
acquired A
acquired A
5 2
5 2
60 8
15 2
126 113
126 113
[111]
[111]
released A
released A
...
@@ -1219,7 +1307,7 @@ def test_slicing_and_indexing(arg):
...
@@ -1219,7 +1307,7 @@ def test_slicing_and_indexing(arg):
cdef
int
[:]
d
=
c
[
2
,
1
:
2
]
cdef
int
[:]
d
=
c
[
2
,
1
:
2
]
print
b
.
shape
[
0
],
b
.
shape
[
1
]
print
b
.
shape
[
0
],
b
.
shape
[
1
]
print
b
.
strides
[
0
],
b
.
strides
[
1
]
print
_int_offsets
(
b
.
strides
[
0
],
b
.
strides
[
1
])
cdef
int
i
,
j
cdef
int
i
,
j
for
i
in
range
(
b
.
shape
[
0
]):
for
i
in
range
(
b
.
shape
[
0
]):
...
@@ -1229,4 +1317,16 @@ def test_slicing_and_indexing(arg):
...
@@ -1229,4 +1317,16 @@ def test_slicing_and_indexing(arg):
assert
itemA
==
itemB
,
(
i
,
j
,
itemA
,
itemB
)
assert
itemA
==
itemB
,
(
i
,
j
,
itemA
,
itemB
)
print
c
[
1
,
1
],
c
[
2
,
0
]
print
c
[
1
,
1
],
c
[
2
,
0
]
print
[
d
[
i
]
for
i
in
range
(
d
.
shape
[
0
])]
print
[
d
[
i
]
for
i
in
range
(
d
.
shape
[
0
])]
\ No newline at end of file
@
testcase
def
test_oob
():
"""
>>> test_oob()
Traceback (most recent call last):
...
IndexError: Index out of bounds (axis 1)
"""
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
print
a
[:,
20
]
tests/run/numpy_memoryview.pyx
View file @
b7e14b9a
...
@@ -6,13 +6,15 @@ Test slicing for memoryviews and memoryviewslices
...
@@ -6,13 +6,15 @@ Test slicing for memoryviews and memoryviewslices
"""
"""
cimport
numpy
as
np
cimport
numpy
as
np
import
numpy
import
numpy
as
np
ctypedef
np
.
int32_t
dtype_t
def
get_array
():
def
get_array
():
# We need to type our array to get a __pyx_get_buffer() that typechecks
# We need to type our array to get a __pyx_get_buffer() that typechecks
# for np.ndarray and calls __getbuffer__ in numpy.pxd
# for np.ndarray and calls __getbuffer__ in numpy.pxd
cdef
np
.
ndarray
[
in
t
,
ndim
=
3
]
a
cdef
np
.
ndarray
[
dtype_
t
,
ndim
=
3
]
a
a
=
n
umpy
.
arange
(
8
*
14
*
11
).
reshape
(
8
,
14
,
11
)
a
=
n
p
.
arange
(
8
*
14
*
11
,
dtype
=
np
.
int32
).
reshape
(
8
,
14
,
11
)
return
a
return
a
a
=
get_array
()
a
=
get_array
()
...
@@ -31,11 +33,11 @@ def test_partial_slicing(array):
...
@@ -31,11 +33,11 @@ def test_partial_slicing(array):
"""
"""
>>> test_partial_slicing(a)
>>> test_partial_slicing(a)
"""
"""
cdef
in
t
[:,
:,
:]
a
=
array
cdef
dtype_
t
[:,
:,
:]
a
=
array
obj
=
array
[
4
]
obj
=
array
[
4
]
cdef
in
t
[:,
:]
b
=
a
[
4
,
:]
cdef
dtype_
t
[:,
:]
b
=
a
[
4
,
:]
cdef
in
t
[:,
:]
c
=
a
[
4
]
cdef
dtype_
t
[:,
:]
c
=
a
[
4
]
ae
(
b
.
shape
[
0
],
c
.
shape
[
0
],
obj
.
shape
[
0
])
ae
(
b
.
shape
[
0
],
c
.
shape
[
0
],
obj
.
shape
[
0
])
ae
(
b
.
shape
[
1
],
c
.
shape
[
1
],
obj
.
shape
[
1
])
ae
(
b
.
shape
[
1
],
c
.
shape
[
1
],
obj
.
shape
[
1
])
...
@@ -46,15 +48,15 @@ def test_ellipsis(array):
...
@@ -46,15 +48,15 @@ def test_ellipsis(array):
"""
"""
>>> test_ellipsis(a)
>>> test_ellipsis(a)
"""
"""
cdef
in
t
[:,
:,
:]
a
=
array
cdef
dtype_
t
[:,
:,
:]
a
=
array
cdef
in
t
[:,
:]
b
=
a
[...,
4
]
cdef
dtype_
t
[:,
:]
b
=
a
[...,
4
]
b_obj
=
array
[...,
4
]
b_obj
=
array
[...,
4
]
cdef
in
t
[:,
:]
c
=
a
[
4
,
...]
cdef
dtype_
t
[:,
:]
c
=
a
[
4
,
...]
c_obj
=
array
[
4
,
...]
c_obj
=
array
[
4
,
...]
cdef
in
t
[:,
:]
d
=
a
[
2
:
8
,
...,
2
]
cdef
dtype_
t
[:,
:]
d
=
a
[
2
:
8
,
...,
2
]
d_obj
=
array
[
2
:
8
,
...,
2
]
d_obj
=
array
[
2
:
8
,
...,
2
]
ae
(
tuple
([
b
.
shape
[
i
]
for
i
in
range
(
2
)]),
b_obj
.
shape
)
ae
(
tuple
([
b
.
shape
[
i
]
for
i
in
range
(
2
)]),
b_obj
.
shape
)
...
@@ -75,7 +77,7 @@ def test_ellipsis(array):
...
@@ -75,7 +77,7 @@ def test_ellipsis(array):
for
j
in
range
(
d
.
shape
[
1
]):
for
j
in
range
(
d
.
shape
[
1
]):
ae
(
d
[
i
,
j
],
d_obj
[
i
,
j
])
ae
(
d
[
i
,
j
],
d_obj
[
i
,
j
])
cdef
in
t
[:]
e
=
a
[...,
5
,
6
]
cdef
dtype_
t
[:]
e
=
a
[...,
5
,
6
]
e_obj
=
array
[...,
5
,
6
]
e_obj
=
array
[...,
5
,
6
]
ae
(
e
.
shape
[
0
],
e_obj
.
shape
[
0
])
ae
(
e
.
shape
[
0
],
e_obj
.
shape
[
0
])
ae
(
e
.
strides
[
0
],
e_obj
.
strides
[
0
])
ae
(
e
.
strides
[
0
],
e_obj
.
strides
[
0
])
...
@@ -88,7 +90,7 @@ def test_partial_slicing_memoryview(array):
...
@@ -88,7 +90,7 @@ def test_partial_slicing_memoryview(array):
"""
"""
>>> test_partial_slicing_memoryview(a)
>>> test_partial_slicing_memoryview(a)
"""
"""
cdef
in
t
[:,
:,
:]
_a
=
array
cdef
dtype_
t
[:,
:,
:]
_a
=
array
a
=
_a
a
=
_a
obj
=
array
[
4
]
obj
=
array
[
4
]
...
@@ -104,7 +106,7 @@ def test_ellipsis_memoryview(array):
...
@@ -104,7 +106,7 @@ def test_ellipsis_memoryview(array):
"""
"""
>>> test_ellipsis_memoryview(a)
>>> test_ellipsis_memoryview(a)
"""
"""
cdef
in
t
[:,
:,
:]
_a
=
array
cdef
dtype_
t
[:,
:,
:]
_a
=
array
a
=
_a
a
=
_a
b
=
a
[...,
4
]
b
=
a
[...,
4
]
...
@@ -137,4 +139,4 @@ def test_ellipsis_memoryview(array):
...
@@ -137,4 +139,4 @@ def test_ellipsis_memoryview(array):
e
=
a
[...,
5
,
6
]
e
=
a
[...,
5
,
6
]
e_obj
=
array
[...,
5
,
6
]
e_obj
=
array
[...,
5
,
6
]
ae
(
e
.
shape
[
0
],
e_obj
.
shape
[
0
])
ae
(
e
.
shape
[
0
],
e_obj
.
shape
[
0
])
ae
(
e
.
strides
[
0
],
e_obj
.
strides
[
0
])
ae
(
e
.
strides
[
0
],
e_obj
.
strides
[
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