Author: mattip <[email protected]>
Branch: numpypy.float16
Changeset: r58669:a48a08333d1a
Date: 2012-10-30 05:04 +0200
http://bitbucket.org/pypy/pypy/changeset/a48a08333d1a/
Log: test, implement float16bits to doublebits and back
diff --git a/pypy/module/micronumpy/halffloat.py
b/pypy/module/micronumpy/halffloat.py
--- a/pypy/module/micronumpy/halffloat.py
+++ b/pypy/module/micronumpy/halffloat.py
@@ -80,13 +80,12 @@
# npy_set_floatstatus_underflow()
f_sig >>= (113 - f_exp)
# Handle rounding by adding 1 to the bit beyond half precision
-
if (f_sig & 0x00003fff) != 0x00001000:
# The last remaining bit is 1, and the rmaining bit pattern
# is not 1000...0, so round up
f_sig += 0x00001000
h_sig = f_sig >> 13
- # If the rounding cuased a bit to spill into h_exp, it will
+ # If the rounding caused a bit to spill into h_exp, it will
# increment h_exp from zero to one and h_sig will remain zero
# which is the correct result.
return h_sgn + h_sig
@@ -108,3 +107,88 @@
#npy_set_floatstatus_overflow()
return h_sgn + h_sig
+def halfbits_to_doublebits(h):
+ h_exp = h & 0x7c00
+ d_sgn = h >>15 << 63
+ if h_exp == 0: #0 or subnormal
+ h_sig = h & 0x03ff
+ if h_sig == 0:
+ return d_sgn
+ #Subnormal
+ h_sig <<= 1;
+ while (h_sig & 0x0400) == 0:
+ h_sig <<= 1
+ h_exp += 1
+ d_exp = ((1023 - 15 - h_exp)) << 52
+ d_sig = ((h_sig & 0x03ff)) << 42
+ return d_sgn + d_exp + d_sig;
+ elif h_exp == 0x7c00: # inf or nan
+ return d_sgn + 0x7ff0000000000000 + ((h & 0x03ff) << 42)
+ return d_sgn + (((h & 0x7fff) + 0xfc000) << 42)
+
+def doublebits_to_halfbits(d):
+ h_sgn = (d & 0x8000000000000000) >> 48
+ d_exp = (d & 0x7ff0000000000000)
+ if d_exp >= 0x40f0000000000000:
+ # Exponent overflow, convert to signed inf/nan
+ if d_exp == 0x7ff0000000000000:
+ # inf or nan
+ d_sig = d & 0x000fffffffffffff
+ if d_sig != 0:
+ #nan - propagate the flag in the significand
+ ret = 0x7c00 + (d_sig >> 42)
+ # ... but make sure it stays a nan
+ if ret == 0x7c00:
+ ret += 1
+ return h_sgn + ret
+ else:
+ # signed inf
+ return h_sgn + 0x7c00
+ else:
+ # overflow to signed inf
+ # npy_set_floatstatus_overflow()
+ return h_sgn + 0x7c00
+ if d_exp <= 0x3f00000000000000:
+ # Exponent underflow converts to a subnormal half or signed zero
+ if d_exp < 0x3e60000000000000:
+ # Signed zeros, subnormal floats, and floats with small
+ # exponents all conver to signed zero halfs
+ if d & 0x7fffffffffffffff != 0:
+ pass
+ # npy_set_floatstatus_underflow()
+ return h_sgn
+ # Make the subnormal significand
+ d_exp >>= 52
+ d_sig = 0x0010000000000000 + (d & 0x000fffffffffffff)
+ if (d_sig & ((1 << (1051 - d_exp)) - 1)) != 0:
+ # not exactly represented, therefore underflowed
+ pass
+ # npy_set_floatstatus_underflow()
+ d_sig >>= (1009 - d_exp)
+ # Handle rounding by adding 1 to the bit beyond half precision
+ if (d_sig & 0x000007ffffffffff) != 0x0000020000000000:
+ # The last remaining bit is 1, and the rmaining bit pattern
+ # is not 1000...0, so round up
+ d_sig += 0x0000020000000000
+ h_sig = d_sig >> 42
+ # If the rounding caused a bit to spill into h_exp, it will
+ # increment h_exp from zero to one and h_sig will remain zero
+ # which is the correct result.
+ return h_sgn + h_sig
+ # No overflow or underflow
+ h_exp = (d_exp - 0x3f00000000000000) >> 42
+ d_sig = d & 0x000fffffffffffff
+ if (d_sig & 0x000007ffffffffff) != 0x0000020000000000:
+ # The last remaining bit is 1, and the rmaining bit pattern
+ # is not 1000...0, so round up
+ d_sig += 0x0000020000000000
+ h_sig = d_sig >> 42
+ # If the rounding cuased a bit to spill into h_exp, it will
+ # increment h_exp from zero to one and h_sig will remain zero
+ # which is the correct result. However, h_exp may increment to
+ # 15, at greatest, in which case the result overflows
+ h_sig += h_exp
+ if h_sig == 0x7c00:
+ pass
+ #npy_set_floatstatus_overflow()
+ return h_sgn + h_sig
diff --git a/pypy/module/micronumpy/test/test_halffloat.py
b/pypy/module/micronumpy/test/test_halffloat.py
--- a/pypy/module/micronumpy/test/test_halffloat.py
+++ b/pypy/module/micronumpy/test/test_halffloat.py
@@ -7,8 +7,8 @@
from pypy.module.micronumpy import halffloat
cls.w_halffloat = cls.space.wrap(halffloat)
- def test_bitconvert_exact(self):
- #from _numpypy import array, uint32
+ def test_bitconvert_exact_f(self):
+ #from _numpypy import array, uint32 ## Do this when 'view' works
# These test cases were created by
# numpy.float32(v).view(uint32)
# numpy.float16(v).view(uint16)
@@ -22,7 +22,8 @@
assert [f, v] == [hbits, v]
f = self.halffloat.halfbits_to_floatbits(hbits)
assert [f, v] == [fbits, v]
- def test_bitconvert_inexact(self):
+
+ def test_bitconvert_inexact_f(self):
# finexact is
# numpy.float32(numpy.float16(v)).view(uint32)
cases = [[10.001, 1092617241, 1092616192, 18688],
@@ -33,7 +34,8 @@
assert [f, v] == [hbits, v]
f = self.halffloat.halfbits_to_floatbits(hbits)
assert [f, v] == [finexact, v]
- def test_bitconvert_overunderfloat(self):
+
+ def test_bitconvert_overunderflow_f(self):
cases = [[67000.0, 1199758336, 2139095040, 31744],
[-67000.0, 3347241984, 4286578688, 64512],
[1e-08, 841731191, 0, 0],
@@ -44,3 +46,33 @@
assert [f, v] == [hbits, v]
f = self.halffloat.halfbits_to_floatbits(hbits)
assert [f, v] == [finexact, v]
+
+ def test_bitconvert_exact_d(self):
+ #from _numpypy import array, uint32 ## Do this when 'view' works
+ # These test cases were created by
+ # numpy.float64(v).view(uint64)
+ # numpy.float16(v).view(uint16)
+ cases =[[0, 0, 0], [10, 4621819117588971520, 18688],
+ [-10, 13845191154443747328, 51456],
+ [10000.0, 4666723172467343360, 28898],
+ [float('inf'), 9218868437227405312, 31744],
+ [-float('inf'), 18442240474082181120, 64512]]
+ for v, dbits, hbits in cases:
+ # No 'view' in numpypy yet
+ # dbits = array(v, dtype='float64').view(uint64)
+ h = self.halffloat.doublebits_to_halfbits(dbits)
+ assert [h, v] == [hbits, v]
+ d = self.halffloat.halfbits_to_doublebits(hbits)
+ assert [d, v] == [dbits, v]
+
+ def test_bitconvert_inexact_d(self):
+ # finexact is
+ # numpy.float64(numpy.float16(v)).view(uint64)
+ cases = [[10.001, 4621819680538924941, 4621819117588971520, 18688],
+ [-10.001, 13845191717393700749, 13845191154443747328, 51456],
+ [22001, 4671776802786508800, 4671776527908601856, 30047]]
+ for v, fexact, finexact, hbits in cases:
+ f = self.halffloat.doublebits_to_halfbits(fexact)
+ assert [f, v] == [hbits, v]
+ f = self.halffloat.halfbits_to_doublebits(hbits)
+ assert [f, v] == [finexact, v]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit