From 2a5e66aeae19b19b6ef4d929a28162c5a0158c9d Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Tue, 3 Nov 2009 16:35:19 +0100 Subject: [PATCH] Fix #441 --- Cython/Compiler/Code.py | 6 ++-- Cython/Compiler/ModuleNode.py | 8 ++++-- Cython/Compiler/PyrexTypes.py | 30 ++++++++++++-------- tests/run/complex_numbers_T305.pyx | 44 +++++++++++++++++++++++++----- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 45b880f9..b514047e 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -408,8 +408,10 @@ class GlobalState(object): code_layout = [ 'h_code', 'utility_code_proto_before_types', - 'type_declarations', - 'utility_code_proto', + 'numeric_typedefs', # Let these detailed individual parts stay!, + 'complex_type_declarations', # as the proper solution is to make a full DAG... + 'type_declarations', # More coarse-grained blocks would simply hide + 'utility_code_proto', # the ugliness, not fix it 'module_declarations', 'typeinfo', 'before_global_var', diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 506010af..575414fc 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -654,8 +654,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): def generate_typedef(self, entry, code): base_type = entry.type.typedef_base_type - code.putln("") - code.putln("typedef %s;" % base_type.declaration_code(entry.cname)) + if base_type.is_numeric: + writer = code.globalstate['numeric_typedefs'] + else: + writer = code + writer.putln("") + writer.putln("typedef %s;" % base_type.declaration_code(entry.cname)) def sue_header_footer(self, type, kind, name): if type.typedef_flag: diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 282c5198..9e73dc96 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -871,12 +871,21 @@ class CComplexType(CNumericType): scope = None def __init__(self, real_type): + while real_type.is_typedef and not real_type.typedef_is_external: + real_type = real_type.typedef_base_type + if real_type.is_typedef and real_type.typedef_is_external: + # The below is not actually used: Coercions are currently disabled + # so that complex types of external types can not be created + self.funcsuffix = "_%s" % real_type.specalization_name() + else: + self.funcsuffix = real_type.math_h_modifier + self.real_type = real_type CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed) self.binops = {} self.from_parts = "%s_from_parts" % self.specalization_name() self.default_value = "%s(0, 0)" % self.from_parts - + def __eq__(self, other): if isinstance(self, CComplexType) and isinstance(other, CComplexType): return self.real_type == other.real_type @@ -899,7 +908,7 @@ class CComplexType(CNumericType): def __hash__(self): return ~hash(self.real_type) - + def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0): if for_display: @@ -915,8 +924,9 @@ class CComplexType(CNumericType): def assignable_from(self, src_type): # Temporary hack/feature disabling, see #441 - if not src_type.is_complex and src_type.is_numeric and src_type.is_typedef: - return False + if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef + and src_type.typedef_is_external): + return False else: return super(CComplexType, self).assignable_from(src_type) @@ -940,7 +950,7 @@ class CComplexType(CNumericType): CFuncType(self, [CFuncTypeArg("self", self, None)]), pos=None, defining=1, - cname="__Pyx_c_conj%s" % self.real_type.math_h_modifier) + cname="__Pyx_c_conj%s" % self.funcsuffix) return True @@ -956,7 +966,7 @@ class CComplexType(CNumericType): utility_code.specialize( self, real_type = self.real_type.declaration_code(''), - m = self.real_type.math_h_modifier)) + m = self.funcsuffix)) return True def create_to_py_utility_code(self, env): @@ -973,7 +983,7 @@ class CComplexType(CNumericType): utility_code.specialize( self, real_type = self.real_type.declaration_code(''), - m = self.real_type.math_h_modifier)) + m = self.funcsuffix)) self.from_py_function = "__Pyx_PyComplex_As_" + self.specalization_name() return True @@ -984,8 +994,7 @@ class CComplexType(CNumericType): pass try: op_name = complex_ops[nargs, op] - modifier = self.real_type.math_h_modifier - self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, modifier) + self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix) return func_name except KeyError: return None @@ -1045,7 +1054,7 @@ proto=""" """) complex_type_utility_code = UtilityCode( -proto_block='utility_code_proto_before_types', +proto_block='complex_type_declarations', proto=""" #if CYTHON_CCOMPLEX #ifdef __cplusplus @@ -1204,7 +1213,6 @@ impl=""" #endif """) - class CArrayType(CType): # base_type CType Element type # size integer or None Number of elements diff --git a/tests/run/complex_numbers_T305.pyx b/tests/run/complex_numbers_T305.pyx index 6ae5aaad..d3ce1024 100644 --- a/tests/run/complex_numbers_T305.pyx +++ b/tests/run/complex_numbers_T305.pyx @@ -123,15 +123,45 @@ def test_conjugate_double(double complex z): ctypedef double complex cdouble def test_conjugate_typedef(cdouble z): + """ + >>> test_conjugate_typedef(2+3j) + (2-3j) + """ return z.conjugate() -#ctypedef double mydouble -#def test_coerce_typedef_multiply(mydouble x, double complex z): -# """ -# >>> test_coerce_typedef_multiply(3, 1j) -# (3j) -# """ -# return x * z +## cdef extern from "complex_numbers_T305.h": +## ctypedef double double_really_float "myfloat" +## ctypedef float float_really_double "mydouble" +## ctypedef float real_float "myfloat" +## ctypedef double real_double "mydouble" + +## def test_conjugate_nosizeassumptions(double_really_float x, +## float_really_double y, +## real_float z, real_double w): +## """ +## >>> test_conjugate_nosizeassumptions(1, 1, 1, 1) +## (-1j, -1j, -1j, -1j) +## >>> ["%.2f" % x.imag for x in test_conjugate_nosizeassumptions(2e300, 2e300, 2e300, 2e300)] +## ['-inf', '-2e+300', '-inf', '-2e+300'] +## """ +## cdef double complex I = 1j +## return ((x*I).conjugate(), (y*I).conjugate(), (z*I).conjugate(), (w*I).conjugate()) + +ctypedef double mydouble +def test_coerce_typedef_multiply(mydouble x, double complex z): + """ + >>> test_coerce_typedef_multiply(3, 1+1j) + (3+3j) + """ + return x * z + +ctypedef int myint +def test_coerce_typedef_multiply_int(myint x, double complex z): + """ + >>> test_coerce_typedef_multiply_int(3, 1+1j) + (3+3j) + """ + return x * z cpdef double complex complex_retval(): """ -- 2.26.2