[pypy-svn] r76160 - pypy/branch/fast-forward/pypy/rlib/rstruct

benjamin at codespeak.net benjamin at codespeak.net
Mon Jul 12 21:16:57 CEST 2010


Author: benjamin
Date: Mon Jul 12 21:16:46 2010
New Revision: 76160

Modified:
   pypy/branch/fast-forward/pypy/rlib/rstruct/ieee.py
Log:
pack and unpack floats in unsigned longs

Modified: pypy/branch/fast-forward/pypy/rlib/rstruct/ieee.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rstruct/ieee.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rstruct/ieee.py	Mon Jul 12 21:16:46 2010
@@ -4,7 +4,8 @@
 
 import math
 
-from pypy.rlib import rarithmetic
+from pypy.rlib import rarithmetic, objectmodel
+from pypy.rlib.rarithmetic import r_ulonglong
 
 
 def round_to_nearest(x):
@@ -18,7 +19,7 @@
     if you use this for negative x.
 
     """
-    int_part = int(x)
+    int_part = r_ulonglong(x)
     frac_part = x - int_part
     if frac_part > 0.5 or frac_part == 0.5 and int_part & 1 == 1:
         int_part += 1
@@ -46,9 +47,10 @@
          raise ValueError("input out of range")
 
     # extract pieces
-    sign = Q >> BITS - 1
-    exp = (Q & ((1 << BITS - 1) - (1 << MANT_DIG - 1))) >> MANT_DIG - 1
-    mant = Q & ((1 << MANT_DIG - 1) - 1)
+    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)
 
     if exp == MAX_EXP - MIN_EXP + 2:
         # nan or infinity
@@ -58,7 +60,7 @@
         result = math.ldexp(float(mant), MIN_EXP - MANT_DIG)
     else:
         # normal
-        mant += 1 << MANT_DIG - 1
+        mant += r_ulonglong(1) << MANT_DIG - 1
         result = math.ldexp(float(mant), exp + MIN_EXP - MANT_DIG - 1)
     return -result if sign else result
 
@@ -82,33 +84,34 @@
 
     sign = rarithmetic.copysign(1.0, x) < 0.0
     if rarithmetic.isinf(x):
-        mant = 0
+        mant = r_ulonglong(0)
         exp = MAX_EXP - MIN_EXP + 2
     elif rarithmetic.isnan(x):
-        mant = 1 << (MANT_DIG-2) # other values possible
+        mant = r_ulonglong(1) << (MANT_DIG-2) # other values possible
         exp = MAX_EXP - MIN_EXP + 2
     elif x == 0.0:
-        mant = 0
+        mant = r_ulonglong(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 * (1 << MANT_DIG))
-            mant -= 1 << MANT_DIG - 1
+            mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG))
+            mant -= r_ulonglong(1) << MANT_DIG - 1
         else:
             # Subnormal case.
             if exp + MANT_DIG - 1 >= 0:
-                mant = round_to_nearest(m * (1 << exp + MANT_DIG - 1))
+                mant = round_to_nearest(m * (r_ulonglong(1) << exp + MANT_DIG - 1))
             else:
-                mant = 0
+                mant = r_ulonglong(0)
             exp = 0
 
         # Special case: rounding produced a MANT_DIG-bit mantissa.
-        assert 0 <= mant <= 1 << MANT_DIG - 1
-        if mant == 1 << MANT_DIG - 1:
-            mant = 0
+        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)
             exp += 1
 
         # Raise on overflow (in some circumstances, may want to return
@@ -117,9 +120,10 @@
              raise OverflowError("float too large to pack in this format")
 
     # check constraints
-    assert 0 <= mant < 1 << MANT_DIG - 1
-    assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
-    assert 0 <= sign <= 1
+    if not objectmodel.we_are_translated():
+        assert 0 <= mant < 1 << MANT_DIG - 1
+        assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
+        assert 0 <= sign <= 1
     return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
 
 
@@ -134,8 +138,8 @@
 
 
 def unpack_float(s, be):
-    unsigned = 0
+    unsigned = r_ulonglong(0)
     for i in range(len(s)):
         c = ord(s[len(s) - 1 - i if be else i])
-        unsigned |= c << (i * 8)
+        unsigned |= r_ulonglong(c) << (i * 8)
     return float_unpack(unsigned, len(s))



More information about the Pypy-commit mailing list