Commit 2cd11fd8 authored by Mark Florisson's avatar Mark Florisson

@cname for enum/struct in CythonUtilityCode + simple memslice indexing

parent 556722cb
......@@ -93,7 +93,7 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
return aux_var
auxvars = ((PyrexTypes.c_pyx_buffer_nd_type, Naming.pybuffernd_prefix),
(PyrexTypes.c_pyx_buffer_type, Naming.pybufferstruct_prefix))
(PyrexTypes.c_pyx_buffer_type, Naming.pybufferstruct_prefix))
pybuffernd, rcbuffer = [decvar(type, prefix) for (type, prefix) in auxvars]
entry.buffer_aux = Symtab.BufferAux(pybuffernd, rcbuffer)
......@@ -195,15 +195,26 @@ def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, nee
# Code generation
#
def get_buf_suboffsetvars(entry):
return [("%s.diminfo[%d].suboffsets" % \
(entry.buffer_aux.buflocal_nd_var.cname, i)) for i in range(entry.type.ndim)]
def get_buf_stridevars(entry):
return [("%s.diminfo[%d].strides" % \
(entry.buffer_aux.buflocal_nd_var.cname, i)) for i in range(entry.type.ndim)]
def get_buf_shapevars(entry):
return [("%s.diminfo[%d].shape" % \
(entry.buffer_aux.buflocal_nd_var.cname, i)) for i in range(entry.type.ndim)]
class BufferEntry(object):
def __init__(self, entry):
self.entry = entry
self.type = entry.type
self.cname = entry.buffer_aux.buflocal_nd_var.cname
self.buf_ptr = "%s.rcbuffer->pybuffer.buf" % self.cname
self.buf_ptr_type = self.entry.type.buffer_ptr_type
def get_buf_suboffsetvars(self):
return self._for_all_ndim("%s.diminfo[%d].suboffsets")
def get_buf_stridevars(self):
return self._for_all_ndim("%s.diminfo[%d].strides")
def get_buf_shapevars(self):
return self._for_all_ndim("%s.diminfo[%d].shape")
def _for_all_ndim(self, s):
return [s % (self.cname, i) for i in range(self.type.ndim)]
def get_flags(buffer_aux, buffer_type):
flags = 'PyBUF_FORMAT'
......@@ -358,7 +369,8 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buf_entry,
code.putln("}") # Release stack
def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos, code):
def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives,
pos, code, negative_indices):
"""
Generates code to process indices and calculate an offset into
a buffer. Returns a C string which gives a pointer which can be
......@@ -370,11 +382,9 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
body. The lookup however is delegated to a inline function that is instantiated
once per ndim (lookup with suboffsets tend to get quite complicated).
entry is a BufferEntry
"""
bufaux = entry.buffer_aux
pybuffernd_struct = bufaux.buflocal_nd_var.cname
# bufstruct = bufaux.buffer_info_var.cname
negative_indices = directives['wraparound'] and entry.type.negative_indices
negative_indices = directives['wraparound'] and negative_indices
if directives['boundscheck']:
# Check bounds and fix negative indices.
......@@ -384,7 +394,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
code.putln("%s = -1;" % tmp_cname)
for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
get_buf_shapevars(entry))):
entry.get_buf_shapevars())):
if signed != 0:
# not unsigned, deal with negative index
code.putln("if (%s < 0) {" % cname)
......@@ -412,7 +422,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
elif negative_indices:
# Only fix negative indices.
for signed, cname, shape in zip(index_signeds, index_cnames,
get_buf_shapevars(entry)):
entry.get_buf_shapevars()):
if signed != 0:
code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape))
......@@ -423,7 +433,9 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
nd = entry.type.ndim
mode = entry.type.mode
if mode == 'full':
for i, s, o in zip(index_cnames, get_buf_stridevars(entry), get_buf_suboffsetvars(entry)):
for i, s, o in zip(index_cnames,
entry.get_buf_stridevars(),
entry.get_buf_suboffsetvars()):
params.append(i)
params.append(s)
params.append(o)
......@@ -441,7 +453,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
funcgen = buf_lookup_fortran_code
else:
assert False
for i, s in zip(index_cnames, get_buf_stridevars(entry)):
for i, s in zip(index_cnames, entry.get_buf_stridevars()):
params.append(i)
params.append(s)
......@@ -452,11 +464,9 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos,
defcode = code.globalstate['utility_code_def']
funcgen(protocode, defcode, name=funcname, nd=nd)
ptr_type = entry.type.buffer_ptr_type
ptrcode = "%s(%s, %s.rcbuffer->pybuffer.buf, %s)" % (funcname,
ptr_type.declaration_code(""),
pybuffernd_struct,
", ".join(params))
buf_ptr_type_code = entry.buf_ptr_type.declaration_code("")
ptrcode = "%s(%s, %s, %s)" % (funcname, buf_ptr_type_code, entry.buf_ptr,
", ".join(params))
return ptrcode
......
......@@ -49,9 +49,15 @@ class UtilityCodeBase(object):
_utility_cache = {}
@classmethod
def _add_utility(self, utility, type, lines, begin_lineno):
def _add_utility(cls, utility, type, lines, begin_lineno):
if utility:
code = '\n' * begin_lineno + ''.join(lines)
if cls.is_cython_utility:
# Don't forget our line number
code = '\n' * begin_lineno + ''.join(lines)
else:
# line numbers are not important here
code = '\n'.join(lines)
if type == 'Proto':
utility[0] = code
else:
......@@ -74,8 +80,6 @@ class UtilityCodeBase(object):
comment = '//'
regex = r'%s\s*Utility(Proto|Code)\s*:\s*((\w|\.)+)\s*' % comment
flags = re.DOTALL
utilities = {}
lines = []
......
......@@ -2209,6 +2209,10 @@ class IndexNode(ExprNode):
subexprs = ['base', 'index', 'indices']
indices = None
# Whether we're assigning to a buffer (in that case it needs to be
# writable)
writable_needed = False
def __init__(self, pos, index, *args, **kw):
ExprNode.__init__(self, pos, index=index, *args, **kw)
self._index = index
......@@ -2341,8 +2345,8 @@ class IndexNode(ExprNode):
skip_child_analysis = False
buffer_access = False
memoryviewslice_access = False
if self.base.type.is_buffer:
# memoryviewslice_access = False
if self.base.type.is_buffer or self.base.type.is_memoryviewslice:
if self.indices:
indices = self.indices
else:
......@@ -2360,11 +2364,11 @@ class IndexNode(ExprNode):
if buffer_access:
assert hasattr(self.base, "entry") # Must be a NameNode-like node
if self.base.type.is_memoryviewslice:
assert hasattr(self.base, "entry")
if self.indices or not isinstance(self.index, EllipsisNode):
error(self.pos, "Memoryviews currently support ellipsis indexing only.")
else: memoryviewslice_access = True
# if self.base.type.is_memoryviewslice:
# assert hasattr(self.base, "entry")
# if self.indices or not isinstance(self.index, EllipsisNode):
# error(self.pos, "Memoryviews currently support ellipsis indexing only.")
# else: memoryviewslice_access = True
# On cloning, indices is cloned. Otherwise, unpack index into indices
assert not (buffer_access and isinstance(self.index, CloneNode))
......@@ -2382,13 +2386,15 @@ class IndexNode(ExprNode):
if not self.base.entry.type.writable:
error(self.pos, "Writing to readonly buffer")
else:
self.base.entry.buffer_aux.writable_needed = True
self.writable_needed = True
if self.type.is_buffer:
self.base.entry.buffer_aux.writable_needed = True
elif memoryviewslice_access:
self.type = self.base.type
self.is_memoryviewslice_access = True
if getting:
error(self.pos, "memoryviews currently support setting only.")
# elif memoryviewslice_access:
# self.type = self.base.type
# self.is_memoryviewslice_access = True
# if getting:
# error(self.pos, "memoryviews currently support setting only.")
else:
base_type = self.base.type
......@@ -2680,18 +2686,30 @@ class IndexNode(ExprNode):
def buffer_lookup_code(self, code):
# Assign indices to temps
index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False)
for i in self.indices]
for temp, index in zip(index_temps, self.indices):
code.putln("%s = %s;" % (temp, index.result()))
# Generate buffer access code using these temps
import Buffer
import Buffer, MemoryView
# The above could happen because child_attrs is wrong somewhere so that
# options are not propagated.
return Buffer.put_buffer_lookup_code(entry=self.base.entry,
entry = self.base.entry
if entry.type.is_buffer:
buffer_entry = Buffer.BufferEntry(entry)
negative_indices = entry.type.negative_indices
else:
buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry)
negative_indices = Buffer.buffer_defaults['negative_indices']
return Buffer.put_buffer_lookup_code(entry=buffer_entry,
index_signeds=[i.type.signed for i in self.indices],
index_cnames=index_temps,
directives=code.globalstate.directives,
pos=self.pos, code=code)
pos=self.pos, code=code,
negative_indices=negative_indices)
def put_nonecheck(self, code):
code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
......
......@@ -6,7 +6,7 @@ from Code import UtilityCode
from UtilityCode import CythonUtilityCode
from PyrexTypes import py_object_type, cython_memoryview_ptr_type
import Buffer
import PyrexTypes
START_ERR = "there must be nothing or the value 0 (zero) in the start slot."
STOP_ERR = "Axis specification only allowed in the 'stop' slot."
......@@ -112,7 +112,7 @@ def put_assign_to_memviewslice(lhs_cname, rhs_cname, memviewslicetype, pos, code
for i in range(ndim):
code.putln("%s.shape[%d] = %s.shape[%d];" % (lhs_cname, i, rhs_cname, i))
code.putln("%s.strides[%d] = %s.strides[%d];" % (lhs_cname, i, rhs_cname, i))
code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % (lhs_cname, i, rhs_cname, i))
# code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % (lhs_cname, i, rhs_cname, i))
def get_buf_flag(specs):
is_c_contig, is_f_contig = is_cf_contig(specs)
......@@ -173,6 +173,28 @@ def src_conforms_to_dst(src, dst):
return True
class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
def __init__(self, entry):
self.entry = entry
self.type = entry.type
self.cname = entry.cname
self.buf_ptr = "%s.data" % self.cname
dtype = self.entry.type.dtype
dtype = PyrexTypes.CPtrType(dtype)
self.buf_ptr_type = dtype
def get_buf_suboffsetvars(self):
return self._for_all_ndim("%s.memview->view.suboffsets[%d]")
def get_buf_stridevars(self):
return self._for_all_ndim("%s.strides[%d]")
def get_buf_shapevars(self):
return self._for_all_ndim("%s.shape[%d]")
def get_copy_func_name(to_memview):
base = "__Pyx_BufferNew_%s_From_%s_%s"
if to_memview.is_c_contig:
......@@ -245,7 +267,7 @@ static int %s(const __Pyx_memviewslice mvs) {
%(for_loop)s {
#ifdef DEBUG
printf("mvs.suboffsets[i] %%d\\n", mvs.suboffsets[i]);
/* printf("mvs.suboffsets[i] %%d\\n", mvs.suboffsets[i]); */
printf("mvs.strides[i] %%d\\n", mvs.strides[i]);
printf("mvs.shape[i] %%d\\n", mvs.shape[i]);
printf("size %%d\\n", size);
......@@ -253,7 +275,7 @@ static int %s(const __Pyx_memviewslice mvs) {
#endif
#undef DEBUG
if(mvs.suboffsets[i] >= 0) {
if(mvs.memview->view.suboffsets[i] >= 0) {
return 0;
}
if(size * itemsize != mvs.strides[i]) {
......@@ -595,6 +617,20 @@ def is_cf_contig(specs):
return is_c_contig, is_f_contig
def get_mode(specs):
is_c_contig, is_f_contig = is_cf_contig(specs)
if is_c_contig:
return 'c'
elif is_f_contig:
return 'fortran'
for access, packing in specs:
if access in ('ptr', 'full'):
return 'full'
return 'strided'
def validate_axes_specs(pos, specs):
packing_specs = ('contig', 'strided', 'follow')
......@@ -622,7 +658,6 @@ def validate_axes_specs(pos, specs):
if not (is_c_contig or is_f_contig):
raise CompileError(pos, "Invalid use of the follow specifier.")
def _get_resolved_spec(env, spec):
# spec must be a NameNode or an AttributeNode
if isinstance(spec, NameNode):
......@@ -704,13 +739,13 @@ def load_memview_cy_utility(name, *args, **kwargs):
def load_memview_c_utility(name, *args, **kwargs):
return UtilityCode.load_utility_from_file(
"MemoryView.c", name, *args, **kwargs)
"MemoryView_C.c", name, *args, **kwargs)
def load_memview_c_string(name):
return UtilityCode.load_utility_as_string("MemoryView.c", name)
return UtilityCode.load_utility_as_string("MemoryView_C.c", name)
_, copy_template = UtilityCode.load_utility_as_string(
"MemoryView.c", "MemviewSliceCopyTemplate")
"MemoryView_C.c", "MemviewSliceCopyTemplate")
fmt_dict = {
'memview_struct_name': memview_objstruct_cname,
......
......@@ -65,10 +65,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.body.stats.extend(tree.stats)
else:
self.body.stats.append(tree)
selfscope = self.scope
selfscope.utility_code_list.extend(scope.utility_code_list)
self.scope.utility_code_list.extend(scope.utility_code_list)
def extend_if_not_in(L1, L2):
for x in L2:
if x not in L1:
L1.append(x)
extend_if_not_in(self.scope.include_files, scope.include_files)
extend_if_not_in(self.scope.included_files, scope.included_files)
extend_if_not_in(self.scope.python_include_files,
scope.python_include_files)
if merge_scope:
selfscope.merge_in(scope)
self.scope.merge_in(scope)
def analyse_declarations(self, env):
if Options.embed_pos_in_docstring:
......
......@@ -6977,11 +6977,15 @@ class CnameDecoratorNode(StatNode):
self.node.analyse_declarations(env)
self.is_function = isinstance(self.node, FuncDefNode)
is_struct_or_enum = isinstance(self.node, (CStructOrUnionDefNode,
CEnumDefNode))
e = self.node.entry
if self.is_function:
e.cname = self.cname
e.func_cname = self.cname
elif is_struct_or_enum:
e.cname = e.type.cname = self.cname
else:
scope = self.node.scope
......
......@@ -1255,7 +1255,7 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
"""
def handle_function(self, node):
if not node.decorators:
if not getattr(node, 'decorators', None):
return self.visit_Node(node)
for i, decorator in enumerate(node.decorators):
......@@ -1289,6 +1289,8 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
visit_FuncDefNode = handle_function
visit_CClassDefNode = handle_function
visit_CEnumDefNode = handle_function
visit_CStructOrUnionDefNode = handle_function
class ForwardDeclareTypes(CythonTransform):
......@@ -1576,6 +1578,14 @@ if VALUE is not None:
self.visitchildren(node)
return None
def visit_CnameDecoratorNode(self, node):
self.visitchildren(node)
if not node.node:
return None
return node
def create_Property(self, entry):
if entry.visibility == 'public':
if entry.type.is_pyobject:
......
......@@ -7,8 +7,8 @@ ctypedef object (*p_sub_expr_func)(object)
# entry points
cpdef p_module(PyrexScanner s, pxd, full_module_name)
cpdef p_code(PyrexScanner s, level= *)
cpdef p_module(PyrexScanner s, pxd, full_module_name, ctx=*)
cpdef p_code(PyrexScanner s, level= *, ctx=*)
# internal parser states
......
......@@ -33,6 +33,7 @@ class Ctx(object):
nogil = 0
namespace = None
templates = None
allow_struct_enum_decorator = False
def __init__(self, **kwds):
self.__dict__.update(kwds)
......@@ -1754,7 +1755,8 @@ def p_statement(s, ctx, first_statement = 0):
s.error('decorator not allowed here')
s.level = ctx.level
decorators = p_decorators(s)
if s.sy not in ('def', 'cdef', 'cpdef', 'class'):
bad_toks = 'def', 'cdef', 'cpdef', 'class'
if not ctx.allow_struct_enum_decorator and s.sy not in bad_toks:
s.error("Decorators can only be followed by functions or classes")
elif s.sy == 'pass' and cdef_flag:
# empty cdef block
......@@ -1774,7 +1776,10 @@ def p_statement(s, ctx, first_statement = 0):
s.level = ctx.level
node = p_cdef_statement(s, ctx(overridable = overridable))
if decorators is not None:
if not isinstance(node, (Nodes.CFuncDefNode, Nodes.CVarDefNode, Nodes.CClassDefNode)):
tup = Nodes.CFuncDefNode, Nodes.CVarDefNode, Nodes.CClassDefNode
if ctx.allow_struct_enum_decorator:
tup += Nodes.CStructOrUnionDefNode, Nodes.CEnumDefNode
if not isinstance(node, tup):
s.error("Decorators can only be followed by functions or classes")
node.decorators = decorators
return node
......@@ -2892,8 +2897,8 @@ def p_doc_string(s):
else:
return None
def p_code(s, level=None):
body = p_statement_list(s, Ctx(level = level), first_statement = 1)
def p_code(s, level=None, ctx=Ctx):
body = p_statement_list(s, ctx(level = level), first_statement = 1)
if s.sy != 'EOF':
s.error("Syntax error in statement [%s,%s]" % (
repr(s.sy), repr(s.systring)))
......@@ -2915,7 +2920,7 @@ def p_compiler_directive_comments(s):
s.next()
return result
def p_module(s, pxd, full_module_name):
def p_module(s, pxd, full_module_name, ctx=Ctx):
pos = s.position()
directive_comments = p_compiler_directive_comments(s)
......@@ -2930,7 +2935,7 @@ def p_module(s, pxd, full_module_name):
else:
level = 'module'
body = p_statement_list(s, Ctx(level = level), first_statement = 1)
body = p_statement_list(s, ctx(level=level), first_statement = 1)
if s.sy != 'EOF':
s.error("Syntax error in statement [%s,%s]" % (
repr(s.sy), repr(s.systring)))
......
......@@ -368,11 +368,14 @@ class MemoryViewSliceType(PyrexType):
self.dtype = base_dtype
self.axes = axes
self.ndim = len(axes)
import MemoryView
self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes)
assert not (self.is_c_contig and self.is_f_contig)
self.mode = MemoryView.get_mode(axes)
def same_as_resolved_type(self, other_type):
return ((other_type.is_memoryviewslice and
self.dtype.same_as(other_type.dtype) and
......
......@@ -32,7 +32,7 @@ class StringParseContext(Main.Context):
return ModuleScope(module_name, parent_module = None, context = self)
def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None,
context=None):
context=None, allow_struct_enum_decorator=False):
"""
Utility method to parse a (unicode) string of code. This is mostly
used for internal Cython compiler purposes (creating code snippets
......@@ -66,12 +66,15 @@ def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None,
scanner = PyrexScanner(buf, code_source, source_encoding = encoding,
scope = scope, context = context, initial_pos = initial_pos)
ctx = Parsing.Ctx(allow_struct_enum_decorator=allow_struct_enum_decorator)
if level is None:
tree = Parsing.p_module(scanner, 0, module_name)
tree = Parsing.p_module(scanner, 0, module_name, ctx=ctx)
tree.scope = scope
tree.is_pxd = False
else:
tree = Parsing.p_code(scanner, level=level)
tree = Parsing.p_code(scanner, level=level, ctx=ctx)
tree.scope = scope
return tree
......
......@@ -86,7 +86,8 @@ class CythonUtilityCode(Code.UtilityCodeBase):
context = CythonUtilityCodeContext(self.name)
context.prefix = self.prefix
#context = StringParseContext(self.name)
tree = parse_from_strings(self.name, self.pyx, context=context)
tree = parse_from_strings(self.name, self.pyx, context=context,
allow_struct_enum_decorator=True)
pipeline = Pipeline.create_pipeline(context, 'pyx', exclude_classes=excludes)
if entries_only:
......
......@@ -11,6 +11,7 @@ cdef extern from "Python.h":
PyBUF_F_CONTIGUOUS,
PyBUF_ANY_CONTIGUOUS
@cname("__pyx_array")
cdef class array:
......@@ -87,10 +88,6 @@ cdef class array:
self.data = <char *>malloc(self.len)
if not self.data:
raise MemoryError("unable to allocate array data.")
else:
self.data = NULL
self.callback_free_data = NULL
def __getbuffer__(self, Py_buffer *info, int flags):
......@@ -139,6 +136,21 @@ cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *
# UtilityCode: MemoryView
# from cpython cimport ...
cdef extern from "pythread.h":
ctypedef void *PyThread_type_lock
PyThread_type_lock PyThread_allocate_lock()
void PyThread_free_lock(PyThread_type_lock)
int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
void PyThread_release_lock(PyThread_type_lock) nogil
cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int)
void __Pyx_ReleaseBuffer(Py_buffer *)
@cname('__pyx_MemviewEnum')
cdef class Enum(object):
cdef object name
......@@ -147,6 +159,7 @@ cdef class Enum(object):
def __repr__(self):
return self.name
cdef strided = Enum("<strided axis packing mode>")
cdef contig = Enum("<contig axis packing mode>")
cdef follow = Enum("<follow axis packing mode>")
......@@ -154,25 +167,29 @@ cdef direct = Enum("<direct axis access mode>")
cdef ptr = Enum("<ptr axis access mode>")
cdef full = Enum("<full axis access mode>")
cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int)
void __Pyx_ReleaseBuffer(Py_buffer *)
@cname('__pyx_memoryview')
cdef class memoryview(object):
cdef object obj
cdef Py_buffer view
cdef int gotbuf_flag
cdef PyThread_type_lock acqcnt_lock
cdef int acquisition_count
def __cinit__(memoryview self, object obj, int flags):
self.obj = obj
__Pyx_GetBuffer(self.obj, &self.view, flags)
#self.acqcnt_lock = PyThread_allocate_lock()
#if self.acqcnt_lock == NULL:
# raise MemoryError
__Pyx_GetBuffer(obj, &self.view, flags)
def __dealloc__(memoryview self):
#PyThread_free_lock(self.acqcnt_lock)
self.obj = None
__Pyx_ReleaseBuffer(&self.view)
@cname('__pyx_memoryview_new')
cdef memoryview memoryview_cwrapper(object o, int flags):
return memoryview(o, flags)
......@@ -4,10 +4,11 @@
typedef struct {
struct %(memview_struct_name)s *memview;
/* For convenience and faster access */
char *data;
Py_ssize_t shape[%(max_dims)d];
Py_ssize_t strides[%(max_dims)d];
Py_ssize_t suboffsets[%(max_dims)d];
/* Py_ssize_t suboffsets[%(max_dims)d]; */
} %(memviewslice_name)s;
// UtilityProto: MemviewSliceInit
......@@ -24,6 +25,8 @@ typedef struct {
#define __Pyx_IS_C_CONTIG 1
#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,
int *axes_specs, int c_or_f_flag, int ndim, __Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice);
......@@ -40,7 +43,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
int *axes_specs,
int c_or_f_flag,
int ndim,
__Pyx_TypeInfo *dtype,
__Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[],
__Pyx_memviewslice *memviewslice) {
......@@ -191,11 +194,12 @@ static int __Pyx_init_memviewslice(
for(i=0; i<ndim; i++) {
memviewslice->strides[i] = buf->strides[i];
memviewslice->shape[i] = buf->shape[i];
/*
if(buf->suboffsets) {
memviewslice->suboffsets[i] = buf->suboffsets[i];
} else {
memviewslice->suboffsets[i] = -1;
}
}*/
}
__Pyx_INCREF((PyObject *)memview);
......
......@@ -55,3 +55,17 @@ def full_or_strided():
cy.array(shape=(10,10), itemsize=sizeof(float), format='f', mode='c')
cdef object[long long int, ndim=3, mode='strided'] stridedbuf = \
cy.array(shape=(1,2,3), itemsize=sizeof(long long int), format='q', mode='fortran')
def dont_allocate_buffer():
"""
>>> dont_allocate_buffer()
callback called 1
"""
cdef cy.array result = cy.array((10, 10), itemsize=sizeof(int), format='i', allocate_buffer=False)
assert result.data == NULL
result.data = <char *> 1
result.callback_free_data = callback
result = None
cdef void callback(char *data):
print "callback called %d" % <long> data
cimport cython
from cython cimport array
from libc.stdlib cimport malloc, free
def create_array(shape, mode='c'):
cdef array result = array(shape, itemsize=sizeof(int), format='i', mode=mode)
cdef int *data = <int *> result.data
cdef int i, j, value
for i in range(shape[0]):
for j in range(shape[1]):
value = i * shape[0] + j
if mode == 'fortran':
data[i + j * 10] = value
else:
data[value] = value
return result
def slice_contig_indexing():
"""
>>> slice_contig_indexing()
98
61
98
61
"""
cdef int[:, ::1] carr = create_array((14, 10))
cdef int[::1, :] farr = create_array((10, 14), mode='fortran')
print carr[9, 8]
print carr[6, 1]
print farr[9, 8]
print farr[6, 1]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment