def test_various_nans(self): # check patterns that should preserve the mantissa across nan conversions maxmant64 = (1 << 52) - 1 # maximum double mantissa maxmant16 = (1 << 10) - 1 # maximum float16 mantissa assert maxmant64 >> 42 == maxmant16 exp = 0xfff << 52 for i in range(20): val_to_preserve = exp | ((maxmant16 - i) << 42) a = ieee.float_unpack(val_to_preserve, 8) assert isnan(a), 'i %d, maxmant %s' % (i, hex(val_to_preserve)) b = ieee.float_pack(a, 8) assert b == val_to_preserve, 'i %d, val %s b %s' % (i, hex(val_to_preserve), hex(b)) b = ieee.float_pack(a, 2) assert b == 0xffff - i, 'i %d, b%s' % (i, hex(b))
def test_various_nans(self): # check patterns that should preserve the mantissa across nan conversions maxmant64 = (1 << 52) - 1 # maximum double mantissa maxmant16 = (1 << 10) - 1 # maximum float16 mantissa assert maxmant64 >> 42 == maxmant16 exp = 0xfff << 52 for i in range(20): val_to_preserve = exp | ((maxmant16 - i) << 42) a = ieee.float_unpack(val_to_preserve, 8) assert isnan(a), 'i %d, maxmant %s' % (i, hex(val_to_preserve)) b = ieee.float_pack(a, 8) assert b == val_to_preserve, 'i %d, val %s b %s' % ( i, hex(val_to_preserve), hex(b)) b = ieee.float_pack(a, 2) assert b == 0xffff - i, 'i %d, b%s' % (i, hex(b))
def test_halffloat_inexact(self): # testcases generated from numpy.float16(x).view('uint16') cases = [[10.001, 18688, 10.0], [-10.001, 51456, -10], [0.027588, 10000, 0.027587890625], [22001, 30047, 22000]] for c, h, f in cases: hbit = ieee.float_pack(c, 2) assert hbit == h assert f == ieee.float_unpack(h, 2)
def test_halffloat_exact(self): # testcases generated from numpy.float16(x).view('uint16') cases = [[0, 0], [10, 18688], [-10, 51456], [10e3, 28898], [float("inf"), 31744], [-float("inf"), 64512]] for c, h in cases: hbit = ieee.float_pack(c, 2) assert hbit == h assert c == ieee.float_unpack(h, 2)
def check_float(self, x): # check roundtrip for size in [10, 12, 16]: for be in [False, True]: Q = [] ieee.pack_float80(Q, x, size, be) Q = Q[0] y = ieee.unpack_float80(Q, be) assert repr(x) == repr(y), '%r != %r, Q=%r' % (x, y, Q) for be in [False, True]: Q = [] ieee.pack_float(Q, x, 8, be) Q = Q[0] y = ieee.unpack_float(Q, be) assert repr(x) == repr(y), '%r != %r, Q=%r' % (x, y, Q) # check that packing agrees with the struct module struct_pack8 = struct.unpack('<Q', struct.pack('<d', x))[0] float_pack8 = ieee.float_pack(x, 8) assert struct_pack8 == float_pack8 # check that packing agrees with the struct module try: struct_pack4 = struct.unpack('<L', struct.pack('<f', x))[0] except OverflowError: struct_pack4 = "overflow" try: float_pack4 = ieee.float_pack(x, 4) except OverflowError: float_pack4 = "overflow" assert struct_pack4 == float_pack4 if float_pack4 == "overflow": return # if we didn't overflow, try round-tripping the binary32 value roundtrip = ieee.float_pack(ieee.float_unpack(float_pack4, 4), 4) assert float_pack4 == roundtrip try: float_pack2 = ieee.float_pack(x, 2) except OverflowError: return roundtrip = ieee.float_pack(ieee.float_unpack(float_pack2, 2), 2) assert (float_pack2, x) == (roundtrip, x)
def test_halffloat_exact(self): #testcases generated from numpy.float16(x).view('uint16') cases = [[0, 0], [10, 18688], [-10, 51456], [10e3, 28898], [float('inf'), 31744], [-float('inf'), 64512]] for c, h in cases: hbit = ieee.float_pack(c, 2) assert hbit == h assert c == ieee.float_unpack(h, 2)
def test_halffloat_inexact(self): #testcases generated from numpy.float16(x).view('uint16') cases = [[10.001, 18688, 10.], [-10.001, 51456, -10], [0.027588, 10000, 0.027587890625], [22001, 30047, 22000]] for c, h, f in cases: hbit = ieee.float_pack(c, 2) assert hbit == h assert f == ieee.float_unpack(h, 2)
def fetch(self, space, n0): from rpython.rlib.rstruct.ieee import float_pack r = float_pack(self.value, 8) # C double if n0 == 0: return space.wrap_uint(r_uint(intmask(r >> 32))) else: # bounds-check for primitive access is done in the primitive assert n0 == 1 return space.wrap_uint(r_uint(intmask(r)))
def store(self, space, n0, w_obj): uint = r_ulonglong(space.unwrap_uint(w_obj)) r = float_pack(self.getvalue(), 8) if n0 == 0: r = ((r << 32) >> 32) | (uint << 32) else: assert n0 == 1 r = ((r >> 32) << 32) | uint self.value = float_unpack(r, 8)
def test_halffloat_overunderflow(self): cases = [[670000, float('inf')], [-67000, -float('inf')], [1e-08, 0], [-1e-8, -0.]] for f1, f2 in cases: try: f_out = ieee.float_unpack(ieee.float_pack(f1, 2), 2) except OverflowError: f_out = math.copysign(float('inf'), f1) assert f_out == f2 assert math.copysign(1., f_out) == math.copysign(1., f2)
def test_halffloat_overunderflow(self): import math cases = [[670000, float('inf')], [-67000, -float('inf')], [1e-08, 0], [-1e-8, -0.]] for f1, f2 in cases: try: f_out = ieee.float_unpack(ieee.float_pack(f1, 2), 2) except OverflowError: f_out = math.copysign(float('inf'), f1) assert f_out == f2 assert math.copysign(1., f_out) == math.copysign(1., f2)
def store(self, space, n0, w_obj): from rpython.rlib.rstruct.ieee import float_unpack, float_pack from rpython.rlib.rarithmetic import r_ulonglong uint = r_ulonglong(space.unwrap_uint(w_obj)) r = float_pack(self.value, 8) if n0 == 0: r = ((r << 32) >> 32) | (uint << 32) else: assert n0 == 1 r = ((r >> 32) << 32) | uint self.value = float_unpack(r, 8)
def pack_float(space, packer, repetitions): if repetitions > len(packer.args_w) - packer.args_index: raise space.error(space.w_ArgumentError, "too few arguments") for i in xrange(packer.args_index, repetitions + packer.args_index): w_item = packer.args_w[i] if not (isinstance(w_item, W_FloatObject) or isinstance(w_item, W_FixnumObject)): raise space.error(space.w_TypeError, "can't convert %s into Float" % space.obj_to_s(space.getclass(w_item)) ) doubleval = space.float_w(w_item) l = ["\0"] * size try: unsigned = float_pack(doubleval, size) except OverflowError: unsigned = float_pack(rfloat.copysign(rfloat.INFINITY, doubleval), size) for i in xrange(size): l[i] = chr((unsigned >> (i * 8)) & 0xff) if bigendian: l.reverse() packer.result.extend(l) packer.args_index += repetitions
def fetch(self, space, n0): r = float_pack(self.getvalue(), 8) # C double if n0 == 0: return space.wrap_int(r_uint32(intmask(r >> 32))) else: # bounds-check for primitive access is done in the primitive assert n0 == 1 if constants.IS_64BIT: # mask the bits above 32 return space.wrap_int(r_uint32(intmask(r & 0xffffffff))) else: return space.wrap_int(r_uint32(intmask(r)))
def pack_float(space, packer, repetitions): if repetitions > len(packer.args_w) - packer.args_index: raise space.error(space.w_ArgumentError, "too few arguments") for i in xrange(packer.args_index, repetitions + packer.args_index): w_item = packer.args_w[i] if not (isinstance(w_item, W_FloatObject) or isinstance(w_item, W_FixnumObject)): raise space.error(space.w_TypeError, "can't convert %s into Float" % space.obj_to_s(space.getclass(w_item)) ) doubleval = space.float_w(w_item) l = ["\0"] * size try: unsigned = float_pack(doubleval, size) except OverflowError: unsigned = float_pack(math.copysign(special_value.INF, doubleval), size) for i in xrange(size): l[i] = chr((unsigned >> (i * 8)) & 0xff) if bigendian: l.reverse() packer.result.extend(l) packer.args_index += repetitions
def float2bits(flt): #data_str = struct.pack ( 'f', flt ) #bits = struct.unpack( 'I', data_str )[0] # float_pack returns an r_int rather than an int, must cast it or # arithmetic operations behave differently! try: bits = trim(intmask(ieee.float_pack(flt, 4))) # float_pack also will throw an OverflowError if the computed value # won't fit in the expected number of bytes, catch this and return # the encoding for inf/-inf except OverflowError: bits = 0x7f800000 if flt > 0 else 0xff800000 return bits
def toBytes(self): # float_pack() takes a double and gives us the packed integer; we need # to reinterpret it as packed ASCII and repack into bytes. x = float_pack(self._d, 8) return "".join([chr(x >> ((7 - i) * 8) & 0xff) for i in range(8)])
def setvalue(self, v): # This will only be called if we `become' a W_MutableFloat, should be rare r = float_pack(v, 8) # just shift and mask self.high = r_uint32(r >> 32) self.low = r_uint32(r)