Author: mattip <[email protected]>
Branch: numpypy-longdouble
Changeset: r59543:3fbc98dc8730
Date: 2012-12-13 22:57 -0800
http://bitbucket.org/pypy/pypy/changeset/3fbc98dc8730/

Log:    test, implement pack_float128 which returns a 128 bit int
        r_ulonglonglong along the way, implement and test r_ulonglonglong

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -489,6 +489,7 @@
 r_ulonglong = build_int('r_ulonglong', False, 64)
 
 r_longlonglong = build_int('r_longlonglong', True, 128)
+r_ulonglonglong = build_int('r_ulonglonglong', False, 128)
 longlongmax = r_longlong(LONGLONG_TEST - 1)
 
 if r_longlong is not r_int:
diff --git a/pypy/rlib/rstruct/ieee.py b/pypy/rlib/rstruct/ieee.py
--- a/pypy/rlib/rstruct/ieee.py
+++ b/pypy/rlib/rstruct/ieee.py
@@ -5,7 +5,7 @@
 import math
 
 from pypy.rlib import rarithmetic, rfloat, objectmodel, jit
-from pypy.rlib.rarithmetic import r_ulonglong
+from pypy.rlib.rarithmetic import r_ulonglong, r_ulonglonglong
 
 
 def round_to_nearest(x):
@@ -27,24 +27,33 @@
 
 
 def float_unpack(Q, size):
