def descr_eq(self, space, w_other): if not isinstance(w_other, W_AbstractTupleObject): return space.w_NotImplemented if not isinstance(w_other, cls): if typelen != w_other.length(): return space.w_False for i in iter_n: myval = getattr(self, 'value%s' % i) otherval = w_other.getitem(space, i) myval = wraps[i](self.space, myval) if not space.eq_w(myval, otherval): return space.w_False return space.w_True for i in iter_n: myval = getattr(self, 'value%s' % i) otherval = getattr(w_other, 'value%s' % i) if typetuple[i] == object: if not self.space.eq_w(myval, otherval): return space.w_False else: if myval != otherval: if typetuple[i] == float: # issue with NaNs, which should be equal here if (float2longlong(myval) == float2longlong( otherval)): continue return space.w_False return space.w_True
def descr_eq(self, space, w_other): if not isinstance(w_other, W_AbstractTupleObject): return space.w_NotImplemented if not isinstance(w_other, cls): if typelen != w_other.length(): return space.w_False for i in iter_n: myval = getattr(self, 'value%s' % i) otherval = w_other.getitem(space, i) if typetuple[i] != object: myval = space.wrap(myval) if not space.eq_w(myval, otherval): return space.w_False return space.w_True for i in iter_n: myval = getattr(self, 'value%s' % i) otherval = getattr(w_other, 'value%s' % i) if typetuple[i] == object: if not self.space.eq_w(myval, otherval): return space.w_False else: if myval != otherval: if typetuple[i] == float: # issue with NaNs, which should be equal here if (float2longlong(myval) == float2longlong(otherval)): continue return space.w_False return space.w_True
def is_w(self, space, w_other): from rpython.rlib.longlong2float import float2longlong if not isinstance(w_other, W_FloatObject): return False if self.user_overridden_class or w_other.user_overridden_class: return self is w_other one = float2longlong(space.float_w(self)) two = float2longlong(space.float_w(w_other)) return one == two
def immutable_unique_id(self, space): if self.user_overridden_class: return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_COMPLEX as tag real = space.float_w(space.getattr(self, space.wrap("real"))) imag = space.float_w(space.getattr(self, space.wrap("imag"))) real_b = rbigint.fromrarith_int(float2longlong(real)) imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag))) val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag)) return space.newlong_from_rbigint(val)
def eqv(self, other): from rpython.rlib.longlong2float import float2longlong import math if not isinstance(other, W_Flonum): return False v1 = self.value v2 = other.value ll1 = float2longlong(v1) ll2 = float2longlong(v2) # Assumes that all non-NaN values are canonical return ll1 == ll2 or (math.isnan(v1) and math.isnan(v2))
def equal(self, other): from rpython.rlib.longlong2float import float2longlong import math if not isinstance(other, W_Flonum): return False v1 = self.value v2 = other.value ll1 = float2longlong(v1) ll2 = float2longlong(v2) # Assumes that all non-NaN values are canonical return ll1 == ll2 or (math.isnan(v1) and math.isnan(v2))
def is_w(self, space, w_other): from rpython.rlib.longlong2float import float2longlong if not isinstance(w_other, W_ComplexObject): return False if self.user_overridden_class or w_other.user_overridden_class: return self is w_other real1 = space.float_w(space.getattr(self, space.wrap("real"))) real2 = space.float_w(space.getattr(w_other, space.wrap("real"))) imag1 = space.float_w(space.getattr(self, space.wrap("imag"))) imag2 = space.float_w(space.getattr(w_other, space.wrap("imag"))) real1 = float2longlong(real1) real2 = float2longlong(real2) imag1 = float2longlong(imag1) imag2 = float2longlong(imag2) return real1 == real2 and imag1 == imag2
def is_w(self, space, w_other): from rpython.rlib.longlong2float import float2longlong if not isinstance(w_other, W_ComplexObject): return False if self.user_overridden_class or w_other.user_overridden_class: return self is w_other real1 = space.float_w(space.getattr(self, space.newtext("real"))) real2 = space.float_w(space.getattr(w_other, space.newtext("real"))) imag1 = space.float_w(space.getattr(self, space.newtext("imag"))) imag2 = space.float_w(space.getattr(w_other, space.newtext("imag"))) real1 = float2longlong(real1) real2 = float2longlong(real2) imag1 = float2longlong(imag1) imag2 = float2longlong(imag2) return real1 == real2 and imag1 == imag2
def float_pack80(x, size): """Convert a Python float or longfloat x into two 64-bit unsigned integers with 80 bit extended representation.""" x = float(x) # longfloat not really supported if size == 10 or size == 12 or size == 16: MIN_EXP = -16381 MAX_EXP = 16384 MANT_DIG = 64 BITS = 80 else: raise ValueError("invalid size value") sign = rfloat.copysign(1.0, x) < 0.0 if rfloat.isinf(x): mant = r_ulonglong(0) exp = MAX_EXP - MIN_EXP + 2 elif rfloat.isnan(x): # rfloat.isnan(x): asint = cast(ULONGLONG, float2longlong(x)) mant = asint & ((r_ulonglong(1) << 51) - 1) if mant == 0: mant = r_ulonglong(1) << (MANT_DIG - 1) - 1 sign = asint < 0 exp = MAX_EXP - MIN_EXP + 2 elif x == 0.0: mant = r_ulonglong(0) exp = 0 else: m, e = math.frexp(abs(x)) # abs(x) == m * 2**e exp = e - (MIN_EXP - 1) if exp > 0: # Normal case. Avoid uint64 overflow by using MANT_DIG-1 mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG - 1)) else: # Subnormal case. if exp + MANT_DIG - 1 >= 0: mant = round_to_nearest(m * (r_ulonglong(1) << exp + MANT_DIG - 1)) else: mant = r_ulonglong(0) exp = 0 # Special case: rounding produced a MANT_DIG-bit mantissa. if mant == r_ulonglong(1) << MANT_DIG - 1: mant = r_ulonglong(0) exp += 1 # Raise on overflow (in some circumstances, may want to return # infinity instead). if exp >= MAX_EXP - MIN_EXP + 2: raise OverflowError("float too large to pack in this format") mant = mant << 1 # check constraints if not objectmodel.we_are_translated(): assert 0 <= mant <= (1 << MANT_DIG) - 1 assert 0 <= exp <= MAX_EXP - MIN_EXP + 2 assert 0 <= sign <= 1 exp = r_ulonglong(exp) sign = r_ulonglong(sign) return (mant, (sign << BITS - MANT_DIG - 1) | exp)
def test_consistency_float2longlong_ll2ctypes(floatval): #return struct.unpack('@q', struct.pack('@d', floatval))[0] with lltype.scoped_alloc(DOUBLE_ARRAY_PTR.TO, 1) as d_array: ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array) d_array[0] = floatval llval = ll_array[0] assert llval == float2longlong(floatval)
def wrap(self, val): assert isinstance(val, float) bits = float2longlong(val) if is_int32_from_longlong_nan(bits): bits = decode_int32_from_longlong_nan(bits) return W_Fixnum(bits) return W_Flonum(val)
def write_location(self, obj, value): if isinstance(value, Double): val = float2longlong(value.get_embedded_double()) obj._primFields[self._ext_idx] = val self._mark_as_set(obj) else: self._unset_or_generalize(obj, value)
def pack_double(pack_obj, fmtdesc, count): for _ in xrange(count): value = pack_obj.space.float_w(pack_obj.pop_arg()) value = longlong2float.float2longlong(value) for i in range(fmtdesc.size): pack_obj.result.append(chr(value & 0xff)) value >>= 8
def pack_double(fmtiter): doubleval = fmtiter.accept_float_arg() if std.pack_fastpath(rffi.DOUBLE)(fmtiter, doubleval): return # slow path value = longlong2float.float2longlong(doubleval) pack_float_to_buffer(fmtiter.wbuf, fmtiter.pos, value, 8, fmtiter.bigendian) fmtiter.advance(8)
def immutable_unique_id(self, space): if self.user_overridden_class: return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_FLOAT as tag val = float2longlong(space.float_w(self)) b = rbigint.fromrarith_int(val) b = b.lshift(3).int_or_(tag) return space.newlong_from_rbigint(b)
def unique_value(self, val): if isinstance(val, ConstFloat): if val.getfloat() == 0.0: return 0 return float2longlong(val.getfloat()) elif isinstance(val, ConstInt): return rffi.cast(lltype.Signed, val.getint()) else: assert isinstance(val, ConstPtr) return rffi.cast(lltype.Signed, val.getref_base())
def write_location(self, obj, value): assert value is not None assert isinstance(value, AbstractObject) if isinstance(value, Double): setattr(obj, "_primField" + str(field_idx), float2longlong(value.get_embedded_double())) self._mark_as_set(obj) else: self._unset_or_generalize(obj, value)
def unique_value(self, val): if val.type == FLOAT: if val.getfloat() == 0.0: return 0 return float2longlong(val.getfloat()) elif val.type == INT: return rffi.cast(lltype.Signed, val.getint()) else: assert val.type == REF return rffi.cast(lltype.Signed, val.getref_base())
def unwrap_string(self, space): word = longlong2float.float2longlong(self.getvalue()) return "".join([chr(word & 0x000000ff), chr((word >> 8) & 0x000000ff), chr((word >> 16) & 0x000000ff), chr((word >> 24) & 0x000000ff), chr((word >> 32) & 0x000000ff), chr((word >> 40) & 0x000000ff), chr((word >> 48) & 0x000000ff), chr((word >> 56) & 0x000000ff)])
def pack_double(fmtiter): doubleval = fmtiter.accept_float_arg() value = longlong2float.float2longlong(doubleval) if fmtiter.bigendian: for i in range_8_unroll: x = (value >> (8 * i)) & 0xff fmtiter.result.append(chr(x)) else: for i in range_8_unroll: fmtiter.result.append(chr(value & 0xff)) value >>= 8
def pack_double(fmtiter): doubleval = fmtiter.accept_float_arg() value = longlong2float.float2longlong(doubleval) if fmtiter.bigendian: for i in range_8_unroll: x = (value >> (8*i)) & 0xff fmtiter.result.append(chr(x)) else: for i in range_8_unroll: fmtiter.result.append(chr(value & 0xff)) value >>= 8
def unwrap_string(self, space): word = longlong2float.float2longlong(self.getvalue()) return "".join([ chr(word & 0x000000ff), chr((word >> 8) & 0x000000ff), chr((word >> 16) & 0x000000ff), chr((word >> 24) & 0x000000ff), chr((word >> 32) & 0x000000ff), chr((word >> 40) & 0x000000ff), chr((word >> 48) & 0x000000ff), chr((word >> 56) & 0x000000ff) ])
def _sqlite3VdbeSerialPut_with_length(self, buf, serial_type, length): flags = self.get_flags() if flags & CConfig.MEM_Null: return 0 if flags & (CConfig.MEM_Int | CConfig.MEM_Real): if flags & CConfig.MEM_Int: i = self.get_u_i() else: i = longlong2float.float2longlong(self.get_u_r()) _write_int_to_buf(buf, i, length) return length else: rffi.c_memcpy(rffi.cast(rffi.VOIDP, buf), rffi.cast(rffi.VOIDP, self.get_z()), length) return length
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 real_floating_point_bytes(n, _size, big_endian): if isinstance(n, values.W_Flonum): v = n.value elif isinstance(n, values.W_Fixnum): v = float(n.value) elif isinstance(n, values.W_Bignum): v = rbigint.tofloat(n.value) else: raise SchemeException("real->floating-point-bytes: expected real") size = _size.value if size != 4 and size != 8: raise SchemeException("real->floating-point-bytes: size not 4 or 8") intval = longlong2float.float2longlong(v) if big_endian is not values.w_false: intval = rarithmetic.byteswap(intval) chars = [chr((intval >> (i * 8)) % 256) for i in range(size)] return values.W_Bytes.from_charlist(chars)
def op_convert_float_bytes_to_longlong(a): from rpython.rlib.longlong2float import float2longlong return float2longlong(a)
def test_float2longlong(): assert float2longlong(0.0) == r_longlong(0)
def _box(self, val): space = self.space if self.typ is space.IntObjectCls: return space.newint(float2longlong(val)) else: return space.newfloat(val)
def op_convert_float_bytes_to_longlong(self, f): from rpython.rlib import longlong2float return longlong2float.float2longlong(f)
def FloatImmedLoc(floatstorage): from rpython.rlib.longlong2float import float2longlong value = intmask(float2longlong(floatstorage)) return ImmedLoc(value, True)
def float_pack(x, size): """Convert a Python float x into a 64-bit unsigned integer with the same byte representation.""" 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") sign = rfloat.copysign(1.0, x) < 0.0 if rfloat.isinf(x): mant = r_ulonglong(0) exp = MAX_EXP - MIN_EXP + 2 elif rfloat.isnan(x): asint = cast(ULONGLONG, float2longlong(x)) sign = asint >> 63 # shift off lower bits, perhaps losing data mant = asint & ((r_ulonglong(1) << 52) - 1) if MANT_DIG < 53: mant = mant >> (53 - MANT_DIG) if mant == 0: mant = r_ulonglong(1) << (MANT_DIG - 1) - 1 exp = MAX_EXP - MIN_EXP + 2 elif x == 0.0: mant = r_ulonglong(0) exp = 0 else: m, e = math.frexp(abs(x)) # abs(x) == m * 2**e exp = e - (MIN_EXP - 1) if exp > 0: # Normal case. mant = round_to_nearest(m * (r_ulonglong(1) << MANT_DIG)) mant -= r_ulonglong(1) << MANT_DIG - 1 else: # Subnormal case. if exp + MANT_DIG - 1 >= 0: mant = round_to_nearest(m * (r_ulonglong(1) << exp + MANT_DIG - 1)) else: mant = r_ulonglong(0) exp = 0 # Special case: rounding produced a MANT_DIG-bit mantissa. if not objectmodel.we_are_translated(): assert 0 <= mant <= 1 << MANT_DIG - 1 if mant == r_ulonglong(1) << MANT_DIG - 1: mant = r_ulonglong(0) exp += 1 # Raise on overflow (in some circumstances, may want to return # infinity instead). if exp >= MAX_EXP - MIN_EXP + 2: raise OverflowError("float too large to pack in this format") # check constraints if not objectmodel.we_are_translated(): assert 0 <= mant <= (1 << MANT_DIG) - 1 assert 0 <= exp <= MAX_EXP - MIN_EXP + 2 assert 0 <= sign <= 1 exp = r_ulonglong(exp) sign = r_ulonglong(sign) return ((sign << BITS - 1) | (exp << MANT_DIG - 1)) | mant
def BFL(value, short=False): if short: return struct.pack('f', value) return struct.pack('>q', float2longlong(value))
def f(x): ll = float2longlong(x) return longlong2float(ll)
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(self, space, w_obj): return space.newint( intmask( longlong2float.float2longlong( w_obj.unboxed_storage[self.pos])))
def read(self, space, w_obj): return space.newint(intmask(longlong2float.float2longlong( w_obj.unboxed_storage[self.pos])))
def _run(self, atypes, rtype, avalues, rvalue, expected_call_release_gil=1, supports_floats=True, supports_longlong=False, supports_singlefloats=False): cif_description = get_description(atypes, rtype) def verify(*args): for a, exp_a in zip(args, avalues): if (lltype.typeOf(exp_a) == rffi.ULONG and lltype.typeOf(a) == lltype.Signed): a = rffi.cast(rffi.ULONG, a) assert a == exp_a return rvalue FUNC = lltype.FuncType([lltype.typeOf(avalue) for avalue in avalues], lltype.typeOf(rvalue)) func = lltype.functionptr(FUNC, 'verify', _callable=verify) func_addr = rffi.cast(rffi.VOIDP, func) for i in range(len(avalues)): cif_description.exchange_args[i] = (i+1) * 16 cif_description.exchange_result = (len(avalues)+1) * 16 unroll_avalues = unrolling_iterable(avalues) def fake_call_impl_any(cif_description, func_addr, exchange_buffer): ofs = 16 for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) data = rffi.ptradd(exchange_buffer, ofs) got = rffi.cast(lltype.Ptr(TYPE), data)[0] if lltype.typeOf(avalue) is lltype.SingleFloat: got = float(got) avalue = float(avalue) elif (lltype.typeOf(avalue) is rffi.SIGNEDCHAR or lltype.typeOf(avalue) is rffi.UCHAR): got = intmask(got) avalue = intmask(avalue) assert got == avalue ofs += 16 if rvalue is not None: write_rvalue = rvalue else: write_rvalue = 12923 # ignored TYPE = rffi.CArray(lltype.typeOf(write_rvalue)) data = rffi.ptradd(exchange_buffer, ofs) rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue def f(i): exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16, flavor='raw') targetptr = rffi.ptradd(exbuf, 16) for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) if i >= 9: # a guard that can fail pass rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue targetptr = rffi.ptradd(targetptr, 16) jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 else: TYPE = rffi.CArray(lltype.typeOf(rvalue)) res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0] lltype.free(exbuf, flavor='raw') if lltype.typeOf(res) is lltype.SingleFloat: res = float(res) return res def matching_result(res, rvalue): if rvalue is None: return res == 654321 if isinstance(rvalue, r_singlefloat): rvalue = float(rvalue) if lltype.typeOf(rvalue) is rffi.ULONG: res = intmask(res) rvalue = intmask(rvalue) return res == rvalue with FakeFFI(fake_call_impl_any): res = f(-42) assert matching_result(res, rvalue) res = self.interp_operations(f, [-42], supports_floats = supports_floats, supports_longlong = supports_longlong, supports_singlefloats = supports_singlefloats) if is_longlong(FUNC.RESULT): # longlongs are returned as floats, but that's just # an inconvenience of interp_operations(). Normally both # longlong and floats are passed around as longlongs. res = float2longlong(res) assert matching_result(res, rvalue) self.check_operations_history(call_may_force=0, call_release_gil=expected_call_release_gil) ################################################## driver = jit.JitDriver(reds=['i'], greens=[]) def main(): i = 0 while 1: driver.jit_merge_point(i=i) res = f(i) i += 1 if i == 12: return res self.meta_interp(main, [])