reworked type promotion rules, nearly identical to the one in Pyrex
authorLisandro Dalcin <dalcinl@gmail.com>
Thu, 15 Apr 2010 19:12:04 +0000 (16:12 -0300)
committerLisandro Dalcin <dalcinl@gmail.com>
Thu, 15 Apr 2010 19:12:04 +0000 (16:12 -0300)
Cython/Compiler/PyrexTypes.py
tests/run/unsigned.pyx

index 6babebe378d4c59889f264414747334c2346b00e..26e54343737f043672bb524e1e38a42485321d5c 100755 (executable)
@@ -2327,25 +2327,27 @@ def widest_numeric_type(type1, type2):
     # Given two numeric types, return the narrowest type
     # encompassing both of them.
     if type1 == type2:
-        return type1
-    if type1.is_complex:
-        if type2.is_complex:
-            return CComplexType(widest_numeric_type(type1.real_type, type2.real_type))
-        else:
-            return CComplexType(widest_numeric_type(type1.real_type, type2))
-    elif type2.is_complex:
-        return CComplexType(widest_numeric_type(type1, type2.real_type))
-    if type1.is_enum and type2.is_enum:
-        return c_int_type
-    elif type1 is type2:
-        return type1
-    elif (type1.signed and type2.signed) or (not type1.signed and not type2.signed):
-        if type2.rank > type1.rank:
-            return type2
-        else:
-            return type1
+        widest_type = type1
+    elif type1.is_complex or type2.is_complex:
+        def real_type(ntype):
+            if ntype.is_complex:
+                return ntype.real_type
+            return ntype
+        widest_type = CComplexType(
+            widest_numeric_type(
+                real_type(type1), 
+                real_type(type2)))
+    elif type1.is_enum and type2.is_enum:
+        widest_type = c_int_type
+    elif type1.rank < type2.rank:
+        widest_type = type2
+    elif type1.rank > type2.rank:
+        widest_type = type1
+    elif type1.signed < type2.signed:
+        widest_type = type1
     else:
-        return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
+        widest_type = type2
+    return widest_type
 
 def spanning_type(type1, type2):
     # Return a type assignable from both type1 and type2.
index 45aaa112bef1546641a5bde2ed59beaec49584a3..ea9d9fa71f27a21baacde0092c51bbe615f9eba5 100644 (file)
@@ -1,29 +1,51 @@
-import sys
-
-if sys.version_info[0] >= 3:
-    __doc__ = u"""
-    >>> test_signed()
-    3 <class 'int'>
-    9 <class 'int'>
-    6 <class 'int'>
-    12 <class 'int'>
-"""
-else:
-    __doc__ = u"""
-    >>> test_signed()
-    3 <type 'int'>
-    9 <type 'long'>
-    6 <type 'long'>
-    12 <type 'long'>
-"""
-
 cdef int i = 1
 cdef long l = 2
 cdef unsigned int ui = 4
 cdef unsigned long ul = 8
 
-def test_signed():
-    print i + l, type(i+l)
-    print i + ul, type(i+ul)
-    print ui + l, type(ui+l)
-    print ui + ul, type(ui+ul)
+def test_add():
+    """
+    >>> test_add()
+    3
+    9
+    6
+    12
+    """
+    print i + l
+    print i + ul
+    print ui + l
+    print ui + ul
+
+def test_add_sshort_ulong(signed short a, unsigned long b):
+    """
+    >>> test_add_sshort_ulong(1, 1) == 2
+    True
+    >>> test_add_sshort_ulong(-1, 1) == 0
+    True
+    >>> test_add_sshort_ulong(-2, 1) == -1
+    False
+    """
+    return a + b
+
+def test_add_ushort_slonglong(unsigned short a, signed long long b):
+    """
+    >>> test_add_ushort_slonglong(1, 1) == 2
+    True
+    >>> test_add_ushort_slonglong(1, -1) == 0
+    True
+    >>> test_add_ushort_slonglong(1, -2) == -1
+    True
+    """
+    return a + b
+
+def test_add_slong_ulong(signed long a, unsigned long b):
+    """
+    >>> test_add_slong_ulong(1, 1) == 2
+    True
+    >>> test_add_slong_ulong(-1, 1) == 0
+    True
+    >>> test_add_slong_ulong(-2, 1) == -1
+    False
+    """
+    return a + b
+