[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