-    """Convert a 16-bit, 32-bit or 64-bit integer created
+    """Convert a 16-bit, 32-bit 64-bit integer created
     by float_pack into a Python float."""
-
-    if size == 8:
+    if size == 16 or size == 12:
+        #Implement a x86-hardware extended 80 bit format
+        MIN_EXP = -16381  # = sys.float_info.min_exp
+        MAX_EXP = 16384   # = sys.float_info.max_exp
+        MANT_DIG = 64    # = sys.float_info.mant_dig
+        BITS = 80
+        one = r_ulonglonglong(1)
+    elif size == 8:
         MIN_EXP = -1021  # = sys.float_info.min_exp
         MAX_EXP = 1024   # = sys.float_info.max_exp
         MANT_DIG = 53    # = sys.float_info.mant_dig
         BITS = 64
+        one = r_ulonglong(1)
     elif size == 4:
         MIN_EXP = -125   # C's FLT_MIN_EXP
         MAX_EXP = 128    # FLT_MAX_EXP
         MANT_DIG = 24    # FLT_MANT_DIG
         BITS = 32
+        one = r_ulonglong(1)
     elif size == 2:
         MIN_EXP = -13   
         MAX_EXP = 16    
         MANT_DIG = 11
         BITS = 16
+        one = r_ulonglong(1)
     else:
         raise ValueError("invalid size value")
 
@@ -56,7 +65,6 @@
             raise ValueError("input out of range")
 
     # extract pieces
-    one = r_ulonglong(1)
     sign = rarithmetic.intmask(Q >> BITS - 1)
     exp = rarithmetic.intmask((Q & ((one << BITS - 1) - (one << MANT_DIG - 
1))) >> MANT_DIG - 1)
     mant = Q & ((one << MANT_DIG - 1) - 1)
@@ -77,7 +85,14 @@
 def float_pack(x, size):
     """Convert a Python float x into a 64-bit unsigned integer
     with the same byte representation."""
+    return float_pack_helper(x, size, r_ulonglong)
 
+def float_pack128(x, size):
+    """Convert a Python float x into a 64-bit unsigned integer
+    with the same byte representation."""
+    return float_pack_helper(x, size, r_ulonglonglong)
+
+def float_pack_helper(x, size, r_type):
     if size == 8:
         MIN_EXP = -1021  # = sys.float_info.min_exp
         MAX_EXP = 1024   # = sys.float_info.max_exp
@@ -93,40 +108,46 @@
         MAX_EXP = 16    
         MANT_DIG = 11
         BITS = 16
+    elif size == 16 or size == 12:
+        #Implement a x86-hardware extended 80 bit format
+        MIN_EXP = -16381  # = sys.float_info.min_exp
+        MAX_EXP = 16384   # = sys.float_info.max_exp
+        MANT_DIG = 64    # = sys.float_info.mant_dig
+        BITS = 80
     else:
         raise ValueError("invalid size value")
 
     sign = rfloat.copysign(1.0, x) < 0.0
     if not rfloat.isfinite(x):
         if rfloat.isinf(x):
-            mant = r_ulonglong(0)
+            mant = r_type(0)
             exp = MAX_EXP - MIN_EXP + 2
         else:  # rfloat.isnan(x):
-            mant = r_ulonglong(1) << (MANT_DIG-2) # other values possible
+            mant = r_type(1) << (MANT_DIG-2) # other values possible
             exp = MAX_EXP - MIN_EXP + 2
     elif x == 0.0:
-        mant = r_ulonglong(0)
+        mant = r_type(0)
         exp = 0
     else:
         m, e = math.frexp(abs(x))  # abs(x) == m * 2**e
         exp = e - (MIN_EXP - 1)
         if exp > 0:
             # Normal case.
-            mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG))
-            mant -= r_ulonglong(1) << MANT_DIG - 1
+            mant = round_to_nearest(m * (r_type(1) << MANT_DIG))
+            mant -= r_type(1) << MANT_DIG - 1
         else:
             # Subnormal case.
             if exp + MANT_DIG - 1 >= 0:
-                mant = round_to_nearest(m * (r_ulonglong(1) << exp + MANT_DIG 
- 1))
+                mant = round_to_nearest(m * (r_type(1) << exp + MANT_DIG - 1))
             else:
-                mant = r_ulonglong(0)
+                mant = r_type(0)
             exp = 0
 
         # Special case: rounding produced a MANT_DIG-bit mantissa.
         if not objectmodel.we_are_translated():
             assert 0 <= mant <= 1 << MANT_DIG - 1
-        if mant == r_ulonglong(1) << MANT_DIG - 1:
-            mant = r_ulonglong(0)
+        if mant == r_type(1) << MANT_DIG - 1:
+            mant = r_type(0)
             exp += 1
 
         # Raise on overflow (in some circumstances, may want to return
@@ -140,8 +161,8 @@
         assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
         assert 0 <= sign <= 1
 
-    exp = r_ulonglong(exp)
-    sign = r_ulonglong(sign)
+    exp = r_type(exp)
+    sign = r_type(sign)
     return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
 
 
diff --git a/pypy/rlib/rstruct/test/test_ieee.py 
b/pypy/rlib/rstruct/test/test_ieee.py
--- a/pypy/rlib/rstruct/test/test_ieee.py
+++ b/pypy/rlib/rstruct/test/test_ieee.py
@@ -3,7 +3,7 @@
 import struct
 
 from pypy.rlib.rfloat import isnan
-from pypy.rlib.rstruct.ieee import float_pack, float_unpack
+from pypy.rlib.rstruct.ieee import float_pack, float_unpack, float_pack128
 
 
 class TestFloatPacking:
@@ -18,6 +18,13 @@
         y = float_unpack(Q, 8)
         assert repr(x) == repr(y)
 
+        Q = float_pack128(x, 16)
+        y = float_unpack(Q, 16)
+        assert repr(x) == repr(y)
+        Q = float_pack128(x, 12)
+        y = float_unpack(Q, 12)
+        assert repr(x) == repr(y)
+
         # check that packing agrees with the struct module
         struct_pack8 = struct.unpack('<Q', struct.pack('<d', x))[0]
         float_pack8 = float_pack(x, 8)
diff --git a/pypy/rlib/test/test_rarithmetic.py 
b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -165,12 +165,12 @@
             assert types.index(type(x)) == expected
 
 def test_limits():
-    for cls in r_uint, r_ulonglong:
+    for cls in r_uint, r_ulonglong, r_ulonglonglong:
         mask = cls.MASK
         assert cls(mask) == mask
         assert cls(mask+1) == 0
 
-    for cls in r_int, r_longlong:
+    for cls in r_int, r_longlong, r_longlonglong:
         mask = cls.MASK>>1
         assert cls(mask) == mask
         assert cls(-mask-1) == -mask-1
@@ -369,6 +369,11 @@
     y = r_ulonglong(x)
     assert long(y) == 2**r_ulonglong.BITS - 1
 
+def test_r_ulonglonglong():
+    x = r_longlonglong(-1)
+    y = r_ulonglonglong(x)
+    assert long(y) == 2**r_ulonglonglong.BITS - 1
+
 def test_highest_bit():
     py.test.raises(AssertionError, highest_bit, 0)
     py.test.raises(AssertionError, highest_bit, 14)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to