Author: mattip <[email protected]>
Branch: numpypy-longdouble
Changeset: r59543:3fbc98dc8730
Date: 2012-12-13 22:57 -0800
http://bitbucket.org/pypy/pypy/changeset/3fbc98dc8730/
Log: test, implement pack_float128 which returns a 128 bit int
r_ulonglonglong along the way, implement and test r_ulonglonglong
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -489,6 +489,7 @@
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:
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
@@ -5,7 +5,7 @@
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):
@@ -27,24 +27,33 @@
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")
@@ -56,7 +65,6 @@
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)
@@ -77,7 +85,14 @@
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
@@ -93,40 +108,46 @@
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
@@ -140,8 +161,8 @@
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
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
@@ -3,7 +3,7 @@
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:
@@ -18,6 +18,13 @@
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)
diff --git a/pypy/rlib/test/test_rarithmetic.py
b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -165,12 +165,12 @@
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
@@ -369,6 +369,11 @@
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)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit