def float_bytes_to_real(bytes, signed): # XXX Currently does not make use of the signed parameter if len(bytes) not in (4, 8): raise SchemeException( "floating-point-bytes->real: byte string must have length 2, 4, or 8") try: if objectmodel.we_are_translated(): val = rarithmetic.r_int64(0) for i, v in enumerate(bytes): val += rarithmetic.r_int64(ord(v)) << (i * 8) return values.W_Flonum(longlong2float.longlong2float(val)) else: # use unsigned to avoid rlib bug val = rarithmetic.r_uint64(0) for i, v in enumerate(bytes): val += rarithmetic.r_uint64(ord(v)) << (i * 8) return values.W_Flonum(pycket_longlong2float(val)) except OverflowError, e: # Uncomment the check below to run Pycket on the # interpreter with compiled (zo) files # (fasl makes a call that blows the longlong2float on rpython) # if val == 18442240474082181120L: # return values.W_Flonum.NEGINF raise SchemeException("RPython overflow : %s" % e)
def _unbox(self, w_value): space = self.space assert type(w_value) is self.typ if type(w_value) is space.IntObjectCls: return longlong2float(space.int_w(w_value)) else: return space.float_w(w_value)
def unpack_longlong2float(fmtiter): from rpython.rlib.rstruct.runpack import runpack from rpython.rlib.longlong2float import longlong2float s = fmtiter.read(8) llval = runpack('q', s) # this is a bit recursive, I know doubleval = longlong2float(llval) fmtiter.appendobj(doubleval)
def test_int_or_float_special_nan(self): from rpython.rlib import longlong2float, rarithmetic space = self.space ll = rarithmetic.r_longlong(0xfffffffe12345678 - 2**64) specialnan = longlong2float.longlong2float(ll) w_l = W_ListObject(space, [space.wrap(1), space.wrap(specialnan)]) assert isinstance(w_l.strategy, ObjectListStrategy)
def float_unpack(Q, size): """Convert a 16-bit, 32-bit, or 64-bit integer created by float_pack into a Python float.""" if size == 8: MIN_EXP = -1021 # = sys.float_info.min_exp MAX_EXP = 1024 # = sys.float_info.max_exp MANT_DIG = 53 # = sys.float_info.mant_dig BITS = 64 elif size == 4: MIN_EXP = -125 # C's FLT_MIN_EXP MAX_EXP = 128 # FLT_MAX_EXP MANT_DIG = 24 # FLT_MANT_DIG BITS = 32 elif size == 2: MIN_EXP = -13 MAX_EXP = 16 MANT_DIG = 11 BITS = 16 else: raise ValueError("invalid size value") if not objectmodel.we_are_translated(): # This tests generates wrong code when translated: # with gcc, shifting a 64bit int by 64 bits does # not change the value. if Q >> BITS: raise ValueError("input '%r' out of range '%r'" % (Q, Q >> BITS)) # extract pieces with assumed 1.mant values one = r_ulonglong(1) sign = rarithmetic.intmask(Q >> BITS - 1) exp = rarithmetic.intmask((Q & ((one << BITS - 1) - (one << MANT_DIG - 1))) >> MANT_DIG - 1) mant = Q & ((one << MANT_DIG - 1) - 1) if exp == MAX_EXP - MIN_EXP + 2: # nan or infinity if mant == 0: result = rfloat.INFINITY else: # preserve at most 52 bits of mant value, but pad w/zeros exp = r_ulonglong(0x7ff) << 52 sign = r_ulonglong(sign) << 63 if MANT_DIG < 53: mant = r_ulonglong(mant) << (53 - MANT_DIG) if mant == 0: result = rfloat.NAN else: uint = exp | mant | sign result = longlong2float(cast(LONGLONG, uint)) return result elif exp == 0: # subnormal or zero result = math.ldexp(mant, MIN_EXP - MANT_DIG) else: # normal: add implicit one value mant += one << MANT_DIG - 1 result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1) return -result if sign else result
def read_location(self, obj): # assert isinstance(obj, Object) if self.is_set(obj): double_val = longlong2float( getattr(obj, "_primField" + str(field_idx))) return Double(double_val) else: return nilObject
def test_consistency_longlong2float_ll2ctypes(llval): # these definitions are used only in tests, when not translated #return struct.unpack('@d', struct.pack('@q', llval))[0] with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array: ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) ll_array[0] = llval floatval = d_array[0] assert repr(floatval) == repr(longlong2float(llval))
def float_unpack(Q, size): """Convert a 16-bit, 32-bit, or 64-bit integer created by float_pack into a Python float.""" if size == 8: MIN_EXP = -1021 # = sys.float_info.min_exp MAX_EXP = 1024 # = sys.float_info.max_exp MANT_DIG = 53 # = sys.float_info.mant_dig BITS = 64 elif size == 4: MIN_EXP = -125 # C's FLT_MIN_EXP MAX_EXP = 128 # FLT_MAX_EXP MANT_DIG = 24 # FLT_MANT_DIG BITS = 32 elif size == 2: MIN_EXP = -13 MAX_EXP = 16 MANT_DIG = 11 BITS = 16 else: raise ValueError("invalid size value") if not objectmodel.we_are_translated(): # This tests generates wrong code when translated: # with gcc, shifting a 64bit int by 64 bits does # not change the value. if Q >> BITS: raise ValueError("input '%r' out of range '%r'" % (Q, Q >> BITS)) # extract pieces with assumed 1.mant values one = r_ulonglong(1) sign = rarithmetic.intmask(Q >> BITS - 1) exp = rarithmetic.intmask((Q & ((one << BITS - 1) - (one << MANT_DIG - 1))) >> MANT_DIG - 1) mant = Q & ((one << MANT_DIG - 1) - 1) if exp == MAX_EXP - MIN_EXP + 2: # nan or infinity if mant == 0: result = rfloat.INFINITY else: # preserve at most 52 bits of mant value, but pad w/zeros exp = r_ulonglong(0x7FF) << 52 sign = r_ulonglong(sign) << 63 if MANT_DIG < 53: mant = r_ulonglong(mant) << (53 - MANT_DIG) if mant == 0: result = rfloat.NAN else: uint = exp | mant | sign result = longlong2float(cast(LONGLONG, uint)) return result elif exp == 0: # subnormal or zero result = math.ldexp(mant, MIN_EXP - MANT_DIG) else: # normal: add implicit one value mant += one << MANT_DIG - 1 result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1) return -result if sign else result
def integer_bytes_to_integer(bstr, signed): # XXX Currently does not make use of the signed parameter bytes = bstr.value if len(bytes) not in (4, 8): raise SchemeException("floating-point-bytes->real: byte string must have length 2, 4, or 8") val = 0 for i, v in enumerate(bytes): val += ord(v) << (i * 8) return values.W_Flonum(longlong2float.longlong2float(val))
def integer_bytes_to_integer(bstr, signed): # XXX Currently does not make use of the signed parameter bytes = bstr.value if len(bytes) not in (4, 8): raise SchemeException( "floating-point-bytes->real: byte string must have length 2, 4, or 8") val = 0 for i, v in enumerate(bytes): val += ord(v) << (i * 8) return values.W_Flonum(longlong2float.longlong2float(val))
def test_int_or_float_from_float_special_nan(self): from rpython.rlib import longlong2float, rarithmetic space = self.space w = space.wrap ll = rarithmetic.r_longlong(0xfffffffe12345678 - 2**64) specialnan = longlong2float.longlong2float(ll) w_l = W_ListObject(space, [space.wrap(specialnan)]) assert isinstance(w_l.strategy, FloatListStrategy) w_l.append(w(42)) assert isinstance(w_l.strategy, ObjectListStrategy) assert space.int_w(w_l.getitem(1)) == 42 assert space.len_w(w_l) == 2
def fn_encode_nan(f1, i2): from rpython.rlib.longlong2float import can_encode_float, can_encode_int32 from rpython.rlib.longlong2float import encode_int32_into_longlong_nan from rpython.rlib.longlong2float import decode_int32_from_longlong_nan from rpython.rlib.longlong2float import is_int32_from_longlong_nan assert can_encode_float(f1) assert can_encode_int32(i2) l1 = float2longlong(f1) l2 = encode_int32_into_longlong_nan(i2) assert not is_int32_from_longlong_nan(l1) assert is_int32_from_longlong_nan(l2) f1b = longlong2float(l1) assert f1b == f1 or (math.isnan(f1b) and math.isnan(f1)) assert decode_int32_from_longlong_nan(l2) == i2 return 42
def fn_encode_nan(f1, i2): from rpython.rlib.longlong2float import can_encode_float, can_encode_int32 from rpython.rlib.longlong2float import encode_int32_into_longlong_nan from rpython.rlib.longlong2float import decode_int32_from_longlong_nan from rpython.rlib.longlong2float import is_int32_from_longlong_nan from rpython.rlib.rfloat import isnan assert can_encode_float(f1) assert can_encode_int32(i2) l1 = float2longlong(f1) l2 = encode_int32_into_longlong_nan(i2) assert not is_int32_from_longlong_nan(l1) assert is_int32_from_longlong_nan(l2) f1b = longlong2float(l1) assert f1b == f1 or (isnan(f1b) and isnan(f1)) assert decode_int32_from_longlong_nan(l2) == i2 return 42
def byteswap(arg): """ Convert little->big endian and the opposite """ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.longlong2float import longlong2float, float2longlong,\ uint2singlefloat, singlefloat2uint T = lltype.typeOf(arg) if T == lltype.SingleFloat: arg = singlefloat2uint(arg) elif T == lltype.Float: arg = float2longlong(arg) elif T == lltype.LongFloat: assert False else: # we cannot do arithmetics on small ints arg = widen(arg) if rffi.sizeof(T) == 1: res = arg elif rffi.sizeof(T) == 2: a, b = arg & 0xFF, arg & 0xFF00 res = (a << 8) | (b >> 8) elif rffi.sizeof(T) == 4: FF = r_uint(0xFF) arg = r_uint(arg) a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16), arg & (FF << 24)) res = (a << 24) | (b << 8) | (c >> 8) | (d >> 24) elif rffi.sizeof(T) == 8: FF = r_ulonglong(0xFF) arg = r_ulonglong(arg) a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16), arg & (FF << 24)) e, f, g, h = (arg & (FF << 32), arg & (FF << 40), arg & (FF << 48), arg & (FF << 56)) res = ((a << 56) | (b << 40) | (c << 24) | (d << 8) | (e >> 8) | (f >> 24) | (g >> 40) | (h >> 56)) else: assert False # unreachable code if T == lltype.SingleFloat: return uint2singlefloat(rffi.cast(rffi.UINT, res)) if T == lltype.Float: return longlong2float(rffi.cast(rffi.LONGLONG, res)) return rffi.cast(T, res)
def float_unpack80(QQ, size): '''Unpack a (mant, exp) tuple of r_ulonglong in 80-bit extended format into a python float (a double) ''' if size == 10 or size == 12 or size == 16: MIN_EXP = -16381 MAX_EXP = 16384 MANT_DIG = 64 TOP_BITS = 80 - 64 else: raise ValueError("invalid size value") if len(QQ) != 2: raise ValueError("QQ must be two 64 bit uints") if not objectmodel.we_are_translated(): # This tests generates wrong code when translated: # with gcc, shifting a 64bit int by 64 bits does # not change the value. if QQ[1] >> TOP_BITS: raise ValueError("input '%r' out of range '%r'" % (QQ, QQ[1] >> TOP_BITS)) # extract pieces with explicit one in MANT_DIG one = r_ulonglong(1) sign = rarithmetic.intmask(QQ[1] >> TOP_BITS - 1) exp = rarithmetic.intmask((QQ[1] & ((one << TOP_BITS - 1) - 1))) mant = QQ[0] if exp == MAX_EXP - MIN_EXP + 2: # nan or infinity if mant == 0: result = rfloat.INFINITY else: exp = r_ulonglong(0x7ff) << 52 mant = r_ulonglong(mant) >> size + 1 if mant == 0: result = rfloat.NAN else: uint = exp | r_ulonglong(mant) | r_ulonglong(sign) result = longlong2float(cast(LONGLONG, uint)) return result else: # normal result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1) return -result if sign else result
def float_unpack80(QQ, size): """Unpack a (mant, exp) tuple of r_ulonglong in 80-bit extended format into a python float (a double) """ if size == 10 or size == 12 or size == 16: MIN_EXP = -16381 MAX_EXP = 16384 MANT_DIG = 64 TOP_BITS = 80 - 64 else: raise ValueError("invalid size value") if len(QQ) != 2: raise ValueError("QQ must be two 64 bit uints") if not objectmodel.we_are_translated(): # This tests generates wrong code when translated: # with gcc, shifting a 64bit int by 64 bits does # not change the value. if QQ[1] >> TOP_BITS: raise ValueError("input '%r' out of range '%r'" % (QQ, QQ[1] >> TOP_BITS)) # extract pieces with explicit one in MANT_DIG one = r_ulonglong(1) sign = rarithmetic.intmask(QQ[1] >> TOP_BITS - 1) exp = rarithmetic.intmask((QQ[1] & ((one << TOP_BITS - 1) - 1))) mant = QQ[0] if exp == MAX_EXP - MIN_EXP + 2: # nan or infinity if mant == 0: result = rfloat.INFINITY else: exp = r_ulonglong(0x7FF) << 52 mant = r_ulonglong(mant) >> size + 1 if mant == 0: result = rfloat.NAN else: uint = exp | r_ulonglong(mant) | r_ulonglong(sign) result = longlong2float(cast(LONGLONG, uint)) return result else: # normal result = math.ldexp(mant, exp + MIN_EXP - MANT_DIG - 1) return -result if sign else result
def _store(self, space, w_obj, w_value): w_obj.unboxed_storage[self.pos] = longlong2float.longlong2float( rffi.cast(lltype.SignedLongLong, space.int_w(w_value)))
def unwrap(self, w_val): if isinstance(w_val, W_Fixnum): bits = encode_int32_into_longlong_nan(w_val.value) return longlong2float(bits) assert isinstance(w_val, W_Flonum) return w_val.value
def fn(f1): ll = float2longlong(f1) f2 = longlong2float(ll) return f2
def f(f1): try: ll = float2longlong(f1) return longlong2float(ll) except Exception: return 500
def read_location(self, obj): if self.is_set(obj): val = longlong2float(obj._primFields[self._ext_idx]) return Double(val) else: return nilObject
def op_convert_longlong_bytes_to_float(a): from rpython.rlib.longlong2float import longlong2float return longlong2float(a)
def f(x): ll = float2longlong(x) return longlong2float(ll)