[pypy-commit] pypy default: clean up ieee.py and add another test
bdkearns
noreply at buildbot.pypy.org
Mon Feb 11 04:05:50 CET 2013
Author: Brian Kearns <bdkearns at gmail.com>
Branch:
Changeset: r61057:b93922fe456d
Date: 2013-02-10 22:01 -0500
http://bitbucket.org/pypy/pypy/changeset/b93922fe456d/
Log: clean up ieee.py and add another test
diff --git a/rpython/rlib/rstruct/ieee.py b/rpython/rlib/rstruct/ieee.py
--- a/rpython/rlib/rstruct/ieee.py
+++ b/rpython/rlib/rstruct/ieee.py
@@ -7,7 +7,6 @@
from rpython.rlib import rarithmetic, rfloat, objectmodel, jit
from rpython.rlib.rarithmetic import r_ulonglong
-
def round_to_nearest(x):
"""Python 3 style round: round a float x to the nearest int, but
unlike the builtin Python 2.x round function:
@@ -25,38 +24,6 @@
int_part += 1
return int_part
-def float_unpack80(QQ):
- '''Unpack a (mant, exp) tuple of r_ulonglong in 80-bit extended format
- into a long double float
- '''
- MIN_EXP = -16381
- MAX_EXP = 16384
- MANT_DIG = 64
- TOPBITS = 80 - 64
- one = r_ulonglong(1)
- if len(QQ) != 2:
- raise ValueError("QQ must be two 64 bit uints")
- if not objectmodel.we_are_translated():
- # This tests generates wrong code when translated:
- # with gcc, shifting a 64bit int by 64 bits does
- # not change the value.
- if QQ[1] >> TOPBITS:
- raise ValueError("input '%r' out of range '%r'" % (QQ, QQ[1]>>TOPBITS))
-
- # extract pieces with explicit one in MANT_DIG
- sign = rarithmetic.intmask(QQ[1] >> TOPBITS - 1)
- exp = rarithmetic.intmask((QQ[1] & ((one << TOPBITS - 1) - 1)))
- mant = QQ[0]
-
- if exp == MAX_EXP - MIN_EXP + 2:
- # nan or infinity
- result = rfloat.NAN if mant &((one << MANT_DIG - 1) - 1) else rfloat.INFINITY
- else:
- # normal
- result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1)
- return -result if sign else result
-
-
def float_unpack(Q, size):
"""Convert a 16-bit, 32-bit 64-bit integer created
by float_pack into a Python float."""
@@ -73,8 +40,8 @@
BITS = 32
one = r_ulonglong(1)
elif size == 2:
- MIN_EXP = -13
- MAX_EXP = 16
+ MIN_EXP = -13
+ MAX_EXP = 16
MANT_DIG = 11
BITS = 16
one = r_ulonglong(1)
@@ -105,6 +72,36 @@
result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1)
return -result if sign else result
+def float_unpack80(QQ):
+ '''Unpack a (mant, exp) tuple of r_ulonglong in 80-bit extended format
+ into a long double float
+ '''
+ MIN_EXP = -16381
+ MAX_EXP = 16384
+ MANT_DIG = 64
+ TOPBITS = 80 - 64
+ one = r_ulonglong(1)
+ if len(QQ) != 2:
+ raise ValueError("QQ must be two 64 bit uints")
+ if not objectmodel.we_are_translated():
+ # This tests generates wrong code when translated:
+ # with gcc, shifting a 64bit int by 64 bits does
+ # not change the value.
+ if QQ[1] >> TOPBITS:
+ raise ValueError("input '%r' out of range '%r'" % (QQ, QQ[1]>>TOPBITS))
+
+ # extract pieces with explicit one in MANT_DIG
+ sign = rarithmetic.intmask(QQ[1] >> TOPBITS - 1)
+ exp = rarithmetic.intmask((QQ[1] & ((one << TOPBITS - 1) - 1)))
+ mant = QQ[0]
+
+ if exp == MAX_EXP - MIN_EXP + 2:
+ # nan or infinity
+ result = rfloat.NAN if mant &((one << MANT_DIG - 1) - 1) else rfloat.INFINITY
+ else:
+ # normal
+ result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1)
+ return -result if sign else result
def float_pack(x, size):
"""Convert a Python float x into a 64-bit unsigned integer
@@ -120,17 +117,10 @@
MANT_DIG = 24 # FLT_MANT_DIG
BITS = 32
elif size == 2:
- MIN_EXP = -13
- MAX_EXP = 16
+ MIN_EXP = -13
+ MAX_EXP = 16
MANT_DIG = 11
BITS = 16
- elif size == 16 or size == 12:
- #Implement a x86-hardware extended 80 bit format
- # with explicit 1 in bit 64
- MIN_EXP = -16381
- MAX_EXP = 16384
- MANT_DIG = 64
- BITS = 80
else:
raise ValueError("invalid size value")
@@ -177,21 +167,18 @@
assert 0 <= mant < 1 << MANT_DIG - 1
assert 0 <= exp <= MAX_EXP - MIN_EXP + 2
assert 0 <= sign <= 1
- if size==12 or size == 16:
- mant |= r_ulonglong(1) <<(MANT_DIG-1) #1 is explicit for 80bit extended format
- exp = exp << 1
exp = r_ulonglong(exp)
sign = r_ulonglong(sign)
return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
-def float_pack80(_x):
+def float_pack80(x):
"""Convert a Python float or longfloat x into two 64-bit unsigned integers
with 80 bit extended representation."""
MIN_EXP = -16381
MAX_EXP = 16384
- MANT_DIG = 64
+ MANT_DIG = 64
BITS = 80
- x = float(_x) #longfloat not really supported
+ x = float(x) # longfloat not really supported
sign = rfloat.copysign(1.0, x) < 0.0
if not rfloat.isfinite(x):
if rfloat.isinf(x):
@@ -237,6 +224,15 @@
sign = r_ulonglong(sign)
return (mant, (sign << BITS - MANT_DIG - 1) | exp)
+ at jit.unroll_safe
+def pack_float(result, x, size, be):
+ l = []
+ unsigned = float_pack(x, size)
+ for i in range(size):
+ l.append(chr((unsigned >> (i * 8)) & 0xFF))
+ if be:
+ l.reverse()
+ result.append("".join(l))
@jit.unroll_safe
def pack_float80(result, x, size, be):
@@ -250,16 +246,6 @@
l.reverse()
result.append("".join(l))
- at jit.unroll_safe
-def pack_float(result, x, size, be):
- l = []
- unsigned = float_pack(x, size)
- for i in range(size):
- l.append(chr((unsigned >> (i * 8)) & 0xFF))
- if be:
- l.reverse()
- result.append("".join(l))
-
def unpack_float(s, be):
unsigned = r_ulonglong(0)
for i in range(len(s)):
diff --git a/rpython/rlib/rstruct/test/test_ieee.py b/rpython/rlib/rstruct/test/test_ieee.py
--- a/rpython/rlib/rstruct/test/test_ieee.py
+++ b/rpython/rlib/rstruct/test/test_ieee.py
@@ -5,9 +5,7 @@
from rpython.rlib.rfloat import isnan
from rpython.rlib.rstruct.ieee import float_pack, float_unpack, float_pack80, float_unpack80
-
class TestFloatPacking:
-
def setup_class(cls):
if sys.version_info < (2, 6):
py.test.skip("the 'struct' module of this old CPython is broken")
@@ -61,6 +59,13 @@
self.check_float(0.0)
self.check_float(-0.0)
+ def test_check_size(self):
+ # these were refactored into separate pack80/unpack80 functions
+ py.test.raises(ValueError, float_pack, 1.0, 12)
+ py.test.raises(ValueError, float_pack, 1.0, 16)
+ py.test.raises(ValueError, float_unpack, 1, 12)
+ py.test.raises(ValueError, float_unpack, 1, 16)
+
def test_nans(self):
Q = float_pack80(float('nan'))
y = float_unpack80(Q)
@@ -161,4 +166,3 @@
f_out = math.copysign(float('inf'), f1)
assert f_out == f2
assert math.copysign(1., f_out) == math.copysign(1., f2)
-
More information about the pypy-commit
mailing list