diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /contrib/tools/cython/Cython/Compiler/MemoryView.py | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/MemoryView.py')
-rw-r--r-- | contrib/tools/cython/Cython/Compiler/MemoryView.py | 1504 |
1 files changed, 752 insertions, 752 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/MemoryView.py b/contrib/tools/cython/Cython/Compiler/MemoryView.py index 0406d6c716..28b67e29b1 100644 --- a/contrib/tools/cython/Cython/Compiler/MemoryView.py +++ b/contrib/tools/cython/Cython/Compiler/MemoryView.py @@ -1,272 +1,272 @@ -from __future__ import absolute_import - -from .Errors import CompileError, error -from . import ExprNodes -from .ExprNodes import IntNode, NameNode, AttributeNode -from . import Options -from .Code import UtilityCode, TempitaUtilityCode -from .UtilityCode import CythonUtilityCode -from . import Buffer -from . import PyrexTypes -from . import ModuleNode - -START_ERR = "Start must not be given." -STOP_ERR = "Axis specification only allowed in the 'step' slot." -STEP_ERR = "Step must be omitted, 1, or a valid specifier." -BOTH_CF_ERR = "Cannot specify an array that is both C and Fortran contiguous." -INVALID_ERR = "Invalid axis specification." -NOT_CIMPORTED_ERR = "Variable was not cimported from cython.view" -EXPR_ERR = "no expressions allowed in axis spec, only names and literals." -CF_ERR = "Invalid axis specification for a C/Fortran contiguous array." -ERR_UNINITIALIZED = ("Cannot check if memoryview %s is initialized without the " - "GIL, consider using initializedcheck(False)") - - -def concat_flags(*flags): - return "(%s)" % "|".join(flags) - - -format_flag = "PyBUF_FORMAT" - +from __future__ import absolute_import + +from .Errors import CompileError, error +from . import ExprNodes +from .ExprNodes import IntNode, NameNode, AttributeNode +from . import Options +from .Code import UtilityCode, TempitaUtilityCode +from .UtilityCode import CythonUtilityCode +from . import Buffer +from . import PyrexTypes +from . import ModuleNode + +START_ERR = "Start must not be given." +STOP_ERR = "Axis specification only allowed in the 'step' slot." +STEP_ERR = "Step must be omitted, 1, or a valid specifier." +BOTH_CF_ERR = "Cannot specify an array that is both C and Fortran contiguous." +INVALID_ERR = "Invalid axis specification." +NOT_CIMPORTED_ERR = "Variable was not cimported from cython.view" +EXPR_ERR = "no expressions allowed in axis spec, only names and literals." +CF_ERR = "Invalid axis specification for a C/Fortran contiguous array." +ERR_UNINITIALIZED = ("Cannot check if memoryview %s is initialized without the " + "GIL, consider using initializedcheck(False)") + + +def concat_flags(*flags): + return "(%s)" % "|".join(flags) + + +format_flag = "PyBUF_FORMAT" + memview_c_contiguous = "(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT)" memview_f_contiguous = "(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT)" memview_any_contiguous = "(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT)" memview_full_access = "PyBUF_FULL_RO" #memview_strided_access = "PyBUF_STRIDED_RO" memview_strided_access = "PyBUF_RECORDS_RO" - -MEMVIEW_DIRECT = '__Pyx_MEMVIEW_DIRECT' -MEMVIEW_PTR = '__Pyx_MEMVIEW_PTR' -MEMVIEW_FULL = '__Pyx_MEMVIEW_FULL' -MEMVIEW_CONTIG = '__Pyx_MEMVIEW_CONTIG' -MEMVIEW_STRIDED= '__Pyx_MEMVIEW_STRIDED' -MEMVIEW_FOLLOW = '__Pyx_MEMVIEW_FOLLOW' - -_spec_to_const = { - 'direct' : MEMVIEW_DIRECT, - 'ptr' : MEMVIEW_PTR, - 'full' : MEMVIEW_FULL, - 'contig' : MEMVIEW_CONTIG, - 'strided': MEMVIEW_STRIDED, - 'follow' : MEMVIEW_FOLLOW, - } - -_spec_to_abbrev = { - 'direct' : 'd', - 'ptr' : 'p', - 'full' : 'f', - 'contig' : 'c', - 'strided' : 's', - 'follow' : '_', -} - -memslice_entry_init = "{ 0, 0, { 0 }, { 0 }, { 0 } }" - -memview_name = u'memoryview' -memview_typeptr_cname = '__pyx_memoryview_type' -memview_objstruct_cname = '__pyx_memoryview_obj' -memviewslice_cname = u'__Pyx_memviewslice' - - -def put_init_entry(mv_cname, code): - code.putln("%s.data = NULL;" % mv_cname) - code.putln("%s.memview = NULL;" % mv_cname) - - -#def axes_to_str(axes): -# return "".join([access[0].upper()+packing[0] for (access, packing) in axes]) - - -def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code, - have_gil=False, first_assignment=True): - "We can avoid decreffing the lhs if we know it is the first assignment" - assert rhs.type.is_memoryviewslice - - pretty_rhs = rhs.result_in_temp() or rhs.is_simple() - if pretty_rhs: - rhstmp = rhs.result() - else: - rhstmp = code.funcstate.allocate_temp(lhs_type, manage_ref=False) - code.putln("%s = %s;" % (rhstmp, rhs.result_as(lhs_type))) - - # Allow uninitialized assignment - #code.putln(code.put_error_if_unbound(lhs_pos, rhs.entry)) - put_assign_to_memviewslice(lhs_cname, rhs, rhstmp, lhs_type, code, - have_gil=have_gil, first_assignment=first_assignment) - - if not pretty_rhs: - code.funcstate.release_temp(rhstmp) - - -def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code, - have_gil=False, first_assignment=False): - if not first_assignment: - code.put_xdecref_memoryviewslice(lhs_cname, have_gil=have_gil) - - if not rhs.result_in_temp(): - rhs.make_owned_memoryviewslice(code) - - code.putln("%s = %s;" % (lhs_cname, rhs_cname)) - - -def get_buf_flags(specs): - is_c_contig, is_f_contig = is_cf_contig(specs) - - if is_c_contig: - return memview_c_contiguous - elif is_f_contig: - return memview_f_contiguous - - access, packing = zip(*specs) - - if 'full' in access or 'ptr' in access: - return memview_full_access - else: - return memview_strided_access - - -def insert_newaxes(memoryviewtype, n): - axes = [('direct', 'strided')] * n - axes.extend(memoryviewtype.axes) - return PyrexTypes.MemoryViewSliceType(memoryviewtype.dtype, axes) - - -def broadcast_types(src, dst): - n = abs(src.ndim - dst.ndim) - if src.ndim < dst.ndim: - return insert_newaxes(src, n), dst - else: - return src, insert_newaxes(dst, n) - - -def valid_memslice_dtype(dtype, i=0): - """ - Return whether type dtype can be used as the base type of a - memoryview slice. - - We support structs, numeric types and objects - """ - if dtype.is_complex and dtype.real_type.is_int: - return False - - if dtype is PyrexTypes.c_bint_type: - return False - - if dtype.is_struct and dtype.kind == 'struct': - for member in dtype.scope.var_entries: - if not valid_memslice_dtype(member.type): - return False - - return True - - return ( - dtype.is_error or - # Pointers are not valid (yet) - # (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or - (dtype.is_array and i < 8 and - valid_memslice_dtype(dtype.base_type, i + 1)) or - dtype.is_numeric or - dtype.is_pyobject or - dtype.is_fused or # accept this as it will be replaced by specializations later - (dtype.is_typedef and valid_memslice_dtype(dtype.typedef_base_type)) - ) - - -class MemoryViewSliceBufferEntry(Buffer.BufferEntry): + +MEMVIEW_DIRECT = '__Pyx_MEMVIEW_DIRECT' +MEMVIEW_PTR = '__Pyx_MEMVIEW_PTR' +MEMVIEW_FULL = '__Pyx_MEMVIEW_FULL' +MEMVIEW_CONTIG = '__Pyx_MEMVIEW_CONTIG' +MEMVIEW_STRIDED= '__Pyx_MEMVIEW_STRIDED' +MEMVIEW_FOLLOW = '__Pyx_MEMVIEW_FOLLOW' + +_spec_to_const = { + 'direct' : MEMVIEW_DIRECT, + 'ptr' : MEMVIEW_PTR, + 'full' : MEMVIEW_FULL, + 'contig' : MEMVIEW_CONTIG, + 'strided': MEMVIEW_STRIDED, + 'follow' : MEMVIEW_FOLLOW, + } + +_spec_to_abbrev = { + 'direct' : 'd', + 'ptr' : 'p', + 'full' : 'f', + 'contig' : 'c', + 'strided' : 's', + 'follow' : '_', +} + +memslice_entry_init = "{ 0, 0, { 0 }, { 0 }, { 0 } }" + +memview_name = u'memoryview' +memview_typeptr_cname = '__pyx_memoryview_type' +memview_objstruct_cname = '__pyx_memoryview_obj' +memviewslice_cname = u'__Pyx_memviewslice' + + +def put_init_entry(mv_cname, code): + code.putln("%s.data = NULL;" % mv_cname) + code.putln("%s.memview = NULL;" % mv_cname) + + +#def axes_to_str(axes): +# return "".join([access[0].upper()+packing[0] for (access, packing) in axes]) + + +def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code, + have_gil=False, first_assignment=True): + "We can avoid decreffing the lhs if we know it is the first assignment" + assert rhs.type.is_memoryviewslice + + pretty_rhs = rhs.result_in_temp() or rhs.is_simple() + if pretty_rhs: + rhstmp = rhs.result() + else: + rhstmp = code.funcstate.allocate_temp(lhs_type, manage_ref=False) + code.putln("%s = %s;" % (rhstmp, rhs.result_as(lhs_type))) + + # Allow uninitialized assignment + #code.putln(code.put_error_if_unbound(lhs_pos, rhs.entry)) + put_assign_to_memviewslice(lhs_cname, rhs, rhstmp, lhs_type, code, + have_gil=have_gil, first_assignment=first_assignment) + + if not pretty_rhs: + code.funcstate.release_temp(rhstmp) + + +def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code, + have_gil=False, first_assignment=False): + if not first_assignment: + code.put_xdecref_memoryviewslice(lhs_cname, have_gil=have_gil) + + if not rhs.result_in_temp(): + rhs.make_owned_memoryviewslice(code) + + code.putln("%s = %s;" % (lhs_cname, rhs_cname)) + + +def get_buf_flags(specs): + is_c_contig, is_f_contig = is_cf_contig(specs) + + if is_c_contig: + return memview_c_contiguous + elif is_f_contig: + return memview_f_contiguous + + access, packing = zip(*specs) + + if 'full' in access or 'ptr' in access: + return memview_full_access + else: + return memview_strided_access + + +def insert_newaxes(memoryviewtype, n): + axes = [('direct', 'strided')] * n + axes.extend(memoryviewtype.axes) + return PyrexTypes.MemoryViewSliceType(memoryviewtype.dtype, axes) + + +def broadcast_types(src, dst): + n = abs(src.ndim - dst.ndim) + if src.ndim < dst.ndim: + return insert_newaxes(src, n), dst + else: + return src, insert_newaxes(dst, n) + + +def valid_memslice_dtype(dtype, i=0): + """ + Return whether type dtype can be used as the base type of a + memoryview slice. + + We support structs, numeric types and objects + """ + if dtype.is_complex and dtype.real_type.is_int: + return False + + if dtype is PyrexTypes.c_bint_type: + return False + + if dtype.is_struct and dtype.kind == 'struct': + for member in dtype.scope.var_entries: + if not valid_memslice_dtype(member.type): + return False + + return True + + return ( + dtype.is_error or + # Pointers are not valid (yet) + # (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or + (dtype.is_array and i < 8 and + valid_memslice_dtype(dtype.base_type, i + 1)) or + dtype.is_numeric or + dtype.is_pyobject or + dtype.is_fused or # accept this as it will be replaced by specializations later + (dtype.is_typedef and valid_memslice_dtype(dtype.typedef_base_type)) + ) + + +class MemoryViewSliceBufferEntry(Buffer.BufferEntry): """ May be used during code generation time to be queried for shape/strides/suboffsets attributes, or to perform indexing or slicing. """ - 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 + 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 self.buf_ptr_type = PyrexTypes.CPtrType(dtype) self.init_attributes() - - def get_buf_suboffsetvars(self): - return self._for_all_ndim("%s.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 generate_buffer_lookup_code(self, code, index_cnames): - axes = [(dim, index_cnames[dim], access, packing) - for dim, (access, packing) in enumerate(self.type.axes)] - return self._generate_buffer_lookup_code(code, axes) - - def _generate_buffer_lookup_code(self, code, axes, cast_result=True): + + def get_buf_suboffsetvars(self): + return self._for_all_ndim("%s.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 generate_buffer_lookup_code(self, code, index_cnames): + axes = [(dim, index_cnames[dim], access, packing) + for dim, (access, packing) in enumerate(self.type.axes)] + return self._generate_buffer_lookup_code(code, axes) + + def _generate_buffer_lookup_code(self, code, axes, cast_result=True): """ Generate a single expression that indexes the memory view slice in each dimension. """ - bufp = self.buf_ptr + bufp = self.buf_ptr type_decl = self.type.dtype.empty_declaration_code() - - for dim, index, access, packing in axes: - shape = "%s.shape[%d]" % (self.cname, dim) - stride = "%s.strides[%d]" % (self.cname, dim) - suboffset = "%s.suboffsets[%d]" % (self.cname, dim) - - flag = get_memoryview_flag(access, packing) - - if flag in ("generic", "generic_contiguous"): - # Note: we cannot do cast tricks to avoid stride multiplication - # for generic_contiguous, as we may have to do (dtype *) - # or (dtype **) arithmetic, we won't know which unless - # we check suboffsets - code.globalstate.use_utility_code(memviewslice_index_helpers) - bufp = ('__pyx_memviewslice_index_full(%s, %s, %s, %s)' % - (bufp, index, stride, suboffset)) - - elif flag == "indirect": - bufp = "(%s + %s * %s)" % (bufp, index, stride) - bufp = ("(*((char **) %s) + %s)" % (bufp, suboffset)) - - elif flag == "indirect_contiguous": - # Note: we do char ** arithmetic - bufp = "(*((char **) %s + %s) + %s)" % (bufp, index, suboffset) - - elif flag == "strided": - bufp = "(%s + %s * %s)" % (bufp, index, stride) - - else: - assert flag == 'contiguous', flag - bufp = '((char *) (((%s *) %s) + %s))' % (type_decl, bufp, index) - - bufp = '( /* dim=%d */ %s )' % (dim, bufp) - - if cast_result: - return "((%s *) %s)" % (type_decl, bufp) - - return bufp - - def generate_buffer_slice_code(self, code, indices, dst, have_gil, - have_slices, directives): - """ - Slice a memoryviewslice. - - indices - list of index nodes. If not a SliceNode, or NoneNode, - then it must be coercible to Py_ssize_t - - Simply call __pyx_memoryview_slice_memviewslice with the right + + for dim, index, access, packing in axes: + shape = "%s.shape[%d]" % (self.cname, dim) + stride = "%s.strides[%d]" % (self.cname, dim) + suboffset = "%s.suboffsets[%d]" % (self.cname, dim) + + flag = get_memoryview_flag(access, packing) + + if flag in ("generic", "generic_contiguous"): + # Note: we cannot do cast tricks to avoid stride multiplication + # for generic_contiguous, as we may have to do (dtype *) + # or (dtype **) arithmetic, we won't know which unless + # we check suboffsets + code.globalstate.use_utility_code(memviewslice_index_helpers) + bufp = ('__pyx_memviewslice_index_full(%s, %s, %s, %s)' % + (bufp, index, stride, suboffset)) + + elif flag == "indirect": + bufp = "(%s + %s * %s)" % (bufp, index, stride) + bufp = ("(*((char **) %s) + %s)" % (bufp, suboffset)) + + elif flag == "indirect_contiguous": + # Note: we do char ** arithmetic + bufp = "(*((char **) %s + %s) + %s)" % (bufp, index, suboffset) + + elif flag == "strided": + bufp = "(%s + %s * %s)" % (bufp, index, stride) + + else: + assert flag == 'contiguous', flag + bufp = '((char *) (((%s *) %s) + %s))' % (type_decl, bufp, index) + + bufp = '( /* dim=%d */ %s )' % (dim, bufp) + + if cast_result: + return "((%s *) %s)" % (type_decl, bufp) + + return bufp + + def generate_buffer_slice_code(self, code, indices, dst, have_gil, + have_slices, directives): + """ + Slice a memoryviewslice. + + indices - list of index nodes. If not a SliceNode, or NoneNode, + then it must be coercible to Py_ssize_t + + Simply call __pyx_memoryview_slice_memviewslice with the right arguments, unless the dimension is omitted or a bare ':', in which case we copy over the shape/strides/suboffsets attributes directly for that dimension. - """ - src = self.cname - - code.putln("%(dst)s.data = %(src)s.data;" % locals()) - code.putln("%(dst)s.memview = %(src)s.memview;" % locals()) - code.put_incref_memoryviewslice(dst) - + """ + src = self.cname + + code.putln("%(dst)s.data = %(src)s.data;" % locals()) + code.putln("%(dst)s.memview = %(src)s.memview;" % locals()) + code.put_incref_memoryviewslice(dst) + all_dimensions_direct = all(access == 'direct' for access, packing in self.type.axes) suboffset_dim_temp = [] @@ -278,9 +278,9 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry): suboffset_dim_temp.append(suboffset_dim) return suboffset_dim_temp[0] - dim = -1 + dim = -1 new_ndim = 0 - for index in indices: + for index in indices: if index.is_none: # newaxis for attrib, value in [('shape', 1), ('strides', 0), ('suboffsets', -1)]: @@ -291,37 +291,37 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry): dim += 1 access, packing = self.type.axes[dim] - - if isinstance(index, ExprNodes.SliceNode): - # slice, unspecified dimension, or part of ellipsis + + if isinstance(index, ExprNodes.SliceNode): + # slice, unspecified dimension, or part of ellipsis d = dict(locals()) - for s in "start stop step".split(): - idx = getattr(index, s) - have_idx = d['have_' + s] = not idx.is_none + for s in "start stop step".split(): + idx = getattr(index, s) + have_idx = d['have_' + s] = not idx.is_none d[s] = idx.result() if have_idx else "0" - + if not (d['have_start'] or d['have_stop'] or d['have_step']): - # full slice (:), simply copy over the extent, stride - # and suboffset. Also update suboffset_dim if needed - d['access'] = access + # full slice (:), simply copy over the extent, stride + # and suboffset. Also update suboffset_dim if needed + d['access'] = access util_name = "SimpleSlice" - else: + else: util_name = "ToughSlice" d['error_goto'] = code.error_goto(index.pos) - - new_ndim += 1 - else: - # normal index - idx = index.result() - + + new_ndim += 1 + else: + # normal index + idx = index.result() + indirect = access != 'direct' if indirect: generic = access == 'full' - if new_ndim != 0: - return error(index.pos, - "All preceding dimensions must be " - "indexed and not sliced") - + if new_ndim != 0: + return error(index.pos, + "All preceding dimensions must be " + "indexed and not sliced") + d = dict( locals(), wraparound=int(directives['wraparound']), @@ -330,529 +330,529 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry): if d['boundscheck']: d['error_goto'] = code.error_goto(index.pos) util_name = "SliceIndex" - + _, impl = TempitaUtilityCode.load_as_string(util_name, "MemoryView_C.c", context=d) code.put(impl) - + if suboffset_dim_temp: code.funcstate.release_temp(suboffset_dim_temp[0]) + - -def empty_slice(pos): - none = ExprNodes.NoneNode(pos) - return ExprNodes.SliceNode(pos, start=none, - stop=none, step=none) - +def empty_slice(pos): + none = ExprNodes.NoneNode(pos) + return ExprNodes.SliceNode(pos, start=none, + stop=none, step=none) + def unellipsify(indices, ndim): - result = [] - seen_ellipsis = False - have_slices = False - + result = [] + seen_ellipsis = False + have_slices = False + newaxes = [newaxis for newaxis in indices if newaxis.is_none] - n_indices = len(indices) - len(newaxes) - - for index in indices: - if isinstance(index, ExprNodes.EllipsisNode): - have_slices = True - full_slice = empty_slice(index.pos) - - if seen_ellipsis: - result.append(full_slice) - else: - nslices = ndim - n_indices + 1 - result.extend([full_slice] * nslices) - seen_ellipsis = True - else: + n_indices = len(indices) - len(newaxes) + + for index in indices: + if isinstance(index, ExprNodes.EllipsisNode): + have_slices = True + full_slice = empty_slice(index.pos) + + if seen_ellipsis: + result.append(full_slice) + else: + nslices = ndim - n_indices + 1 + result.extend([full_slice] * nslices) + seen_ellipsis = True + else: have_slices = have_slices or index.is_slice or index.is_none - result.append(index) - - result_length = len(result) - len(newaxes) - if result_length < ndim: - have_slices = True - nslices = ndim - result_length - result.extend([empty_slice(indices[-1].pos)] * nslices) - + result.append(index) + + result_length = len(result) - len(newaxes) + if result_length < ndim: + have_slices = True + nslices = ndim - result_length + result.extend([empty_slice(indices[-1].pos)] * nslices) + return have_slices, result, newaxes - - -def get_memoryview_flag(access, packing): - if access == 'full' and packing in ('strided', 'follow'): - return 'generic' - elif access == 'full' and packing == 'contig': - return 'generic_contiguous' - elif access == 'ptr' and packing in ('strided', 'follow'): - return 'indirect' - elif access == 'ptr' and packing == 'contig': - return 'indirect_contiguous' - elif access == 'direct' and packing in ('strided', 'follow'): - return 'strided' - else: - assert (access, packing) == ('direct', 'contig'), (access, packing) - return 'contiguous' - + + +def get_memoryview_flag(access, packing): + if access == 'full' and packing in ('strided', 'follow'): + return 'generic' + elif access == 'full' and packing == 'contig': + return 'generic_contiguous' + elif access == 'ptr' and packing in ('strided', 'follow'): + return 'indirect' + elif access == 'ptr' and packing == 'contig': + return 'indirect_contiguous' + elif access == 'direct' and packing in ('strided', 'follow'): + return 'strided' + else: + assert (access, packing) == ('direct', 'contig'), (access, packing) + return 'contiguous' + def get_is_contig_func_name(contig_type, ndim): assert contig_type in ('C', 'F') return "__pyx_memviewslice_is_contig_%s%d" % (contig_type, ndim) - + def get_is_contig_utility(contig_type, ndim): assert contig_type in ('C', 'F') C = dict(context, ndim=ndim, contig_type=contig_type) utility = load_memview_c_utility("MemviewSliceCheckContig", C, requires=[is_contig_utility]) - return utility - + return utility + def slice_iter(slice_type, slice_result, ndim, code): if slice_type.is_c_contig or slice_type.is_f_contig: return ContigSliceIter(slice_type, slice_result, ndim, code) - else: + else: return StridedSliceIter(slice_type, slice_result, ndim, code) - - -class SliceIter(object): + + +class SliceIter(object): def __init__(self, slice_type, slice_result, ndim, code): - self.slice_type = slice_type + self.slice_type = slice_type self.slice_result = slice_result - self.code = code - self.ndim = ndim - - -class ContigSliceIter(SliceIter): - def start_loops(self): - code = self.code - code.begin_block() - + self.code = code + self.ndim = ndim + + +class ContigSliceIter(SliceIter): + def start_loops(self): + code = self.code + code.begin_block() + type_decl = self.slice_type.dtype.empty_declaration_code() - + total_size = ' * '.join("%s.shape[%d]" % (self.slice_result, i) for i in range(self.ndim)) - code.putln("Py_ssize_t __pyx_temp_extent = %s;" % total_size) - code.putln("Py_ssize_t __pyx_temp_idx;") - code.putln("%s *__pyx_temp_pointer = (%s *) %s.data;" % ( + code.putln("Py_ssize_t __pyx_temp_extent = %s;" % total_size) + code.putln("Py_ssize_t __pyx_temp_idx;") + code.putln("%s *__pyx_temp_pointer = (%s *) %s.data;" % ( type_decl, type_decl, self.slice_result)) - code.putln("for (__pyx_temp_idx = 0; " - "__pyx_temp_idx < __pyx_temp_extent; " - "__pyx_temp_idx++) {") - - return "__pyx_temp_pointer" - - def end_loops(self): - self.code.putln("__pyx_temp_pointer += 1;") - self.code.putln("}") - self.code.end_block() - - -class StridedSliceIter(SliceIter): - def start_loops(self): - code = self.code - code.begin_block() - - for i in range(self.ndim): + code.putln("for (__pyx_temp_idx = 0; " + "__pyx_temp_idx < __pyx_temp_extent; " + "__pyx_temp_idx++) {") + + return "__pyx_temp_pointer" + + def end_loops(self): + self.code.putln("__pyx_temp_pointer += 1;") + self.code.putln("}") + self.code.end_block() + + +class StridedSliceIter(SliceIter): + def start_loops(self): + code = self.code + code.begin_block() + + for i in range(self.ndim): t = i, self.slice_result, i - code.putln("Py_ssize_t __pyx_temp_extent_%d = %s.shape[%d];" % t) - code.putln("Py_ssize_t __pyx_temp_stride_%d = %s.strides[%d];" % t) - code.putln("char *__pyx_temp_pointer_%d;" % i) - code.putln("Py_ssize_t __pyx_temp_idx_%d;" % i) - + code.putln("Py_ssize_t __pyx_temp_extent_%d = %s.shape[%d];" % t) + code.putln("Py_ssize_t __pyx_temp_stride_%d = %s.strides[%d];" % t) + code.putln("char *__pyx_temp_pointer_%d;" % i) + code.putln("Py_ssize_t __pyx_temp_idx_%d;" % i) + code.putln("__pyx_temp_pointer_0 = %s.data;" % self.slice_result) - - for i in range(self.ndim): - if i > 0: - code.putln("__pyx_temp_pointer_%d = __pyx_temp_pointer_%d;" % (i, i - 1)) - - code.putln("for (__pyx_temp_idx_%d = 0; " - "__pyx_temp_idx_%d < __pyx_temp_extent_%d; " - "__pyx_temp_idx_%d++) {" % (i, i, i, i)) - - return "__pyx_temp_pointer_%d" % (self.ndim - 1) - - def end_loops(self): - code = self.code - for i in range(self.ndim - 1, -1, -1): - code.putln("__pyx_temp_pointer_%d += __pyx_temp_stride_%d;" % (i, i)) - code.putln("}") - - code.end_block() - - -def copy_c_or_fortran_cname(memview): - if memview.is_c_contig: - c_or_f = 'c' - else: - c_or_f = 'f' - - return "__pyx_memoryview_copy_slice_%s_%s" % ( - memview.specialization_suffix(), c_or_f) - - -def get_copy_new_utility(pos, from_memview, to_memview): + + for i in range(self.ndim): + if i > 0: + code.putln("__pyx_temp_pointer_%d = __pyx_temp_pointer_%d;" % (i, i - 1)) + + code.putln("for (__pyx_temp_idx_%d = 0; " + "__pyx_temp_idx_%d < __pyx_temp_extent_%d; " + "__pyx_temp_idx_%d++) {" % (i, i, i, i)) + + return "__pyx_temp_pointer_%d" % (self.ndim - 1) + + def end_loops(self): + code = self.code + for i in range(self.ndim - 1, -1, -1): + code.putln("__pyx_temp_pointer_%d += __pyx_temp_stride_%d;" % (i, i)) + code.putln("}") + + code.end_block() + + +def copy_c_or_fortran_cname(memview): + if memview.is_c_contig: + c_or_f = 'c' + else: + c_or_f = 'f' + + return "__pyx_memoryview_copy_slice_%s_%s" % ( + memview.specialization_suffix(), c_or_f) + + +def get_copy_new_utility(pos, from_memview, to_memview): if (from_memview.dtype != to_memview.dtype and not (from_memview.dtype.is_const and from_memview.dtype.const_base_type == to_memview.dtype)): error(pos, "dtypes must be the same!") return - if len(from_memview.axes) != len(to_memview.axes): + if len(from_memview.axes) != len(to_memview.axes): error(pos, "number of dimensions must be same") return - if not (to_memview.is_c_contig or to_memview.is_f_contig): + if not (to_memview.is_c_contig or to_memview.is_f_contig): error(pos, "to_memview must be c or f contiguous.") return - - for (access, packing) in from_memview.axes: - if access != 'direct': + + for (access, packing) in from_memview.axes: + if access != 'direct': error(pos, "cannot handle 'full' or 'ptr' access at this time.") return - - if to_memview.is_c_contig: - mode = 'c' - contig_flag = memview_c_contiguous - elif to_memview.is_f_contig: - mode = 'fortran' - contig_flag = memview_f_contiguous - - return load_memview_c_utility( - "CopyContentsUtility", - context=dict( - context, - mode=mode, + + if to_memview.is_c_contig: + mode = 'c' + contig_flag = memview_c_contiguous + elif to_memview.is_f_contig: + mode = 'fortran' + contig_flag = memview_f_contiguous + + return load_memview_c_utility( + "CopyContentsUtility", + context=dict( + context, + mode=mode, dtype_decl=to_memview.dtype.empty_declaration_code(), - contig_flag=contig_flag, - ndim=to_memview.ndim, - func_cname=copy_c_or_fortran_cname(to_memview), - dtype_is_object=int(to_memview.dtype.is_pyobject)), - requires=[copy_contents_new_utility]) - - -def get_axes_specs(env, axes): - ''' - get_axes_specs(env, axes) -> list of (access, packing) specs for each axis. - access is one of 'full', 'ptr' or 'direct' - packing is one of 'contig', 'strided' or 'follow' - ''' - - cythonscope = env.global_scope().context.cython_scope - cythonscope.load_cythonscope() - viewscope = cythonscope.viewscope - - access_specs = tuple([viewscope.lookup(name) - for name in ('full', 'direct', 'ptr')]) - packing_specs = tuple([viewscope.lookup(name) - for name in ('contig', 'strided', 'follow')]) - - is_f_contig, is_c_contig = False, False - default_access, default_packing = 'direct', 'strided' - cf_access, cf_packing = default_access, 'follow' - - axes_specs = [] - # analyse all axes. - for idx, axis in enumerate(axes): - if not axis.start.is_none: - raise CompileError(axis.start.pos, START_ERR) - - if not axis.stop.is_none: - raise CompileError(axis.stop.pos, STOP_ERR) - - if axis.step.is_none: - axes_specs.append((default_access, default_packing)) - - elif isinstance(axis.step, IntNode): - # the packing for the ::1 axis is contiguous, - # all others are cf_packing. - if axis.step.compile_time_value(env) != 1: - raise CompileError(axis.step.pos, STEP_ERR) - - axes_specs.append((cf_access, 'cfcontig')) - - elif isinstance(axis.step, (NameNode, AttributeNode)): - entry = _get_resolved_spec(env, axis.step) - if entry.name in view_constant_to_access_packing: - axes_specs.append(view_constant_to_access_packing[entry.name]) - else: + contig_flag=contig_flag, + ndim=to_memview.ndim, + func_cname=copy_c_or_fortran_cname(to_memview), + dtype_is_object=int(to_memview.dtype.is_pyobject)), + requires=[copy_contents_new_utility]) + + +def get_axes_specs(env, axes): + ''' + get_axes_specs(env, axes) -> list of (access, packing) specs for each axis. + access is one of 'full', 'ptr' or 'direct' + packing is one of 'contig', 'strided' or 'follow' + ''' + + cythonscope = env.global_scope().context.cython_scope + cythonscope.load_cythonscope() + viewscope = cythonscope.viewscope + + access_specs = tuple([viewscope.lookup(name) + for name in ('full', 'direct', 'ptr')]) + packing_specs = tuple([viewscope.lookup(name) + for name in ('contig', 'strided', 'follow')]) + + is_f_contig, is_c_contig = False, False + default_access, default_packing = 'direct', 'strided' + cf_access, cf_packing = default_access, 'follow' + + axes_specs = [] + # analyse all axes. + for idx, axis in enumerate(axes): + if not axis.start.is_none: + raise CompileError(axis.start.pos, START_ERR) + + if not axis.stop.is_none: + raise CompileError(axis.stop.pos, STOP_ERR) + + if axis.step.is_none: + axes_specs.append((default_access, default_packing)) + + elif isinstance(axis.step, IntNode): + # the packing for the ::1 axis is contiguous, + # all others are cf_packing. + if axis.step.compile_time_value(env) != 1: + raise CompileError(axis.step.pos, STEP_ERR) + + axes_specs.append((cf_access, 'cfcontig')) + + elif isinstance(axis.step, (NameNode, AttributeNode)): + entry = _get_resolved_spec(env, axis.step) + if entry.name in view_constant_to_access_packing: + axes_specs.append(view_constant_to_access_packing[entry.name]) + else: raise CompileError(axis.step.pos, INVALID_ERR) - - else: - raise CompileError(axis.step.pos, INVALID_ERR) - - # First, find out if we have a ::1 somewhere - contig_dim = 0 - is_contig = False - for idx, (access, packing) in enumerate(axes_specs): - if packing == 'cfcontig': - if is_contig: - raise CompileError(axis.step.pos, BOTH_CF_ERR) - - contig_dim = idx - axes_specs[idx] = (access, 'contig') - is_contig = True - - if is_contig: - # We have a ::1 somewhere, see if we're C or Fortran contiguous - if contig_dim == len(axes) - 1: - is_c_contig = True - else: - is_f_contig = True - - if contig_dim and not axes_specs[contig_dim - 1][0] in ('full', 'ptr'): - raise CompileError(axes[contig_dim].pos, - "Fortran contiguous specifier must follow an indirect dimension") - - if is_c_contig: - # Contiguous in the last dimension, find the last indirect dimension - contig_dim = -1 - for idx, (access, packing) in enumerate(reversed(axes_specs)): - if access in ('ptr', 'full'): - contig_dim = len(axes) - idx - 1 - - # Replace 'strided' with 'follow' for any dimension following the last - # indirect dimension, the first dimension or the dimension following - # the ::1. - # int[::indirect, ::1, :, :] - # ^ ^ - # int[::indirect, :, :, ::1] - # ^ ^ - start = contig_dim + 1 - stop = len(axes) - is_c_contig - for idx, (access, packing) in enumerate(axes_specs[start:stop]): - idx = contig_dim + 1 + idx - if access != 'direct': - raise CompileError(axes[idx].pos, - "Indirect dimension may not follow " - "Fortran contiguous dimension") - if packing == 'contig': - raise CompileError(axes[idx].pos, - "Dimension may not be contiguous") - axes_specs[idx] = (access, cf_packing) - - if is_c_contig: - # For C contiguity, we need to fix the 'contig' dimension - # after the loop - a, p = axes_specs[-1] - axes_specs[-1] = a, 'contig' - - validate_axes_specs([axis.start.pos for axis in axes], - axes_specs, - is_c_contig, - is_f_contig) - - return axes_specs - - -def validate_axes(pos, axes): - if len(axes) >= Options.buffer_max_dims: - error(pos, "More dimensions than the maximum number" - " of buffer dimensions were used.") - return False - - return True - - -def is_cf_contig(specs): - is_c_contig = is_f_contig = False - - if len(specs) == 1 and specs == [('direct', 'contig')]: - is_c_contig = True - - 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] == ('direct','contig') and - all(axis == ('direct','follow') for axis in specs[1:])): - # f_contiguous: 'contig', 'follow', 'follow', ..., 'follow' - is_f_contig = True - - 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' - -view_constant_to_access_packing = { - 'generic': ('full', 'strided'), - 'strided': ('direct', 'strided'), - 'indirect': ('ptr', 'strided'), - 'generic_contiguous': ('full', 'contig'), - 'contiguous': ('direct', 'contig'), - 'indirect_contiguous': ('ptr', 'contig'), -} - -def validate_axes_specs(positions, specs, is_c_contig, is_f_contig): - - packing_specs = ('contig', 'strided', 'follow') - access_specs = ('direct', 'ptr', 'full') - - # is_c_contig, is_f_contig = is_cf_contig(specs) - - has_contig = has_follow = has_strided = has_generic_contig = False - - last_indirect_dimension = -1 - for idx, (access, packing) in enumerate(specs): - if access == 'ptr': - last_indirect_dimension = idx - + + else: + raise CompileError(axis.step.pos, INVALID_ERR) + + # First, find out if we have a ::1 somewhere + contig_dim = 0 + is_contig = False + for idx, (access, packing) in enumerate(axes_specs): + if packing == 'cfcontig': + if is_contig: + raise CompileError(axis.step.pos, BOTH_CF_ERR) + + contig_dim = idx + axes_specs[idx] = (access, 'contig') + is_contig = True + + if is_contig: + # We have a ::1 somewhere, see if we're C or Fortran contiguous + if contig_dim == len(axes) - 1: + is_c_contig = True + else: + is_f_contig = True + + if contig_dim and not axes_specs[contig_dim - 1][0] in ('full', 'ptr'): + raise CompileError(axes[contig_dim].pos, + "Fortran contiguous specifier must follow an indirect dimension") + + if is_c_contig: + # Contiguous in the last dimension, find the last indirect dimension + contig_dim = -1 + for idx, (access, packing) in enumerate(reversed(axes_specs)): + if access in ('ptr', 'full'): + contig_dim = len(axes) - idx - 1 + + # Replace 'strided' with 'follow' for any dimension following the last + # indirect dimension, the first dimension or the dimension following + # the ::1. + # int[::indirect, ::1, :, :] + # ^ ^ + # int[::indirect, :, :, ::1] + # ^ ^ + start = contig_dim + 1 + stop = len(axes) - is_c_contig + for idx, (access, packing) in enumerate(axes_specs[start:stop]): + idx = contig_dim + 1 + idx + if access != 'direct': + raise CompileError(axes[idx].pos, + "Indirect dimension may not follow " + "Fortran contiguous dimension") + if packing == 'contig': + raise CompileError(axes[idx].pos, + "Dimension may not be contiguous") + axes_specs[idx] = (access, cf_packing) + + if is_c_contig: + # For C contiguity, we need to fix the 'contig' dimension + # after the loop + a, p = axes_specs[-1] + axes_specs[-1] = a, 'contig' + + validate_axes_specs([axis.start.pos for axis in axes], + axes_specs, + is_c_contig, + is_f_contig) + + return axes_specs + + +def validate_axes(pos, axes): + if len(axes) >= Options.buffer_max_dims: + error(pos, "More dimensions than the maximum number" + " of buffer dimensions were used.") + return False + + return True + + +def is_cf_contig(specs): + is_c_contig = is_f_contig = False + + if len(specs) == 1 and specs == [('direct', 'contig')]: + is_c_contig = True + + 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] == ('direct','contig') and + all(axis == ('direct','follow') for axis in specs[1:])): + # f_contiguous: 'contig', 'follow', 'follow', ..., 'follow' + is_f_contig = True + + 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' + +view_constant_to_access_packing = { + 'generic': ('full', 'strided'), + 'strided': ('direct', 'strided'), + 'indirect': ('ptr', 'strided'), + 'generic_contiguous': ('full', 'contig'), + 'contiguous': ('direct', 'contig'), + 'indirect_contiguous': ('ptr', 'contig'), +} + +def validate_axes_specs(positions, specs, is_c_contig, is_f_contig): + + packing_specs = ('contig', 'strided', 'follow') + access_specs = ('direct', 'ptr', 'full') + + # is_c_contig, is_f_contig = is_cf_contig(specs) + + has_contig = has_follow = has_strided = has_generic_contig = False + + last_indirect_dimension = -1 + for idx, (access, packing) in enumerate(specs): + if access == 'ptr': + last_indirect_dimension = idx + for idx, (pos, (access, packing)) in enumerate(zip(positions, specs)): - - if not (access in access_specs and - packing in packing_specs): - raise CompileError(pos, "Invalid axes specification.") - - if packing == 'strided': - has_strided = True - elif packing == 'contig': - if has_contig: - raise CompileError(pos, "Only one direct contiguous " - "axis may be specified.") - - valid_contig_dims = last_indirect_dimension + 1, len(specs) - 1 - if idx not in valid_contig_dims and access != 'ptr': - if last_indirect_dimension + 1 != len(specs) - 1: - dims = "dimensions %d and %d" % valid_contig_dims - else: - dims = "dimension %d" % valid_contig_dims[0] - - raise CompileError(pos, "Only %s may be contiguous and direct" % dims) - - has_contig = access != 'ptr' - elif packing == 'follow': - if has_strided: - raise CompileError(pos, "A memoryview cannot have both follow and strided axis specifiers.") - if not (is_c_contig or is_f_contig): - raise CompileError(pos, "Invalid use of the follow specifier.") - - if access in ('ptr', 'full'): - has_strided = False - -def _get_resolved_spec(env, spec): - # spec must be a NameNode or an AttributeNode - if isinstance(spec, NameNode): - return _resolve_NameNode(env, spec) - elif isinstance(spec, AttributeNode): - return _resolve_AttributeNode(env, spec) - else: - raise CompileError(spec.pos, INVALID_ERR) - -def _resolve_NameNode(env, node): - try: - resolved_name = env.lookup(node.name).name - except AttributeError: - raise CompileError(node.pos, INVALID_ERR) - - viewscope = env.global_scope().context.cython_scope.viewscope - entry = viewscope.lookup(resolved_name) - if entry is None: - raise CompileError(node.pos, NOT_CIMPORTED_ERR) - - return entry - -def _resolve_AttributeNode(env, node): - path = [] - while isinstance(node, AttributeNode): - path.insert(0, node.attribute) - node = node.obj - if isinstance(node, NameNode): - path.insert(0, node.name) - else: - raise CompileError(node.pos, EXPR_ERR) - modnames = path[:-1] - # must be at least 1 module name, o/w not an AttributeNode. - assert modnames - - scope = env - for modname in modnames: - mod = scope.lookup(modname) - if not mod or not mod.as_module: - raise CompileError( - node.pos, "undeclared name not builtin: %s" % modname) - scope = mod.as_module - - entry = scope.lookup(path[-1]) - if not entry: - raise CompileError(node.pos, "No such attribute '%s'" % path[-1]) - - return entry - -# -### Utility loading -# - -def load_memview_cy_utility(util_code_name, context=None, **kwargs): - return CythonUtilityCode.load(util_code_name, "MemoryView.pyx", - context=context, **kwargs) - -def load_memview_c_utility(util_code_name, context=None, **kwargs): - if context is None: - return UtilityCode.load(util_code_name, "MemoryView_C.c", **kwargs) - else: - return TempitaUtilityCode.load(util_code_name, "MemoryView_C.c", - context=context, **kwargs) - -def use_cython_array_utility_code(env): - cython_scope = env.global_scope().context.cython_scope - cython_scope.load_cythonscope() - cython_scope.viewscope.lookup('array_cwrapper').used = True - -context = { - 'memview_struct_name': memview_objstruct_cname, - 'max_dims': Options.buffer_max_dims, - 'memviewslice_name': memviewslice_cname, - 'memslice_init': memslice_entry_init, -} -memviewslice_declare_code = load_memview_c_utility( - "MemviewSliceStruct", - context=context, - requires=[]) - + + if not (access in access_specs and + packing in packing_specs): + raise CompileError(pos, "Invalid axes specification.") + + if packing == 'strided': + has_strided = True + elif packing == 'contig': + if has_contig: + raise CompileError(pos, "Only one direct contiguous " + "axis may be specified.") + + valid_contig_dims = last_indirect_dimension + 1, len(specs) - 1 + if idx not in valid_contig_dims and access != 'ptr': + if last_indirect_dimension + 1 != len(specs) - 1: + dims = "dimensions %d and %d" % valid_contig_dims + else: + dims = "dimension %d" % valid_contig_dims[0] + + raise CompileError(pos, "Only %s may be contiguous and direct" % dims) + + has_contig = access != 'ptr' + elif packing == 'follow': + if has_strided: + raise CompileError(pos, "A memoryview cannot have both follow and strided axis specifiers.") + if not (is_c_contig or is_f_contig): + raise CompileError(pos, "Invalid use of the follow specifier.") + + if access in ('ptr', 'full'): + has_strided = False + +def _get_resolved_spec(env, spec): + # spec must be a NameNode or an AttributeNode + if isinstance(spec, NameNode): + return _resolve_NameNode(env, spec) + elif isinstance(spec, AttributeNode): + return _resolve_AttributeNode(env, spec) + else: + raise CompileError(spec.pos, INVALID_ERR) + +def _resolve_NameNode(env, node): + try: + resolved_name = env.lookup(node.name).name + except AttributeError: + raise CompileError(node.pos, INVALID_ERR) + + viewscope = env.global_scope().context.cython_scope.viewscope + entry = viewscope.lookup(resolved_name) + if entry is None: + raise CompileError(node.pos, NOT_CIMPORTED_ERR) + + return entry + +def _resolve_AttributeNode(env, node): + path = [] + while isinstance(node, AttributeNode): + path.insert(0, node.attribute) + node = node.obj + if isinstance(node, NameNode): + path.insert(0, node.name) + else: + raise CompileError(node.pos, EXPR_ERR) + modnames = path[:-1] + # must be at least 1 module name, o/w not an AttributeNode. + assert modnames + + scope = env + for modname in modnames: + mod = scope.lookup(modname) + if not mod or not mod.as_module: + raise CompileError( + node.pos, "undeclared name not builtin: %s" % modname) + scope = mod.as_module + + entry = scope.lookup(path[-1]) + if not entry: + raise CompileError(node.pos, "No such attribute '%s'" % path[-1]) + + return entry + +# +### Utility loading +# + +def load_memview_cy_utility(util_code_name, context=None, **kwargs): + return CythonUtilityCode.load(util_code_name, "MemoryView.pyx", + context=context, **kwargs) + +def load_memview_c_utility(util_code_name, context=None, **kwargs): + if context is None: + return UtilityCode.load(util_code_name, "MemoryView_C.c", **kwargs) + else: + return TempitaUtilityCode.load(util_code_name, "MemoryView_C.c", + context=context, **kwargs) + +def use_cython_array_utility_code(env): + cython_scope = env.global_scope().context.cython_scope + cython_scope.load_cythonscope() + cython_scope.viewscope.lookup('array_cwrapper').used = True + +context = { + 'memview_struct_name': memview_objstruct_cname, + 'max_dims': Options.buffer_max_dims, + 'memviewslice_name': memviewslice_cname, + 'memslice_init': memslice_entry_init, +} +memviewslice_declare_code = load_memview_c_utility( + "MemviewSliceStruct", + context=context, + requires=[]) + atomic_utility = load_memview_c_utility("Atomics", context) - -memviewslice_init_code = load_memview_c_utility( - "MemviewSliceInit", - context=dict(context, BUF_MAX_NDIMS=Options.buffer_max_dims), - requires=[memviewslice_declare_code, - atomic_utility], -) - -memviewslice_index_helpers = load_memview_c_utility("MemviewSliceIndex") - -typeinfo_to_format_code = load_memview_cy_utility( - "BufferFormatFromTypeInfo", requires=[Buffer._typeinfo_to_format_code]) - -is_contig_utility = load_memview_c_utility("MemviewSliceIsContig", context) -overlapping_utility = load_memview_c_utility("OverlappingSlices", context) -copy_contents_new_utility = load_memview_c_utility( - "MemviewSliceCopyTemplate", - context, - requires=[], # require cython_array_utility_code -) - -view_utility_code = load_memview_cy_utility( - "View.MemoryView", - context=context, - requires=[Buffer.GetAndReleaseBufferUtilityCode(), - Buffer.buffer_struct_declare_code, + +memviewslice_init_code = load_memview_c_utility( + "MemviewSliceInit", + context=dict(context, BUF_MAX_NDIMS=Options.buffer_max_dims), + requires=[memviewslice_declare_code, + atomic_utility], +) + +memviewslice_index_helpers = load_memview_c_utility("MemviewSliceIndex") + +typeinfo_to_format_code = load_memview_cy_utility( + "BufferFormatFromTypeInfo", requires=[Buffer._typeinfo_to_format_code]) + +is_contig_utility = load_memview_c_utility("MemviewSliceIsContig", context) +overlapping_utility = load_memview_c_utility("OverlappingSlices", context) +copy_contents_new_utility = load_memview_c_utility( + "MemviewSliceCopyTemplate", + context, + requires=[], # require cython_array_utility_code +) + +view_utility_code = load_memview_cy_utility( + "View.MemoryView", + context=context, + requires=[Buffer.GetAndReleaseBufferUtilityCode(), + Buffer.buffer_struct_declare_code, Buffer.buffer_formats_declare_code, - memviewslice_init_code, - is_contig_utility, - overlapping_utility, - copy_contents_new_utility, - ModuleNode.capsule_utility_code], -) -view_utility_whitelist = ('array', 'memoryview', 'array_cwrapper', - 'generic', 'strided', 'indirect', 'contiguous', - 'indirect_contiguous') - -memviewslice_declare_code.requires.append(view_utility_code) -copy_contents_new_utility.requires.append(view_utility_code) + memviewslice_init_code, + is_contig_utility, + overlapping_utility, + copy_contents_new_utility, + ModuleNode.capsule_utility_code], +) +view_utility_whitelist = ('array', 'memoryview', 'array_cwrapper', + 'generic', 'strided', 'indirect', 'contiguous', + 'indirect_contiguous') + +memviewslice_declare_code.requires.append(view_utility_code) +copy_contents_new_utility.requires.append(view_utility_code) |