Commits

mattip  committed 3fbc98d

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

  • Participants
  • Parent commits 0611e66
  • Branches numpypy-longdouble

Comments (0)

Files changed (4)

File pypy/rlib/rarithmetic.py

 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:

File pypy/rlib/rstruct/ieee.py

 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):
 
 
 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")
 
             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)
 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
         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
         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
 
 

File pypy/rlib/rstruct/test/test_ieee.py

 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:
         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)

File pypy/rlib/test/test_rarithmetic.py

             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
     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)