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
308c3516
Commit
308c3516
authored
Aug 10, 2009
by
Kurt Smith
Committed by
Mark Florisson
Sep 30, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
memviewslice copy implementation.
parent
daa49dd4
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
262 additions
and
39 deletions
+262
-39
Cython/Compiler/CythonScope.py
Cython/Compiler/CythonScope.py
+9
-6
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+173
-6
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+80
-27
No files found.
Cython/Compiler/CythonScope.py
View file @
308c3516
...
...
@@ -260,13 +260,16 @@ cdef extern from *:
cdef class memoryview(object):
cdef object obj
cdef Py_buffer view
cdef int gotbuf_flag
def __cinit__(memoryview self, object obj, int flags):
__Pyx_GetBuffer(obj, &self.view, flags)
self.obj = obj
__Pyx_GetBuffer(self.obj, &self.view, flags)
def __dealloc__(memoryview self):
self.obj = None
__Pyx_ReleaseBuffer(&self.view)
cdef memoryview memoryview_cwrapper(object o, int flags):
...
...
@@ -298,7 +301,7 @@ cdef class array:
Py_ssize_t itemsize
str mode
def __cinit__(array self, tuple shape, Py_ssize_t itemsize, char *format, mode="c"):
def __cinit__(array self, tuple shape, Py_ssize_t itemsize, char *format,
str
mode="c"):
self.ndim = len(shape)
self.itemsize = itemsize
...
...
@@ -328,7 +331,7 @@ cdef class array:
idx += 1
assert idx == self.ndim
if mode == "f
ortran
":
if mode == "f":
idx = 0; stride = 1
for dim in shape:
self.strides[idx] = stride
...
...
@@ -347,7 +350,7 @@ cdef class array:
assert idx == -1
self.len = stride * self.itemsize
else:
raise ValueError("Invalid mode, expected 'c' or 'f
ortran
', got %s" % mode)
raise ValueError("Invalid mode, expected 'c' or 'f', got %s" % mode)
self.mode = mode
...
...
@@ -360,7 +363,7 @@ cdef class array:
cdef int bufmode = -1
if self.mode == b"c":
bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
elif self.mode == b"f
ortran
":
elif self.mode == b"f":
bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
if not (flags & bufmode):
raise ValueError("Can only create a buffer that is contiguous in memory.")
...
...
@@ -393,7 +396,7 @@ cdef class array:
self.format = NULL
self.itemsize = 0
cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char mode):
cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char
*
mode):
return array(shape, itemsize, format, mode)
'''
,
prefix
=
cyarray_prefix
)
Cython/Compiler/MemoryView.py
View file @
308c3516
...
...
@@ -69,6 +69,14 @@ def put_init_entry(mv_cname, code):
code
.
putln
(
"%s.data = NULL;"
%
mv_cname
)
code
.
putln
(
"%s.memview = NULL;"
%
mv_cname
)
def
mangle_dtype_name
(
dtype
):
# a dumb wrapper for now; move Buffer.mangle_dtype_name in here later?
import
Buffer
return
Buffer
.
mangle_dtype_name
(
dtype
)
def
axes_to_str
(
axes
):
return
""
.
join
([
access
[
0
]
+
packing
[
0
]
for
(
access
,
packing
)
in
axes
])
def
gen_acquire_memoryviewslice
(
rhs
,
lhs_type
,
lhs_is_cglobal
,
lhs_result
,
lhs_pos
,
code
):
# import MemoryView
assert
rhs
.
type
.
is_memoryviewslice
...
...
@@ -79,6 +87,7 @@ def gen_acquire_memoryviewslice(rhs, lhs_type, lhs_is_cglobal, lhs_result, lhs_p
else
:
rhstmp
=
code
.
funcstate
.
allocate_temp
(
lhs_type
,
manage_ref
=
False
)
code
.
putln
(
"%s = %s;"
%
(
rhstmp
,
rhs
.
result_as
(
lhs_type
)))
code
.
putln
(
code
.
error_goto_if_null
(
"%s.memview"
%
rhstmp
,
lhs_pos
))
if
not
rhs
.
result_in_temp
():
code
.
put_incref
(
"%s.memview"
%
rhstmp
,
cython_memoryview_ptr_type
)
...
...
@@ -184,6 +193,157 @@ def src_conforms_to_dst(src, dst):
return
True
def
get_copy_contents_name
(
from_mvs
,
to_mvs
):
dtype
=
from_mvs
.
dtype
assert
dtype
==
to_mvs
.
dtype
return
(
'__Pyx_BufferCopyContents_%s_%s_%s'
%
(
axes_to_str
(
from_mvs
.
axes
),
axes_to_str
(
to_mvs
.
axes
),
mangle_dtype_name
(
dtype
)))
copy_template
=
'''
static __Pyx_memviewslice %(copy_name)s(const __Pyx_memviewslice from_mvs) {
int i;
__Pyx_memviewslice new_mvs = {0, 0};
struct __pyx_obj_memoryview *from_memview = from_mvs.memview;
Py_buffer *buf = &from_memview->view;
PyObject *shape_tuple = 0;
PyObject *temp_int = 0;
struct __pyx_obj_array *array_obj = 0;
struct __pyx_obj_memoryview *memview_obj = 0;
char mode[] = "%(mode)s";
__Pyx_SetupRefcountContext("%(copy_name)s");
shape_tuple = PyTuple_New((Py_ssize_t)(buf->ndim));
if(unlikely(!shape_tuple)) {
goto fail;
}
__Pyx_GOTREF(shape_tuple);
for(i=0; i<buf->ndim; i++) {
temp_int = PyInt_FromLong(buf->shape[i]);
if(unlikely(!temp_int)) {
goto fail;
} else {
PyTuple_SET_ITEM(shape_tuple, i, temp_int);
}
}
array_obj = __pyx_cythonarray_array_cwrapper(shape_tuple, %(sizeof_dtype)s, buf->format, mode);
if (unlikely(!array_obj)) {
goto fail;
}
__Pyx_GOTREF(array_obj);
memview_obj = __pyx_viewaxis_memoryview_cwrapper((PyObject *)array_obj, %(contig_flag)s);
if (unlikely(!memview_obj)) {
goto fail;
}
/* initialize new_mvs */
if (unlikely(-1 == __Pyx_init_memviewslice(memview_obj, buf->ndim, &new_mvs))) {
PyErr_SetString(PyExc_RuntimeError,
"Could not initialize new memoryviewslice object.");
goto fail;
}
if (unlikely(-1 == %(copy_contents_name)s(&from_mvs, &new_mvs))) {
/* PyErr_SetString(PyExc_RuntimeError,
"Could not copy contents of memoryview slice."); */
goto fail;
}
goto no_fail;
fail:
__Pyx_XDECREF(new_mvs.memview); new_mvs.memview = 0;
new_mvs.data = 0;
no_fail:
__Pyx_XDECREF(shape_tuple); shape_tuple = 0;
__Pyx_GOTREF(temp_int);
__Pyx_XDECREF(temp_int); temp_int = 0;
__Pyx_XDECREF(array_obj); array_obj = 0;
__Pyx_FinishRefcountContext();
return new_mvs;
}
'''
def
get_copy_contents_code
(
from_mvs
,
to_mvs
,
cfunc_name
):
assert
from_mvs
.
dtype
==
to_mvs
.
dtype
assert
len
(
from_mvs
.
axes
)
==
len
(
to_mvs
.
axes
)
ndim
=
len
(
from_mvs
.
axes
)
# XXX: we only support direct access for now.
for
(
access
,
packing
)
in
from_mvs
.
axes
:
if
access
!=
'direct'
:
raise
NotImplementedError
(
"only direct access supported currently."
)
code
=
'''
static int %(cfunc_name)s(const __Pyx_memviewslice *from_mvs, __Pyx_memviewslice *to_mvs) {
char *to_buf = (char *)to_mvs->data;
char *from_buf = (char *)from_mvs->data;
struct __pyx_obj_memoryview *temp_memview = 0;
char *temp_data = 0;
'''
%
{
'cfunc_name'
:
cfunc_name
}
if
to_mvs
.
is_c_contig
:
start
,
stop
,
step
=
0
,
ndim
,
1
elif
to_mvs
.
is_f_contig
:
start
,
stop
,
step
=
ndim
-
1
,
-
1
,
-
1
else
:
assert
False
INDENT
=
" "
for
i
,
idx
in
enumerate
(
range
(
start
,
stop
,
step
)):
# the crazy indexing is to account for the fortran indexing.
# 'i' always goes up from zero to ndim-1.
# 'idx' is the same as 'i' for c_contig, and goes from ndim-1 to 0 for f_contig.
# this makes the loop code below identical in both cases.
code
+=
INDENT
+
"Py_ssize_t i%d = 0, idx%d = 0;
\
n
"
%
(
i
,
i
)
code
+=
INDENT
+
"Py_ssize_t stride%(i)d = from_mvs->diminfo[%(idx)d].strides;
\
n
"
%
{
'i'
:
i
,
'idx'
:
idx
}
code
+=
INDENT
+
"Py_ssize_t shape%(i)d = from_mvs->diminfo[%(idx)d].shape;
\
n
"
%
{
'i'
:
i
,
'idx'
:
idx
}
code
+=
"
\
n
"
# put down the nested for-loop.
for
k
in
range
(
ndim
):
code
+=
INDENT
*
(
k
+
1
)
+
"for(i%(k)d=0; i%(k)d<shape%(k)d; i%(k)d++) {
\
n
"
%
{
'k'
:
k
}
code
+=
INDENT
*
(
k
+
2
)
+
"idx%(k)d = i%(k)d * stride%(k)d;
\
n
"
%
{
'k'
:
k
}
# the inner part of the loop.
dtype_decl
=
from_mvs
.
dtype
.
declaration_code
(
""
)
last_idx
=
ndim
-
1
code
+=
INDENT
*
ndim
+
"memcpy(to_buf, from_buf+idx%(last_idx)d, sizeof(%(dtype_decl)s));
\
n
"
%
locals
()
code
+=
INDENT
*
ndim
+
"to_buf += sizeof(%(dtype_decl)s);
\
n
"
%
locals
()
# for-loop closing braces
for
k
in
range
(
ndim
-
1
,
-
1
,
-
1
):
code
+=
INDENT
*
(
k
+
1
)
+
"}
\
n
"
# init to_mvs->data and to_mvs->diminfo.
code
+=
INDENT
+
"temp_memview = to_mvs->memview;
\
n
"
code
+=
INDENT
+
"temp_data = to_mvs->data;
\
n
"
code
+=
INDENT
+
"to_mvs->memview = 0; to_mvs->data = 0;
\
n
"
code
+=
INDENT
+
"if(unlikely(-1 == __Pyx_init_memviewslice(temp_memview, %d, to_mvs))) {
\
n
"
%
(
ndim
,)
code
+=
INDENT
*
2
+
"return -1;
\
n
"
code
+=
INDENT
+
"}
\
n
"
code
+=
INDENT
+
"return 0;
\
n
"
code
+=
'}
\
n
'
return
code
def
get_axes_specs
(
env
,
axes
):
'''
...
...
@@ -288,16 +448,17 @@ def get_axes_specs(env, axes):
def
is_cf_contig
(
specs
):
is_c_contig
=
is_f_contig
=
False
packing_idx
=
1
if
(
len
(
specs
)
==
1
and
specs
==
[(
'direct'
,
'contig'
)]):
is_c_contig
=
True
if
(
specs
[
-
1
][
packing_idx
]
==
'contig'
and
all
(
axis
[
packing_idx
]
==
'follow'
for
axis
in
specs
[:
-
1
])):
elif
(
specs
[
-
1
]
==
(
'direct'
,
'contig'
)
and
all
(
axis
==
(
'direct'
,
'follow'
)
for
axis
in
specs
[:
-
1
])):
# c_contiguous: 'follow', 'follow', ..., 'follow', 'contig'
is_c_contig
=
True
elif
(
len
(
specs
)
>
1
and
specs
[
0
]
[
packing_idx
]
==
'contig'
and
all
(
axis
[
packing_idx
]
==
'follow'
for
axis
in
specs
[
1
:])):
specs
[
0
]
==
(
'direct'
,
'contig'
)
and
all
(
axis
==
(
'direct'
,
'follow'
)
for
axis
in
specs
[
1
:])):
# f_contiguous: 'contig', 'follow', 'follow', ..., 'follow'
is_f_contig
=
True
...
...
@@ -596,7 +757,13 @@ static int __Pyx_init_memviewslice(
int i, retval=-1;
Py_buffer *buf = &memview->view;
if(!buf || memviewslice->memview || memviewslice->data) {
if(!buf) {
PyErr_SetString(PyExc_ValueError,
"buf is NULL.");
goto fail;
} else if(memviewslice->memview || memviewslice->data) {
PyErr_SetString(PyExc_ValueError,
"memviewslice is already initialized!");
goto fail;
}
...
...
Cython/Compiler/PyrexTypes.py
View file @
308c3516
...
...
@@ -383,6 +383,7 @@ class MemoryViewSliceType(PyrexType):
if
self
.
scope
is
None
:
import
Symtab
,
MemoryView
from
MemoryView
import
axes_to_str
self
.
scope
=
scope
=
Symtab
.
CClassScope
(
'mvs_class_'
+
self
.
specialization_suffix
(),
...
...
@@ -391,41 +392,90 @@ class MemoryViewSliceType(PyrexType):
scope
.
parent_type
=
self
# the C copy method
c_copy_name
=
'__Pyx_CopyBuffer_C_'
+
self
.
specialization_suffix
()
scope
.
declare_cfunction
(
'copy'
,
CFuncType
(
cython_memoryview_ptr_type
,
[
CFuncTypeArg
(
"memviewslice"
,
self
,
None
)]),
pos
=
None
,
defining
=
1
,
cname
=
c_copy_name
)
scope
.
declare_var
(
'_data'
,
c_char_ptr_type
,
None
,
cname
=
'data'
,
is_cdef
=
1
)
mangle_dtype
=
MemoryView
.
mangle_dtype_name
(
self
.
dtype
)
ndim
=
len
(
self
.
axes
)
to_axes_c
=
[(
'direct'
,
'contig'
)]
to_axes_f
=
[(
'direct'
,
'contig'
)]
if
ndim
-
1
:
to_axes_c
=
[(
'direct'
,
'follow'
)
*
(
ndim
-
1
)]
+
to_axes_c
to_axes_f
=
to_axes_f
+
[(
'direct'
,
'follow'
)
*
(
ndim
-
1
)]
to_memview_c
=
MemoryViewSliceType
(
self
.
dtype
,
to_axes_c
,
self
.
env
)
to_memview_f
=
MemoryViewSliceType
(
self
.
dtype
,
to_axes_f
,
self
.
env
)
copy_name_c
=
'__Pyx_BufferNew_C_From_'
+
self
.
specialization_suffix
()
copy_name_f
=
'__Pyx_BufferNew_F_From_'
+
self
.
specialization_suffix
()
# the Fortran copy method
f_copy_name
=
'__Pyx_CopyBuffer_F_'
+
self
.
specialization_suffix
()
scope
.
declare_cfunction
(
'copy_fortran'
,
CFuncType
(
cython_memoryview_ptr_type
,
cython_name_c
=
'copy'
cython_name_f
=
'copy_fortran'
c_copy_util_code
=
UtilityCode
()
f_copy_util_code
=
UtilityCode
()
for
(
to_memview
,
copy_name
,
cython_name
,
mode
,
contig_flag
,
util_code
)
in
(
(
to_memview_c
,
copy_name_c
,
cython_name_c
,
'c'
,
'PyBUF_C_CONTIGUOUS'
,
c_copy_util_code
),
(
to_memview_f
,
copy_name_f
,
cython_name_f
,
'f'
,
'PyBUF_F_CONTIGUOUS'
,
f_copy_util_code
)):
copy_contents_name
=
MemoryView
.
get_copy_contents_name
(
self
,
to_memview
)
scope
.
declare_cfunction
(
cython_name
,
CFuncType
(
self
,
[
CFuncTypeArg
(
"memviewslice"
,
self
,
None
)]),
pos
=
None
,
defining
=
1
,
cname
=
f_
copy_name
)
cname
=
copy_name
)
# ensure the right util code is used
MemoryView
.
use_cython_array
(
self
.
env
)
MemoryView
.
use_memview_util_code
(
self
.
env
)
copy_impl
=
MemoryView
.
copy_template
%
\
dict
(
copy_name
=
copy_name
,
mode
=
mode
,
sizeof_dtype
=
"sizeof(%s)"
%
self
.
dtype
.
declaration_code
(
''
),
contig_flag
=
contig_flag
,
copy_contents_name
=
copy_contents_name
)
# C copy method implementation.
ccopy_util_code
=
UtilityCode
()
# ccopy_util_code.proto =#XXX
copy_decl
=
'''
\
static __Pyx_memviewslice %s(const __Pyx_memviewslice); /* proto */
'''
%
(
copy_name
,)
util_code
.
proto
=
copy_decl
util_code
.
impl
=
copy_impl
copy_contents_name_c
=
MemoryView
.
get_copy_contents_name
(
self
,
to_memview_c
)
copy_contents_name_f
=
MemoryView
.
get_copy_contents_name
(
self
,
to_memview_f
)
return
True
c_copy_util_code
.
proto
+=
(
'static int %s'
'(const __Pyx_memviewslice *,'
' __Pyx_memviewslice *); /* proto */
\
n
'
%
(
copy_contents_name_c
,))
c_copy_util_code
.
impl
+=
\
MemoryView
.
get_copy_contents_code
(
self
,
to_memview_c
,
copy_contents_name_c
)
if
(
MemoryView
.
get_copy_contents_code
(
self
,
to_memview_c
,
copy_contents_name_c
)
!=
MemoryView
.
get_copy_contents_code
(
self
,
to_memview_f
,
copy_contents_name_f
)):
f_copy_util_code
.
proto
+=
(
'static int %s'
'(const __Pyx_memviewslice *,'
' __Pyx_memviewslice *); /* proto */
\
n
'
%
(
copy_contents_name_f
,))
def
axes_to_str
(
self
):
return
""
.
join
([
access
[
0
]
+
packing
[
0
]
for
(
access
,
packing
)
in
self
.
axes
])
f_copy_util_code
.
impl
+=
\
MemoryView
.
get_copy_contents_code
(
self
,
to_memview_f
,
copy_contents_name_f
)
self
.
env
.
use_utility_code
(
c_copy_util_code
)
self
.
env
.
use_utility_code
(
c_copy_util_code
)
# ensure the right util code is used
MemoryView
.
use_cython_array
(
self
.
env
)
MemoryView
.
use_memview_util_code
(
self
.
env
)
return
True
def
specialization_suffix
(
self
):
return
self
.
axes_to_str
()
+
'_'
+
self
.
dtype
.
specalization_name
()
import
MemoryView
return
MemoryView
.
axes_to_str
(
self
.
axes
)
+
'_'
+
MemoryView
.
mangle_dtype_name
(
self
.
dtype
)
def
global_init_code
(
self
,
entry
,
code
):
code
.
putln
(
"%s.data = NULL;"
%
entry
.
cname
)
...
...
@@ -2622,6 +2672,9 @@ cython_memoryview_type = CStructOrUnionType("__pyx_obj_memoryview", "struct",
cython_memoryview_ptr_type
=
CPtrType
(
cython_memoryview_type
)
memoryviewslice_type
=
CStructOrUnionType
(
"__Pyx_memviewslice"
,
"struct"
,
None
,
1
,
"__Pyx_memviewslice"
)
error_type
=
ErrorType
()
unspecified_type
=
UnspecifiedType
()
...
...
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