def parse_tab_entry(self): t_type = self.uleb() if t_type == 0: # NIL return W_Pri(0) elif t_type == 1: # FALSE return W_Pri(1) elif t_type == 2: # TRUE return W_Pri(2) elif t_type == 3: # INT return W_Num(self.uleb()) elif t_type == 4: # for some reason luajit does save # table values as floats and makes no # distinction between float and int numbers # so we cant user Parser.read_knum lo = self.uleb() hi = self.uleb() hi = hi << 32 res = float_unpack(lo | hi, 8) i_res = int(res) # TODO improve # numbers are stored as floats, so res is a float, # but if its whole number the string of the number has # a .0 at the end, but when accessing the key does not # have .0 if (res - i_res) == 0: return W_Num(i_res) else: return W_Num(res) else: return self.const_str(t_type)
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.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 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_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 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 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 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 read_knum(self): isnum = self.peek() & 1 lo = self.uleb() >> 1 if isnum == 1: """ IEEE 64 bit floating point constant """ hi = self.uleb() hi = hi << 32 res = float_unpack(lo | hi, 8) # TODO n_val can be a float or a int, can this lead # to problems when translating? return W_Num(res) # check if int contant is negative # TODO: not sure if check is correct if lo & (1 << 31) != 0: lo = lo - (1 << 32) return W_Num(lo)
def fillin_fromwords(self, space, high, low): # TODO: support for larger float values? r = (r_ulonglong(high) << 32) | low self.value = float_unpack(r, 8)
def getvalue(self): # Should be rarely called, probably only to do arithmetic once, and then # return a new W_Float. from rpython.rlib.rstruct.ieee import float_unpack return float_unpack( (r_ulonglong(self.high) << 32) | r_ulonglong(self.low), 8)
def getvalue(self): # Should be rarely called, probably only to do arithmetic once, and then # return a new W_Float. from rpython.rlib.rstruct.ieee import float_unpack return float_unpack((r_ulonglong(self.high) << 32) | r_ulonglong(self.low), 8)
def bits2float(bits): #data_str = struct.pack ( 'I', bits ) #flt = struct.unpack( 'f', data_str )[0] flt = ieee.float_unpack(bits, 4) return flt
def fillin_fromwords(self, space, high, low): from rpython.rlib.rstruct.ieee import float_unpack from rpython.rlib.rarithmetic import r_ulonglong r = (r_ulonglong(high) << 32) | low self.value = float_unpack(r, 8)