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

Reply via email to