Author: mattip <[email protected]>
Branch: numpypy-longdouble
Changeset: r59573:b544731e8eab
Date: 2012-12-25 04:20 +0200
http://bitbucket.org/pypy/pypy/changeset/b544731e8eab/
Log: fix nan, simplify interface
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
@@ -25,19 +25,15 @@
int_part += 1
return int_part
-def float_unpack80(QQ, size):
- '''Unpack a (mant, exp) tuple of r_ulonglong into a long double float
+def float_unpack80(QQ):
+ '''Unpack a (mant, exp) tuple of r_ulonglong in 80-bit extended format
+ into a long double float
'''
- if size == 16 or size == 12:
- #Implement a x86-hardware extended 80 bit format as two 64 bit uints
- # QQ[0] is the sign and exp, QQ[1] is the mant
- MIN_EXP = -16381
- MAX_EXP = 16384
- MANT_DIG = 64
- TOPBITS = 80 - 64
- one = r_ulonglong(1)
- else:
- raise ValueError("invalid size value")
+ 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():
@@ -188,18 +184,13 @@
sign = r_ulonglong(sign)
return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
-def float_pack80(x, size):
+def float_pack80(x):
"""Convert a Python float x into two 64-bit unsigned integers
- with the same byte representation."""
- if 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")
+ with 80 bit extended representation."""
+ MIN_EXP = -16381
+ MAX_EXP = 16384
+ MANT_DIG = 64
+ BITS = 80
sign = rfloat.copysign(1.0, x) < 0.0
if not rfloat.isfinite(x):
@@ -207,7 +198,7 @@
mant = r_ulonglong(0)
exp = MAX_EXP - MIN_EXP + 2
else: # rfloat.isnan(x):
- mant = r_ulonglong(1) << (MANT_DIG-2) # other values possible
+ mant = (r_ulonglong(1) << (MANT_DIG-2)) - 1 # other values possible
exp = MAX_EXP - MIN_EXP + 2
elif x == 0.0:
mant = r_ulonglong(0)
@@ -241,8 +232,7 @@
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 = mant << 1
+ mant = mant << 1
exp = r_ulonglong(exp)
sign = r_ulonglong(sign)
return (mant, (sign << BITS - MANT_DIG - 1) | exp)
@@ -251,9 +241,16 @@
@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 size == 12 or size == 16:
+ unsigned = float_pack80(x)
+ for i in range(8):
+ l.append(chr((unsigned[0] >> (i * 8)) & 0xFF))
+ for i in range(size - 8):
+ l.append(chr((unsigned[1] >> (i * 8)) & 0xFF))
+ else:
+ 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))
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
@@ -18,11 +18,8 @@
y = float_unpack(Q, 8)
assert repr(x) == repr(y)
- Q = float_pack80(x, 16)
- y = float_unpack80(Q, 16)
- assert repr(x) == repr(y),'%r != %r, Q=%r'%(x, y, Q)
- Q = float_pack80(x, 12)
- y = float_unpack80(Q, 12)
+ Q = float_pack80(x)
+ y = float_unpack80(Q)
assert repr(x) == repr(y),'%r != %r, Q=%r'%(x, y, Q)
# check that packing agrees with the struct module
@@ -65,11 +62,8 @@
self.check_float(-0.0)
def test_nans(self):
- Q = float_pack80(float('nan'), 16)
- y = float_unpack80(Q, 16)
- assert repr(y) == 'nan'
- Q = float_pack80(float('nan'), 12)
- y = float_unpack80(Q, 12)
+ Q = float_pack80(float('nan'))
+ y = float_unpack80(Q)
assert repr(y) == 'nan'
Q = float_pack(float('nan'), 8)
y = float_unpack(Q, 8)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit