def unpack_ieee(fmtiter): size = rffi.sizeof(TYPE) if fmtiter.bigendian != native_is_bigendian or not native_is_ieee754: # fallback to the very slow unpacking code in ieee.py data = fmtiter.read(size) fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian)) return ## XXX check if the following code is still needed ## if not str_storage_supported(TYPE): ## # this happens e.g. on win32 and ARM32: we cannot read the string ## # content as an array of doubles because it's not properly ## # aligned. But we can read a longlong and convert to float ## assert TYPE == rffi.DOUBLE ## assert rffi.sizeof(TYPE) == 8 ## return unpack_longlong2float(fmtiter) try: # fast path val = unpack_fastpath(TYPE)(fmtiter) except CannotRead: # slow path: we should arrive here only if we could not unpack # because of alignment issues. So we copy the slice into a new # string, which is guaranteed to be properly aligned, and read the # float/double from there input = fmtiter.read(size) val = StringBuffer(input).typed_read(TYPE, 0) fmtiter.appendobj(float(val))
def recv(self, atom, args): if atom is RUN_1: return DoubleObject(float(unwrapStr(args[0]).encode('utf-8'))) if atom is FROMBYTES_1: data = unwrapList(args[0]) x = unpack_float("".join([chr(unwrapInt(byte)) for byte in data]), True) return DoubleObject(x) raise Refused(self, atom, args)
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 unpack_ieee(fmtiter): size = rffi.sizeof(TYPE) if fmtiter.bigendian != native_is_bigendian or not native_is_ieee754: # fallback to the very slow unpacking code in ieee.py data = fmtiter.read(size) fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian)) return ## XXX check if the following code is still needed ## if not str_storage_supported(TYPE): ## # this happens e.g. on win32 and ARM32: we cannot read the string ## # content as an array of doubles because it's not properly ## # aligned. But we can read a longlong and convert to float ## assert TYPE == rffi.DOUBLE ## assert rffi.sizeof(TYPE) == 8 ## return unpack_longlong2float(fmtiter) try: # fast path val = unpack_fastpath(TYPE)(fmtiter) except CannotUnpack: # slow path, take the slice input = fmtiter.read(size) val = str_storage_getitem(TYPE, input, 0) fmtiter.appendobj(float(val))
def rdouble(fd): data = fd.read(8) return Float(ieee.unpack_float(data, True))
def unpacker(fmtiter): data = fmtiter.read(size) fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian))
def read_double(self): data = self.read(8) return ieee.unpack_float(data, False)
def unpack(s): l = s.split(',') s = ''.join([chr(int(x)) for x in l]) return ieee.unpack_float(s, False)
def unpack_float(s): return ieee.unpack_float(s, False)
def unpack_halffloat(fmtiter): data = fmtiter.read(2) fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian))
def array_reconstructor(space, w_cls, typecode, mformat_code, w_items): # Fast path: machine format code corresponds to the # platform-independent typecode. if mformat_code == typecode_to_mformat_code(typecode): return interp_array.w_array( space, w_cls, typecode, Arguments(space, [w_items])) if typecode not in interp_array.types: raise OperationError(space.w_ValueError, space.wrap("invalid type code")) if (mformat_code < MACHINE_FORMAT_CODE_MIN or mformat_code > MACHINE_FORMAT_CODE_MAX): raise OperationError(space.w_ValueError, space.wrap("invalid machine format code")) # Slow path: Decode the byte string according to the given machine # format code. This occurs when the computer unpickling the array # object is architecturally different from the one that pickled # the array. if (mformat_code == IEEE_754_FLOAT_LE or mformat_code == IEEE_754_FLOAT_BE or mformat_code == IEEE_754_DOUBLE_LE or mformat_code == IEEE_754_DOUBLE_BE): descr = format_descriptors[mformat_code] memstr = space.bytes_w(w_items) step = descr.bytes converted_items = [ space.wrap(ieee.unpack_float( memstr[i:i+step], descr.big_endian)) for i in range(0, len(memstr), step)] w_converted_items = space.newlist(converted_items) elif mformat_code == UTF16_LE: w_converted_items = space.call_method( w_items, "decode", space.wrap("utf-16-le")) elif mformat_code == UTF16_BE: w_converted_items = space.call_method( w_items, "decode", space.wrap("utf-16-be")) elif mformat_code == UTF32_LE: w_converted_items = space.call_method( w_items, "decode", space.wrap("utf-32-le")) elif mformat_code == UTF32_BE: w_converted_items = space.call_method( w_items, "decode", space.wrap("utf-32-be")) else: descr = format_descriptors[mformat_code] # If possible, try to pack array's items using a data type # that fits better. This may result in an array with narrower # or wider elements. # # For example, if a 32-bit machine pickles a L-code array of # unsigned longs, then the array will be unpickled by 64-bit # machine as an I-code array of unsigned ints. # # XXX: Is it possible to write a unit test for this? for tc in interp_array.unroll_typecodes: typecode_descr = interp_array.types[tc] if (typecode_descr.is_integer_type() and typecode_descr.bytes == descr.bytes and typecode_descr.signed == descr.signed): typecode = tc break memstr = space.bytes_w(w_items) step = descr.bytes converted_items = [ space.newlong_from_rbigint(rbigint.rbigint.frombytes( memstr[i:i+step], descr.big_endian and 'big' or 'little', descr.signed)) for i in range(0, len(memstr), step)] w_converted_items = space.newlist(converted_items) return interp_array.w_array( space, w_cls, typecode, Arguments(space, [w_converted_items]))
def fromBytes(self, bs, ej): try: return unpack_float(bs, True) except ValueError: throwStr(ej, u"Couldn't unpack invalid IEEE 754 double")
def nextDouble(self): # Second parameter is the big-endian flag. return unpack_float(self.nextBytes(8), True)
def nextDouble(self): # Second parameter is the big-endian flag. try: return unpack_float(self.nextBytes(8), True) except ValueError: raise InvalidMAST("Couldn't decode invalid double")
def array_reconstructor(space, w_cls, typecode, mformat_code, w_items): # Fast path: machine format code corresponds to the # platform-independent typecode. if mformat_code == typecode_to_mformat_code(typecode): return interp_array.w_array(space, w_cls, typecode, Arguments(space, [w_items])) if typecode not in interp_array.types: raise oefmt(space.w_ValueError, "invalid type code") if (mformat_code < MACHINE_FORMAT_CODE_MIN or mformat_code > MACHINE_FORMAT_CODE_MAX): raise oefmt(space.w_ValueError, "invalid machine format code") # Slow path: Decode the byte string according to the given machine # format code. This occurs when the computer unpickling the array # object is architecturally different from the one that pickled # the array. if (mformat_code == IEEE_754_FLOAT_LE or mformat_code == IEEE_754_FLOAT_BE or mformat_code == IEEE_754_DOUBLE_LE or mformat_code == IEEE_754_DOUBLE_BE): descr = format_descriptors[mformat_code] memstr = space.bytes_w(w_items) step = descr.bytes converted_items = [ space.newfloat( ieee.unpack_float(memstr[i:i + step], descr.big_endian)) for i in range(0, len(memstr), step) ] w_converted_items = space.newlist(converted_items) elif mformat_code == UTF16_LE: w_converted_items = space.call_method(w_items, "decode", space.newtext("utf-16-le")) elif mformat_code == UTF16_BE: w_converted_items = space.call_method(w_items, "decode", space.newtext("utf-16-be")) elif mformat_code == UTF32_LE: w_converted_items = space.call_method(w_items, "decode", space.newtext("utf-32-le")) elif mformat_code == UTF32_BE: w_converted_items = space.call_method(w_items, "decode", space.newtext("utf-32-be")) else: descr = format_descriptors[mformat_code] # If possible, try to pack array's items using a data type # that fits better. This may result in an array with narrower # or wider elements. # # For example, if a 32-bit machine pickles a L-code array of # unsigned longs, then the array will be unpickled by 64-bit # machine as an I-code array of unsigned ints. # # XXX: Is it possible to write a unit test for this? for tc in interp_array.unroll_typecodes: typecode_descr = interp_array.types[tc] if (typecode_descr.is_integer_type() and typecode_descr.bytes == descr.bytes and typecode_descr.signed == descr.signed): typecode = tc break memstr = space.bytes_w(w_items) step = descr.bytes converted_items = [ space.newlong_from_rbigint( rbigint.rbigint.frombytes( memstr[i:i + step], descr.big_endian and 'big' or 'little', descr.signed)) for i in range(0, len(memstr), step) ] w_converted_items = space.newlist(converted_items) return interp_array.w_array(space, w_cls, typecode, Arguments(space, [w_converted_items]))