Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
b9ffa8b7
Commit
b9ffa8b7
authored
Sep 23, 2008
by
Dag Sverre Seljebotn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Buffers: negative_indices option
parent
83198d1b
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
56 additions
and
8 deletions
+56
-8
Cython/Compiler/Buffer.py
Cython/Compiler/Buffer.py
+15
-6
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+2
-1
tests/run/bufaccess.pyx
tests/run/bufaccess.pyx
+39
-1
No files found.
Cython/Compiler/Buffer.py
View file @
b9ffa8b7
...
@@ -113,8 +113,8 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
...
@@ -113,8 +113,8 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
#
#
# Analysis
# Analysis
#
#
buffer_options
=
(
"dtype"
,
"ndim"
,
"mode"
)
# ordered!
buffer_options
=
(
"dtype"
,
"ndim"
,
"mode"
,
"negative_indices"
)
# ordered!
buffer_defaults
=
{
"ndim"
:
1
,
"mode"
:
"full"
}
buffer_defaults
=
{
"ndim"
:
1
,
"mode"
:
"full"
,
"negative_indices"
:
True
}
buffer_positional_options_count
=
1
# anything beyond this needs keyword argument
buffer_positional_options_count
=
1
# anything beyond this needs keyword argument
ERR_BUF_OPTION_UNKNOWN
=
'"%s" is not a buffer option'
ERR_BUF_OPTION_UNKNOWN
=
'"%s" is not a buffer option'
...
@@ -124,6 +124,7 @@ ERR_BUF_MISSING = '"%s" missing'
...
@@ -124,6 +124,7 @@ ERR_BUF_MISSING = '"%s" missing'
ERR_BUF_MODE
=
'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)'
ERR_BUF_MODE
=
'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)'
ERR_BUF_NDIM
=
'ndim must be a non-negative integer'
ERR_BUF_NDIM
=
'ndim must be a non-negative integer'
ERR_BUF_DTYPE
=
'dtype must be "object", numeric type or a struct'
ERR_BUF_DTYPE
=
'dtype must be "object", numeric type or a struct'
ERR_BUF_NEGATIVE_INDICES
=
'negative_indices must be a boolean'
def
analyse_buffer_options
(
globalpos
,
env
,
posargs
,
dictargs
,
defaults
=
None
,
need_complete
=
True
):
def
analyse_buffer_options
(
globalpos
,
env
,
posargs
,
dictargs
,
defaults
=
None
,
need_complete
=
True
):
"""
"""
...
@@ -178,6 +179,10 @@ def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, nee
...
@@ -178,6 +179,10 @@ def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, nee
if
mode
and
not
(
mode
in
(
'full'
,
'strided'
,
'c'
,
'fortran'
)):
if
mode
and
not
(
mode
in
(
'full'
,
'strided'
,
'c'
,
'fortran'
)):
raise
CompileError
(
globalpos
,
ERR_BUF_MODE
)
raise
CompileError
(
globalpos
,
ERR_BUF_MODE
)
negative_indices
=
options
.
get
(
"negative_indices"
)
if
mode
and
not
isinstance
(
negative_indices
,
bool
):
raise
CompileError
(
globalpos
,
ERR_BUF_NEGATIVE_INDICES
)
return
options
return
options
...
@@ -336,6 +341,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
...
@@ -336,6 +341,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
"""
"""
bufaux
=
entry
.
buffer_aux
bufaux
=
entry
.
buffer_aux
bufstruct
=
bufaux
.
buffer_info_var
.
cname
bufstruct
=
bufaux
.
buffer_info_var
.
cname
negative_indices
=
entry
.
type
.
negative_indices
if
options
[
'boundscheck'
]:
if
options
[
'boundscheck'
]:
# Check bounds and fix negative indices.
# Check bounds and fix negative indices.
...
@@ -349,9 +355,12 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
...
@@ -349,9 +355,12 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
if
signed
!=
0
:
if
signed
!=
0
:
# not unsigned, deal with negative index
# not unsigned, deal with negative index
code
.
putln
(
"if (%s < 0) {"
%
cname
)
code
.
putln
(
"if (%s < 0) {"
%
cname
)
if
negative_indices
:
code
.
putln
(
"%s += %s;"
%
(
cname
,
shape
.
cname
))
code
.
putln
(
"%s += %s;"
%
(
cname
,
shape
.
cname
))
code
.
putln
(
"if (%s) %s = %d;"
%
(
code
.
putln
(
"if (%s) %s = %d;"
%
(
code
.
unlikely
(
"%s < 0"
%
cname
),
tmp_cname
,
dim
))
code
.
unlikely
(
"%s < 0"
%
cname
),
tmp_cname
,
dim
))
else
:
code
.
putln
(
"%s = %d;"
%
(
tmp_cname
,
dim
))
code
.
put
(
"} else "
)
code
.
put
(
"} else "
)
# check bounds in positive direction
# check bounds in positive direction
code
.
putln
(
"if (%s) %s = %d;"
%
(
code
.
putln
(
"if (%s) %s = %d;"
%
(
...
@@ -364,7 +373,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
...
@@ -364,7 +373,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
code
.
putln
(
code
.
error_goto
(
pos
))
code
.
putln
(
code
.
error_goto
(
pos
))
code
.
end_block
()
code
.
end_block
()
code
.
funcstate
.
release_temp
(
tmp_cname
)
code
.
funcstate
.
release_temp
(
tmp_cname
)
el
se
:
el
if
negative_indices
:
# Only fix negative indices.
# Only fix negative indices.
for
signed
,
cname
,
shape
in
zip
(
index_signeds
,
index_cnames
,
for
signed
,
cname
,
shape
in
zip
(
index_signeds
,
index_cnames
,
bufaux
.
shapevars
):
bufaux
.
shapevars
):
...
...
Cython/Compiler/PyrexTypes.py
View file @
b9ffa8b7
...
@@ -205,12 +205,13 @@ class BufferType(BaseType):
...
@@ -205,12 +205,13 @@ class BufferType(BaseType):
is_buffer
=
1
is_buffer
=
1
writable
=
True
writable
=
True
def
__init__
(
self
,
base
,
dtype
,
ndim
,
mode
):
def
__init__
(
self
,
base
,
dtype
,
ndim
,
mode
,
negative_indices
):
self
.
base
=
base
self
.
base
=
base
self
.
dtype
=
dtype
self
.
dtype
=
dtype
self
.
ndim
=
ndim
self
.
ndim
=
ndim
self
.
buffer_ptr_type
=
CPtrType
(
dtype
)
self
.
buffer_ptr_type
=
CPtrType
(
dtype
)
self
.
mode
=
mode
self
.
mode
=
mode
self
.
negative_indices
=
negative_indices
def
as_argument_type
(
self
):
def
as_argument_type
(
self
):
return
self
return
self
...
...
tests/run/bufaccess.pyx
View file @
b9ffa8b7
...
@@ -473,6 +473,25 @@ def list_comprehension(object[int] buf, len):
...
@@ -473,6 +473,25 @@ def list_comprehension(object[int] buf, len):
cdef
int
i
cdef
int
i
print
u"|"
.
join
([
unicode
(
buf
[
i
])
for
i
in
range
(
len
)])
print
u"|"
.
join
([
unicode
(
buf
[
i
])
for
i
in
range
(
len
)])
#
# The negative_indices buffer option
#
@
testcase
def
no_negative_indices
(
object
[
int
,
negative_indices
=
False
]
buf
,
int
idx
):
"""
The most interesting thing here is to inspect the C source and
make sure optimal code is produced.
>>> A = IntMockBuffer(None, range(6))
>>> no_negative_indices(A, 3)
3
>>> no_negative_indices(A, -1)
Traceback (most recent call last):
...
IndexError: Out of bounds on buffer access (axis 0)
"""
return
buf
[
idx
]
#
#
# Buffer type mismatch examples. Varying the type and access
# Buffer type mismatch examples. Varying the type and access
# method simultaneously, the odds of an interaction is virtually
# method simultaneously, the odds of an interaction is virtually
...
@@ -635,7 +654,7 @@ def safe_get(object[int] buf, int idx):
...
@@ -635,7 +654,7 @@ def safe_get(object[int] buf, int idx):
return
buf
[
idx
]
return
buf
[
idx
]
@
testcase
@
testcase
@
cython
.
boundscheck
(
False
)
@
cython
.
boundscheck
(
False
)
# outer decorators should take precedence
@
cython
.
boundscheck
(
True
)
@
cython
.
boundscheck
(
True
)
def
unsafe_get
(
object
[
int
]
buf
,
int
idx
):
def
unsafe_get
(
object
[
int
]
buf
,
int
idx
):
"""
"""
...
@@ -650,6 +669,18 @@ def unsafe_get(object[int] buf, int idx):
...
@@ -650,6 +669,18 @@ def unsafe_get(object[int] buf, int idx):
"""
"""
return
buf
[
idx
]
return
buf
[
idx
]
@
testcase
@
cython
.
boundscheck
(
False
)
def
unsafe_get_nonegative
(
object
[
int
,
negative_indices
=
False
]
buf
,
int
idx
):
"""
Also inspect the C source to see that it is optimal...
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
>>> unsafe_get_nonegative(A, -2)
3
"""
return
buf
[
idx
]
@
testcase
@
testcase
def
mixed_get
(
object
[
int
]
buf
,
int
unsafe_idx
,
int
safe_idx
):
def
mixed_get
(
object
[
int
]
buf
,
int
unsafe_idx
,
int
safe_idx
):
"""
"""
...
@@ -1077,6 +1108,13 @@ cdef class IntMockBuffer(MockBuffer):
...
@@ -1077,6 +1108,13 @@ cdef class IntMockBuffer(MockBuffer):
cdef
get_itemsize
(
self
):
return
sizeof
(
int
)
cdef
get_itemsize
(
self
):
return
sizeof
(
int
)
cdef
get_default_format
(
self
):
return
b"@i"
cdef
get_default_format
(
self
):
return
b"@i"
cdef
class
UnsignedIntMockBuffer
(
MockBuffer
):
cdef
int
write
(
self
,
char
*
buf
,
object
value
)
except
-
1
:
(
<
unsigned
int
*>
buf
)[
0
]
=
<
unsigned
int
>
value
return
0
cdef
get_itemsize
(
self
):
return
sizeof
(
unsigned
int
)
cdef
get_default_format
(
self
):
return
b"@I"
cdef
class
ShortMockBuffer
(
MockBuffer
):
cdef
class
ShortMockBuffer
(
MockBuffer
):
cdef
int
write
(
self
,
char
*
buf
,
object
value
)
except
-
1
:
cdef
int
write
(
self
,
char
*
buf
,
object
value
)
except
-
1
:
(
<
short
*>
buf
)[
0
]
=
<
short
>
value
(
<
short
*>
buf
)[
0
]
=
<
short
>
value
...
...
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