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 same_numeric_class(self, other): if isinstance(other, values.W_Fixnum): return self, values.W_Flonum(float(other.value)) if isinstance(other, values.W_Flonum): return self, other if isinstance(other, values.W_Bignum): return self, values.W_Flonum(other.value.tofloat()) if isinstance(other, values.W_Rational): return self, other.arith_exact_inexact() return other.same_numeric_class_reversed(self)
def random(args): if not args: # random flonum return values.W_Flonum(rng.random()) a1 = args[0] if isinstance(a1, values.W_Fixnum): upper = a1.value return values.W_Fixnum(int(rng.random() * upper)) if isinstance(a1, values.W_PseudoRandomGenerator): return values.W_Flonum(rng.random()) raise SchemeException("random: invalid arguments")
def arith_remainder_same(self, other): assert isinstance(other, values.W_Flonum) if other.value == 0.0: raise Exception("zero_divisor") x, y = self.value, other.value res = math.fmod(x, y) return values.W_Flonum(res)
def arith_quotient_same(self, other): assert isinstance(other, values.W_Flonum) v1 = self.value v2 = other.value if math.floor(v1) != v1 or math.floor(v2) != v2: raise SchemeException("quotient: expected integer") return values.W_Flonum(v1 / v2)
def read_number_or_id(f, init): sofar = StringBuilder(64) sofar.append(init) while True: c = f.peek() if c == "": break if idchar(c): v = f.read(1) assert v == c sofar.append(v) else: break got = sofar.build() try: val = string_to_int(got) return values.W_Fixnum.make_or_interned(val) except ParseStringOverflowError: val = rbigint.fromdecimalstr(got) return values.W_Bignum(val) except ParseStringError: try: return values.W_Flonum(float(got)) except: return values.W_Symbol.make(got)
def arith_exact_inexact(self): num = self._numerator den = self._denominator try: return values.W_Flonum(num.truediv(den)) except OverflowError: if num.sign == den.sign: return values.W_Flonum.INF return values.W_Flonum.NEGINF
def arith_mod_same(self, other): assert isinstance(other, values.W_Flonum) if other.value == 0.0: raise Exception("zero_divisor") x, y = self.value, other.value res = math.fmod(x, y) # ensure the remainder has the same sign as the denominator if (y < 0.0) != (res < 0.0): res += y return values.W_Flonum(res)
def _str2num(s, radix): from rpython.rlib import rarithmetic, rfloat, rbigint from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError from rpython.rlib.rsre import rsre_re as re import math try: if ((radix == 16 and re.match("^[0-9A-Fa-f]+$", s)) or (radix == 8 and re.match("^[0-7]+$", s)) or (radix == 10 and re.match("^[0-9]+$", s))): try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=radix)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s, base=radix)) if re.match("[+-]?([\d]+)?.?\d+[tT]\d", s): # it's an extflonum return values.W_ExtFlonum(s) if re.match("[+-]?([\d]+)?.?\d+[sf]\d", s): if "f" in s: f_parts = s.split("f") elif "s" in s: f_parts = s.split("s") else: raise ParseStringError("invalid floating point number : %s" % s) if len(f_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: numb = float(f_parts[0]) prec = int(f_parts[1]) p = math.pow(10, prec) except ValueError, e: return values.w_false return values.W_Flonum.make(numb * p, True) if re.match("[+-]?([\d]+)?.?\d+e\d", s): e_parts = s.split("e") if len(e_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: num = float(e_parts[0]) exp = int(e_parts[1]) p = math.pow(10, exp) except ValueError, e: return values.w_false return values.W_Flonum(num * p)
def arith_sqrt(self): n = abs(self.value) root, rem = fixnum_sqrt(n) if rem == 0: result = values.W_Fixnum(root) else: result = values.W_Flonum(math.sqrt(float(n))) if self.value < 0: return imaginary(result) return 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 str2num(w_s): from rpython.rlib import rarithmetic, rfloat, rbigint from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError s = w_s.as_str_utf8() try: if "." in s: return values.W_Flonum(rfloat.string_to_float(s)) else: try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=10)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s)) except ParseStringError as e: return values.w_false
def arith_round(self): from rpython.rlib.rfloat import round_double return values.W_Flonum(round_double(self.value, 0, half_even=True))
if len(e_parts) > 2: raise ParseStringError("invalid floating point number : %s" % s) try: num = float(e_parts[0]) exp = int(e_parts[1]) p = math.pow(10, exp) except ValueError, e: return values.w_false return values.W_Flonum(num*p) if "." in s or re.match("[+-]?([\d]+)(\.[\d]+)?e[+-][\d]+$", s): if not radix == 10: # FIXME raise SchemeException("string->number : floats with base different than 10 are not supported yet : given number : %s - radix : %s" % (w_s.tostring(), str(radix))) return values.W_Flonum(rfloat.string_to_float(s)) else: try: return values.W_Fixnum(rarithmetic.string_to_int(s, base=radix)) except ParseStringOverflowError: return values.W_Bignum(rbigint.rbigint.fromstr(s, base=radix)) except ParseStringError as e: return values.w_false @expose("number->string", [values.W_Number, default(values.W_Fixnum, values.W_Fixnum.make(10))]) def num2str(a, radix): from rpython.rlib.rbigint import BASE8, BASE16 if radix.value == 10: return W_String.fromascii(a.tostring()) else:
def arith_exact_inexact(self): return values.W_Flonum(self._numerator.truediv(self._denominator))
def arith_pow_same(self, other): assert isinstance(other, values.W_Rational) # XXX Not precise v = self._numerator.tofloat() / self._denominator.tofloat() p = other._numerator.tofloat() / other._denominator.tofloat() return values.W_Flonum(math.pow(v, p))
def unsafe_flmax(a, b): return values.W_Flonum(max(a.value, b.value))
def unsafe_fltimes(a, b): return values.W_Flonum(a.value * b.value)
def unsafe_flplus(a, b): return values.W_Flonum(a.value + b.value)
def unsafe_fxfl(a): return values.W_Flonum(float(a.value))
def fxfl(a): return values.W_Flonum(float(a.value))
def arith_ceiling(self): from rpython.rlib.rfloat import isinf if isinf(self.value): return self return values.W_Flonum(float(math.ceil(self.value)))
def to_fl(n): if isinstance(n, values.W_Fixnum): return values.W_Flonum(float(n.value)) if isinstance(n, values.W_Bignum): return values.W_Flonum(rbigint.tofloat(n.value)) raise SchemeException("->fl: expected an exact-integer")
def arith_float_fractional_part(self): try: val = rarithmetic.ovfcheck_float_to_int(self.value) except OverflowError: val = rbigint.fromfloat(self.value).tofloat() return values.W_Flonum(float(self.value - val))
def unsafe_flminus(a, b): return values.W_Flonum(a.value - b.value)
def arith_exp(self): if self.value == 0: return values.W_Fixnum(1) return values.W_Flonum(math.exp(self.value))
def unsafe_fldiv(a, b): return values.W_Flonum(a.value / b.value)
def arith_gcd_same(self, other): assert isinstance(other, values.W_Flonum) if not other.value: return self res = math.fmod(self.value, other.value) return other.arith_gcd(values.W_Flonum(res))
def unsafe_flabs(a): return values.W_Flonum(abs(a.value))
def arith_exact_inexact(self): return values.W_Flonum(self.value.tofloat())