Commit b7d6e693 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge remote-tracking branch 'main/release'

parents 449e3b58 b8a87f10
......@@ -13,6 +13,7 @@ cython.declare(error=object, warning=object, warn_once=object, InternalError=obj
debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object)
import sys
import copy
import operator
from Errors import error, warning, warn_once, InternalError, CompileError
......@@ -33,6 +34,8 @@ import Symtab
import Options
from Cython import Utils
from Annotate import AnnotationItem
from NumpySupport import numpy_transform_attribute_node, \
should_apply_numpy_hack
from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
......@@ -488,11 +491,21 @@ class ExprNode(Node):
# ---------------- Code Generation -----------------
def make_owned_reference(self, code):
# If result is a pyobject, make sure we own
# a reference to it.
"""
If result is a pyobject, make sure we own a reference to it.
If the result is in a temp, it is already a new reference.
"""
if self.type.is_pyobject and not self.result_in_temp():
code.put_incref(self.result(), self.ctype())
def make_owned_memoryviewslice(self, code):
"""
Make sure we own the reference to this memoryview slice.
"""
if not self.result_in_temp():
code.put_incref_memoryviewslice(self.result(),
have_gil=self.in_nogil_context)
def generate_evaluation_code(self, code):
code.mark_pos(self.pos)
......@@ -623,7 +636,7 @@ class ExprNode(Node):
return self
if src_type.is_fused:
error(self.pos, "Type is not specific")
error(self.pos, "Type is not specialized")
else:
error(self.pos, "Cannot coerce to a type that is not specialized")
......@@ -2586,8 +2599,9 @@ class IndexNode(ExprNode):
self.nogil = env.nogil
if buffer_access or self.memslice_index:
if self.base.type.is_memoryviewslice and not self.base.is_name:
self.base = self.base.coerce_to_temp(env)
#if self.base.type.is_memoryviewslice and not self.base.is_name:
# self.base = self.base.coerce_to_temp(env)
self.base = self.base.coerce_to_simple(env)
self.indices = indices
self.index = None
......@@ -2724,7 +2738,7 @@ class IndexNode(ExprNode):
specific_types = []
positions = []
if self.index.is_name:
if self.index.is_name or self.index.is_attribute:
positions.append(self.index.pos)
specific_types.append(self.index.analyse_as_type(env))
elif isinstance(self.index, TupleNode):
......@@ -3042,7 +3056,8 @@ class IndexNode(ExprNode):
if self.base.is_name:
entry = self.base.entry
else:
assert self.base.is_temp
# SimpleCallNode is_simple is not consistent with coerce_to_simple
assert self.base.is_simple() or self.base.is_temp
cname = self.base.result()
entry = Symtab.Entry(cname, cname, self.base.type, self.base.pos)
......@@ -3452,6 +3467,19 @@ class SliceNode(ExprNode):
if self.is_literal:
code.put_giveref(self.py_result())
def __deepcopy__(self, memo):
"""
There is a copy bug in python 2.4 for slice objects.
"""
return SliceNode(
self.pos,
start=copy.deepcopy(self.start, memo),
stop=copy.deepcopy(self.stop, memo),
step=copy.deepcopy(self.step, memo),
is_temp=self.is_temp,
is_literal=self.is_literal,
constant_result=self.constant_result)
class CallNode(ExprNode):
......@@ -4417,9 +4445,13 @@ class AttributeNode(ExprNode):
if entry:
if obj_type.is_extension_type and entry.name == "__weakref__":
error(self.pos, "Illegal use of special attribute __weakref__")
# methods need the normal attribute lookup
# def methods need the normal attribute lookup
# because they do not have struct entries
if entry.is_variable or entry.is_cmethod:
# fused function go through assignment synthesis
# (foo = pycfunction(foo_func_obj)) and need to go through
# regular Python lookup as well
if (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod:
self.type = entry.type
self.member = entry.cname
return
......@@ -4429,10 +4461,8 @@ class AttributeNode(ExprNode):
# attribute.
pass
# NumPy hack
if (getattr(self.obj, 'type', None) and
obj_type.is_extension_type and
obj_type.objstruct_cname == 'PyArrayObject'):
from NumpySupport import numpy_transform_attribute_node
if (getattr(self.obj, 'type', None) and obj_type.is_extension_type
and should_apply_numpy_hack(obj_type)):
replacement_node = numpy_transform_attribute_node(self)
# Since we can't actually replace our node yet, we only grasp its
# type, and then the replacement happens in
......@@ -4440,7 +4470,6 @@ class AttributeNode(ExprNode):
self.type = replacement_node.type
if replacement_node is not self:
return
# If we get here, the base object is not a struct/union/extension
# type, or it is an extension type and the attribute is either not
# declared or is declared as a Python method. Treat it as a Python
......@@ -7244,7 +7273,7 @@ class CythonArrayNode(ExprNode):
else:
return error()
if not base_type.same_as(array_dtype):
if not (base_type.same_as(array_dtype) or base_type.is_void):
return error(self.operand.pos, ERR_BASE_TYPE)
elif self.operand.type.is_array and len(array_dimension_sizes) != ndim:
return error(self.operand.pos,
......@@ -8912,6 +8941,10 @@ class CoercionNode(ExprNode):
code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
class CoerceToMemViewSliceNode(CoercionNode):
"""
Coerce an object to a memoryview slice. This holds a new reference in
a managed temp.
"""
def __init__(self, arg, dst_type, env):
assert dst_type.is_memoryviewslice
......
......@@ -24,6 +24,10 @@ module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_
verbose = 0
standard_include_path = os.path.abspath(os.path.normpath(
os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
class CompilationData(object):
# Bundles the information that is passed from transform to transform.
# (For now, this is only)
......@@ -70,8 +74,6 @@ class Context(object):
self.pxds = {} # full name -> node tree
standard_include_path = os.path.abspath(os.path.normpath(
os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
self.include_directories = include_directories + [standard_include_path]
self.set_language_level(language_level)
......
......@@ -86,7 +86,7 @@ def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
"We can avoid decreffing the lhs if we know it is the first assignment"
assert rhs.type.is_memoryviewslice
pretty_rhs = isinstance(rhs, NameNode) or rhs.result_in_temp()
pretty_rhs = rhs.result_in_temp() or rhs.is_simple()
if pretty_rhs:
rhstmp = rhs.result()
else:
......@@ -106,19 +106,11 @@ def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code
if not first_assignment:
code.put_xdecref_memoryviewslice(lhs_cname, have_gil=have_gil)
if rhs.is_name:
code.put_incref_memoryviewslice(rhs_cname, have_gil=have_gil)
if not rhs.result_in_temp():
rhs.make_owned_memoryviewslice(code)
code.putln("%s = %s;" % (lhs_cname, rhs_cname))
#code.putln("%s.memview = %s.memview;" % (lhs_cname, rhs_cname))
#code.putln("%s.data = %s.data;" % (lhs_cname, rhs_cname))
#for i in range(memviewslicetype.ndim):
# tup = (lhs_cname, i, rhs_cname, i)
# code.putln("%s.shape[%d] = %s.shape[%d];" % tup)
# code.putln("%s.strides[%d] = %s.strides[%d];" % tup)
# code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % tup)
def get_buf_flags(specs):
is_c_contig, is_f_contig = is_cf_contig(specs)
......@@ -888,7 +880,8 @@ context = {
memviewslice_declare_code = load_memview_c_utility(
"MemviewSliceStruct",
proto_block='utility_code_proto_before_types',
context=context)
context=context,
requires=[])
atomic_utility = load_memview_c_utility("Atomics", context,
proto_block='utility_code_proto_before_types')
......@@ -931,4 +924,5 @@ 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)
\ No newline at end of file
......@@ -988,18 +988,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = scope.parent_type
base_type = type.base_type
py_attrs = []
memviewslice_attrs = []
py_buffers = []
for entry in scope.var_entries:
if entry.type.is_pyobject:
py_attrs.append(entry)
elif entry.type.is_memoryviewslice:
memviewslice_attrs.append(entry)
elif entry.type == PyrexTypes.c_py_buffer_type:
py_buffers.append(entry)
have_entries, (py_attrs, py_buffers, memoryview_slices) = \
scope.get_refcounted_entries(include_weakref=True)
need_self_cast = type.vtabslot_cname or py_attrs or memviewslice_attrs or py_buffers
need_self_cast = type.vtabslot_cname or have_entries
code.putln("")
code.putln(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
......@@ -1044,7 +1036,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else:
code.put_init_var_to_py_none(entry, "p->%s", nanny=False)
for entry in memviewslice_attrs:
for entry in memoryview_slices:
code.putln("p->%s.data = NULL;" % entry.cname)
code.putln("p->%s.memview = NULL;" % entry.cname)
......@@ -1081,18 +1073,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"static void %s(PyObject *o) {"
% scope.mangle_internal("tp_dealloc"))
py_attrs = []
weakref_slot = scope.lookup_here("__weakref__")
for entry in scope.var_entries:
if entry.type.is_pyobject and entry is not weakref_slot:
py_attrs.append(entry)
if py_attrs or weakref_slot in scope.var_entries:
_, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries()
if py_attrs or memoryview_slices or weakref_slot in scope.var_entries:
self.generate_self_cast(scope, code)
# call the user's __dealloc__
self.generate_usr_dealloc_call(scope, code)
if weakref_slot in scope.var_entries:
code.putln("if (p->__weakref__) PyObject_ClearWeakRefs(o);")
for entry in py_attrs:
code.put_xdecref("p->%s" % entry.cname, entry.type, nanny=False)
for entry in memoryview_slices:
code.put_xdecref_memoryviewslice("p->%s" % entry.cname,
have_gil=True)
if base_type:
tp_dealloc = TypeSlots.get_base_slot_function(scope, tp_slot)
if tp_dealloc is None:
......@@ -1139,13 +1138,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"static int %s(PyObject *o, visitproc v, void *a) {"
% slot_func)
py_attrs = []
py_buffers = []
for entry in scope.var_entries:
if entry.type.is_pyobject and entry.name != "__weakref__":
py_attrs.append(entry)
if entry.type == PyrexTypes.c_py_buffer_type:
py_buffers.append(entry)
have_entries, (py_attrs, py_buffers,
memoryview_slices) = scope.get_refcounted_entries()
if base_type or py_attrs:
code.putln("int e;")
......@@ -1178,9 +1172,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"}")
for entry in py_buffers:
code.putln("if (p->%s.obj) {" % entry.cname)
code.putln( "e = (*v)(p->%s.obj, a); if (e) return e;" % entry.cname)
for entry in py_buffers + memoryview_slices:
if entry.type == PyrexTypes.c_py_buffer_type:
cname = entry.cname + ".obj"
else:
# traverse the memoryview object, which should traverse the
# object exposing the buffer
cname = entry.cname + ".memview"
code.putln("if (p->%s) {" % cname)
code.putln( "e = (*v)(p->%s, a); if (e) return e;" % cname)
code.putln("}")
if cclass_entry.cname == '__pyx_memoryviewslice':
......
......@@ -439,6 +439,10 @@ class CNameDeclaratorNode(CDeclaratorNode):
else:
self.name = base_type.declaration_code("", for_display=1, pyrex=1)
base_type = py_object_type
if base_type.is_fused and env.fused_to_specific:
base_type = base_type.specialize(env.fused_to_specific)
self.type = base_type
return self, base_type
......@@ -982,6 +986,9 @@ class TemplatedTypeNode(CBaseTypeNode):
dimension = dimension)
self.type = self.array_declarator.analyse(base_type, env)[1]
if self.type.is_fused and env.fused_to_specific:
self.type = self.type.specialize(env.fused_to_specific)
return self.type
class CComplexBaseTypeNode(CBaseTypeNode):
......@@ -1031,8 +1038,8 @@ class FusedTypeNode(CBaseTypeNode):
else:
types.append(type)
if len(self.types) == 1:
return types[0]
# if len(self.types) == 1:
# return types[0]
return PyrexTypes.FusedType(types, name=self.name)
......@@ -2279,7 +2286,6 @@ class FusedCFuncDefNode(StatListNode):
else:
node.py_func.fused_py_func = self.py_func
node.entry.as_variable = self.py_func.entry
# Copy the nodes as AnalyseDeclarationsTransform will prepend
# self.py_func to self.stats, as we only want specialized
# CFuncDefNodes in self.nodes
......@@ -2294,9 +2300,9 @@ class FusedCFuncDefNode(StatListNode):
Create a copy of the original def or lambda function for specialized
versions.
"""
fused_types = PyrexTypes.unique(
fused_compound_types = PyrexTypes.unique(
[arg.type for arg in self.node.args if arg.type.is_fused])
permutations = PyrexTypes.get_all_specialized_permutations(fused_types)
permutations = PyrexTypes.get_all_specialized_permutations(fused_compound_types)
if self.node.entry in env.pyfunc_entries:
env.pyfunc_entries.remove(self.node.entry)
......@@ -2311,7 +2317,7 @@ class FusedCFuncDefNode(StatListNode):
copied_node.analyse_declarations(env)
self.create_new_local_scope(copied_node, env, fused_to_specific)
self.specialize_copied_def(copied_node, cname, self.node.entry,
fused_to_specific, fused_types)
fused_to_specific, fused_compound_types)
PyrexTypes.specialize_entry(copied_node.entry, cname)
copied_node.entry.used = True
......@@ -2420,11 +2426,9 @@ class FusedCFuncDefNode(StatListNode):
"""Specialize the copy of a DefNode given the copied node,
the specialization cname and the original DefNode entry"""
type_strings = [
fused_type.specialize(f2s).typeof_name()
PyrexTypes.specialization_signature_string(fused_type, f2s)
for fused_type in fused_types
]
#type_strings = [f2s[fused_type].typeof_name()
# for fused_type in fused_types]
node.specialized_signature_string = ', '.join(type_strings)
......@@ -2574,7 +2578,7 @@ def __pyx_fused_cpdef(signatures, args, kwargs):
candidates = []
for sig in signatures:
match_found = True
match_found = [x for x in dest_sig if x]
for src_type, dst_type in zip(sig.strip('()').split(', '), dest_sig):
if dst_type is not None and match_found:
match_found = src_type == dst_type
......@@ -5355,7 +5359,7 @@ class ReturnStatNode(StatNode):
"%s = %s;" % (
Naming.retval_cname,
self.value.result_as(self.return_type)))
self.value.generate_post_assignment_code(code)
self.value.generate_post_assignment_code(code)
self.value.free_temps(code)
else:
if self.return_type.is_pyobject:
......
......@@ -2,20 +2,31 @@
# the NumPy ABI changed so that the shape, ndim, strides, etc. fields were
# no longer available, however the use of these were so entrenched in
# Cython codes
import PyrexTypes
import ExprNodes
import os
from StringEncoding import EncodedString
def should_apply_numpy_hack(obj_type):
if not obj_type.is_extension_type or obj_type.objstruct_cname != 'PyArrayObject':
return False
from Scanning import FileSourceDescriptor
from Main import standard_include_path
type_source = obj_type.pos[0]
if isinstance(type_source, FileSourceDescriptor):
type_source_path = os.path.abspath(os.path.normpath(type_source.filename))
return type_source_path == os.path.join(standard_include_path, 'numpy.pxd')
else:
return False
def numpy_transform_attribute_node(node):
import PyrexTypes
import ExprNodes
assert isinstance(node, ExprNodes.AttributeNode)
if node.obj.type.objstruct_cname != 'PyArrayObject':
return node
pos = node.pos
numpy_pxd_scope = node.obj.entry.type.scope.parent_scope
numpy_pxd_scope = node.obj.type.scope.parent_scope
def macro_call_node(numpy_macro_name):
array_node = node.obj
......
......@@ -18,7 +18,8 @@ from Cython.Compiler.TreeFragment import TreeFragment
from Cython.Compiler.StringEncoding import EncodedString
from Cython.Compiler.Errors import error, warning, CompileError, InternalError
from Cython.Compiler.Code import UtilityCode
from Cython.Compiler.NumpySupport import (should_apply_numpy_hack,
numpy_transform_attribute_node)
import copy
......@@ -1495,12 +1496,15 @@ if VALUE is not None:
self.fused_function = None
if node.py_func:
# Create PyCFunction nodes for each specialization
node.stats.insert(0, node.py_func)
node.py_func = self.visit(node.py_func)
pycfunc = ExprNodes.PyCFunctionNode.from_defnode(node.py_func,
True)
pycfunc = ExprNodes.ProxyNode(pycfunc.coerce_to_temp(env))
node.resulting_fused_function = pycfunc
# Create assignment node for our def function
node.fused_func_assignment = self._create_assignment(
node.py_func, ExprNodes.CloneNode(pycfunc), env)
else:
......@@ -1781,7 +1785,7 @@ class AnalyseExpressionsTransform(CythonTransform):
"""
self.visit_Node(node)
if node.is_fused_index and node.type is not PyrexTypes.error_type:
if node.is_fused_index and not node.type.is_error:
node = node.base
elif node.memslice_ellipsis_noop:
# memoryviewslice[...] expression, drop the IndexNode
......@@ -1792,8 +1796,8 @@ class AnalyseExpressionsTransform(CythonTransform):
self.visitchildren(node)
type = node.obj.type
if type.is_extension_type and type.objstruct_cname == 'PyArrayObject':
from NumpySupport import numpy_transform_attribute_node
if (not node.type.is_error and type.is_extension_type and
should_apply_numpy_hack(type)):
node = numpy_transform_attribute_node(node)
self.visitchildren(node)
......@@ -2603,8 +2607,8 @@ class ReplaceFusedTypeChecks(VisitorTransform):
else:
types = PyrexTypes.get_specialized_types(type2)
for specific_type in types:
if type1.same_as(specific_type):
for specialized_type in types:
if type1.same_as(specialized_type):
if op == 'in':
return true_node
else:
......
......@@ -767,12 +767,46 @@ class BufferType(BaseType):
def as_argument_type(self):
return self
def specialize(self, values):
dtype = self.dtype.specialize(values)
if dtype is not self.dtype:
return BufferType(self.base, dtype, self.ndim, self.mode,
self.negative_indices, self.cast)
return self
def __getattr__(self, name):
return getattr(self.base, name)
def __repr__(self):
return "<BufferType %r>" % self.base
def __str__(self):
# avoid ', ', as fused functions split the signature string on ', '
if self.cast:
cast_str = ',cast=True'
else:
cast_str = ''
return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
cast_str)
def assignable_from(self, other_type):
if other_type.is_buffer:
return (self.same_as(other_type, compare_base=False) and
self.base.assignable_from(other_type.base))
return self.base.assignable_from(other_type)
def same_as(self, other_type, compare_base=True):
if not other_type.is_buffer:
return other_type.same_as(self.base)
return (self.dtype.same_as(other_type.dtype) and
self.ndim == other_type.ndim and
self.mode == other_type.mode and
self.cast == other_type.cast and
(not compare_base or self.base.same_as(other_type.base)))
class PyObjectType(PyrexType):
#
......@@ -2631,6 +2665,31 @@ def _get_all_specialized_permutations(fused_types, id="", f2s=()):
return result
def specialization_signature_string(fused_compound_type, fused_to_specific):
"""
Return the signature for a specialization of a fused type. e.g.
floating[:] ->
'float' or 'double'
cdef fused ft:
float[:]
double[:]
ft ->
'float[:]' or 'double[:]'
integral func(floating) ->
'int (*func)(float)' or ...
"""
fused_types = fused_compound_type.get_fused_types()
if len(fused_types) == 1:
fused_type = fused_types[0]
else:
fused_type = fused_compound_type
return fused_type.specialize(fused_to_specific).typeof_name()
def get_specialized_types(type):
"""
Return a list of specialized types sorted in reverse order in accordance
......@@ -2640,10 +2699,15 @@ def get_specialized_types(type):
if isinstance(type, FusedType):
result = type.types
for specialized_type in result:
specialized_type.specialization_string = specialized_type.typeof_name()
else:
result = []
for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
result.append(type.specialize(f2s))
specialized_type = type.specialize(f2s)
specialized_type.specialization_string = (
specialization_signature_string(type, f2s))
result.append(specialized_type)
return sorted(result)
......
......@@ -784,6 +784,23 @@ class Scope(object):
def add_include_file(self, filename):
self.outer_scope.add_include_file(filename)
def get_refcounted_entries(self, include_weakref=False):
py_attrs = []
py_buffers = []
memoryview_slices = []
for entry in self.var_entries:
if entry.type.is_pyobject:
if include_weakref or entry.name != "weakref":
py_attrs.append(entry)
elif entry.type == PyrexTypes.c_py_buffer_type:
py_buffers.append(entry)
elif entry.type.is_memoryviewslice:
memoryview_slices.append(entry)
have_entries = py_attrs or py_buffers or memoryview_slices
return have_entries, (py_attrs, py_buffers, memoryview_slices)
class PreImportScope(Scope):
......
__version__ = "0.16.beta0"
__version__ = "0.16rc1"
# Void cython.* directives (for case insensitive operating systems).
from Cython.Shadow import *
# tag: cpp
cimport cython
from libcpp.vector cimport vector
def test_cpp_specialization(cython.floating element):
"""
>>> import cython
>>> test_cpp_specialization[cython.float](10.0)
vector<float> * float 10.0
>>> test_cpp_specialization[cython.double](10.0)
vector<double> * double 10.0
"""
cdef vector[cython.floating] *v = new vector[cython.floating]()
v.push_back(element)
print cython.typeof(v), cython.typeof(element), v.at(0)
\ No newline at end of file
# mode: run
cimport cython
from cython.view cimport array
from cython cimport integral
from cpython cimport Py_INCREF
from Cython import Shadow as pure_cython
ctypedef char * string_t
# floating = cython.fused_type(float, double) floating
......@@ -249,3 +249,26 @@ def test_sizeof_fused_type(fused_type1 b):
"""
t = sizeof(b), sizeof(fused_type1), sizeof(double)
assert t[0] == t[1] == t[2], t
def get_array(itemsize, format):
result = array((10,), itemsize, format)
result[5] = 5.0
result[6] = 6.0
return result
def test_fused_memslice_dtype(cython.floating[:] array):
"""
Note: the np.ndarray dtype test is in numpy_test
>>> import cython
>>> sorted(test_fused_memslice_dtype.__signatures__)
['double', 'float']
>>> test_fused_memslice_dtype[cython.double](get_array(8, 'd'))
double[:] double[:] 5.0 6.0
>>> test_fused_memslice_dtype[cython.float](get_array(4, 'f'))
float[:] float[:] 5.0 6.0
"""
cdef cython.floating[:] otherarray = array[0:100:1]
print cython.typeof(array), cython.typeof(otherarray), \
array[5], otherarray[6]
......@@ -133,6 +133,16 @@ def test_coerce_to_temp():
print
print _coerce_to_temp()[4][4]
def test_extclass_attribute_dealloc():
"""
>>> test_extclass_attribute_dealloc()
acquired self.arr
2
released self.arr
"""
cdef ExtClassMockedAttr obj = ExtClassMockedAttr()
print obj.arr[4, 4]
cdef float[:,::1] global_mv = array((10,10), itemsize=sizeof(float), format='f')
global_mv = array((10,10), itemsize=sizeof(float), format='f')
cdef object global_obj
......
......@@ -4,6 +4,7 @@
import numpy as np
cimport numpy as np
int64_array = np.ones((3, 2), dtype=np.int64)
def f():
"""
......@@ -14,7 +15,7 @@ def f():
shape[1] 2
strides 16 8
"""
cdef np.ndarray x = np.ones((3, 2), dtype=np.int64)
cdef np.ndarray x = int64_array
cdef int i
cdef Py_ssize_t j, k
cdef char *p
......@@ -23,7 +24,7 @@ def f():
with nogil:
i = x.ndim
print 'ndim', i
with nogil:
p = x.data
print 'data', (<np.int64_t*>p)[0]
......@@ -42,4 +43,12 @@ def f():
j = x.strides[0]
k = x.strides[1]
print 'strides', j, k
def test_non_namenode_attribute_access(obj):
"""
>>> test_non_namenode_attribute_access(int64_array)
data 1
"""
# Try casting, resulting in an AttributeNode with a TypeCastNode as object
# and 'data' as attribute
print "data", (<np.int64_t *> (<np.ndarray> obj).data)[0]
......@@ -2,6 +2,7 @@
# cannot be named "numpy" in order to not clash with the numpy module!
cimport numpy as np
cimport cython
def little_endian():
cdef int endian_detector = 1
......@@ -35,7 +36,7 @@ try:
[[ 16. 17. 18. 19.]
[ 20. 21. 22. 23.]]]
6.0 0.0 13.0 8.0
>>> obj_array()
[a 1 {}]
a 1 {}
......@@ -502,4 +503,69 @@ def test_point_record():
test[i].y = -i
print repr(test).replace('<', '!').replace('>', '!')
def test_fused_ndarray_dtype(np.ndarray[cython.floating, ndim=1] a):
"""
>>> import cython
>>> sorted(test_fused_ndarray_dtype.__signatures__)
['double', 'float']
>>> test_fused_ndarray_dtype[cython.double](np.arange(10, dtype=np.float64))
ndarray[double,ndim=1] ndarray[double,ndim=1] 5.0 6.0
>>> test_fused_ndarray_dtype[cython.float](np.arange(10, dtype=np.float32))
ndarray[float,ndim=1] ndarray[float,ndim=1] 5.0 6.0
"""
cdef np.ndarray[cython.floating, ndim=1] b = a
print cython.typeof(a), cython.typeof(b), a[5], b[6]
double_array = np.linspace(0, 1, 100)
int32_array = np.arange(100, dtype=np.int32)
cdef fused fused_external:
np.int32_t
np.int64_t
np.float32_t
np.float64_t
def test_fused_external(np.ndarray[fused_external, ndim=1] a):
"""
>>> import cython
>>> sorted(test_fused_external.__signatures__)
['float32_t', 'float64_t', 'int32_t', 'int64_t']
>>> test_fused_external["float64_t"](double_array)
float64
>>> test_fused_external["int32_t"](int32_array)
int32
>>> test_fused_external(np.arange(100)) # fix in next release
Traceback (most recent call last):
...
TypeError: No matching signature found
"""
print a.dtype
cdef fused fused_buffers:
np.ndarray[np.int32_t, ndim=1]
np.int64_t[::1]
def test_fused_buffers(fused_buffers arg):
"""
>>> sorted(test_fused_buffers.__signatures__)
['int64_t[::1]', 'ndarray[int32_t,ndim=1]']
"""
cpdef _fused_cpdef_buffers(np.ndarray[fused_external] a):
print a.dtype
def test_fused_cpdef_buffers():
"""
>>> test_fused_cpdef_buffers()
int32
int32
"""
_fused_cpdef_buffers[np.int32_t](int32_array)
cdef np.ndarray[np.int32_t] typed_array = int32_array
_fused_cpdef_buffers(typed_array)
include "numpy_common.pxi"
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