I've already mailed about this, no one (other than Greg, of course)
commented... This patch fix and add tests for the C rules of integral
promotions in some interesting corner cases. The algorithm is
basically the one available in latest Pyrex plus the handling of
complex types. As we already discussed with Greg, this algorithm is
not actually correct according to the wording of the C99 standard (and
common sense), because type promotion do depends on the actual type
sizes. But Greg's implementation is IMHO the best we can do from
Pyrex/Cython side.
If no one complains, I'll push the patch.
--
Lisandro Dalcin
---------------
CIMEC (INTEC/CONICET-UNL)
Predio CONICET-Santa Fe
Colectora RN 168 Km 472, Paraje El Pozo
Tel: +54-342-4511594 (ext 1011)
Tel/Fax: +54-342-4511169
diff -r 9f56bc21a324 Cython/Compiler/PyrexTypes.py
--- a/Cython/Compiler/PyrexTypes.py Thu Apr 15 16:00:47 2010 +0200
+++ b/Cython/Compiler/PyrexTypes.py Thu Apr 15 11:57:57 2010 -0300
@@ -2327,25 +2327,27 @@
# 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.
diff -r 9f56bc21a324 tests/run/unsigned.pyx
--- a/tests/run/unsigned.pyx Thu Apr 15 16:00:47 2010 +0200
+++ b/tests/run/unsigned.pyx Thu Apr 15 11:57:57 2010 -0300
@@ -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
+
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev