def ll_math_atan2(y, x): """wrapper for atan2 that deals directly with special cases before delegating to the platform libm for the remaining cases. This is necessary to get consistent behaviour across platforms. Windows, FreeBSD and alpha Tru64 are amongst platforms that don't always follow C99. """ if isnan(x): return NAN if not isfinite(y): if isnan(y): return NAN if isinf(x): if math_copysign(1.0, x) == 1.0: # atan2(+-inf, +inf) == +-pi/4 return math_copysign(0.25 * math.pi, y) else: # atan2(+-inf, -inf) == +-pi*3/4 return math_copysign(0.75 * math.pi, y) # atan2(+-inf, x) == +-pi/2 for finite x return math_copysign(0.5 * math.pi, y) if isinf(x) or y == 0.0: if math_copysign(1.0, x) == 1.0: # atan2(+-y, +inf) = atan2(+-0, +x) = +-0. return math_copysign(0.0, y) else: # atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. return math_copysign(math.pi, y) return math_atan2(y, x)
def test_math_sqrt(self): def f(x): try: return math.sqrt(x) except ValueError: return -INFINITY res = self.interp_operations(f, [0.0]) assert res == 0.0 self.check_operations_history(call_pure=1) # res = self.interp_operations(f, [25.0]) assert res == 5.0 self.check_operations_history(call_pure=1) # res = self.interp_operations(f, [-0.0]) assert str(res) == '-0.0' self.check_operations_history(call_pure=1) # res = self.interp_operations(f, [1000000.0]) assert res == 1000.0 self.check_operations_history(call_pure=1) # res = self.interp_operations(f, [-1.0]) assert res == -INFINITY self.check_operations_history(call_pure=0) # res = self.interp_operations(f, [INFINITY]) assert isinf(res) and not isnan(res) and res > 0.0 self.check_operations_history(call_pure=0) # res = self.interp_operations(f, [NAN]) assert isnan(res) and not isinf(res) self.check_operations_history(call_pure=0)
def division(ctx, nleft, nright): fleft = nleft.ToNumber() fright = nright.ToNumber() if isnan(fleft) or isnan(fright): return w_NAN if isinf(fleft) and isinf(fright): return w_NAN if isinf(fleft) and fright == 0: s = sign_of(fleft, fright) return w_signed_inf(s) if isinf(fright): return _w(0) if fleft == 0 and fright == 0: return w_NAN if fright == 0: s = sign_of(fleft, fright) return w_signed_inf(s) val = fleft / fright return W_FloatNumber(val)
def check_roundtrip(x, size): s = c_pack(x, size) assert s == pack(x, size) if not isnan(x): assert unpack(s) == x assert c_unpack(s) == x else: assert isnan(unpack(s)) assert isnan(c_unpack(s))
def ll_math_pow(x, y): # deal directly with IEEE specials, to cope with problems on various # platforms whose semantics don't exactly match C99 if isnan(y): if x == 1.0: return 1.0 # 1**Nan = 1 return y if not isfinite(x): if isnan(x): if y == 0.0: return 1.0 # NaN**0 = 1 return x else: # isinf(x) odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0 if y > 0.0: if odd_y: return x return math_fabs(x) elif y == 0.0: return 1.0 else: # y < 0.0 if odd_y: return math_copysign(0.0, x) return 0.0 if isinf(y): if math_fabs(x) == 1.0: return 1.0 elif y > 0.0 and math_fabs(x) > 1.0: return y elif y < 0.0 and math_fabs(x) < 1.0: if x == 0.0: raise ValueError("0**-inf: divide by zero") return -y # result is +inf else: return 0.0 _error_reset() r = math_pow(x, y) errno = rposix.get_errno() if not isfinite(r): if isnan(r): # a NaN result should arise only from (-ve)**(finite non-integer) errno = EDOM else: # isinf(r) # an infinite result here arises either from: # (A) (+/-0.)**negative (-> divide-by-zero) # (B) overflow of x**y with x and y finite if x == 0.0: errno = EDOM else: errno = ERANGE if errno: _likely_raise(errno, r) return r
def ll_math_pow(x, y): # deal directly with IEEE specials, to cope with problems on various # platforms whose semantics don't exactly match C99 if isnan(y): if x == 1.0: return 1.0 # 1**Nan = 1 return y if not isfinite(x): if isnan(x): if y == 0.0: return 1.0 # NaN**0 = 1 return x else: # isinf(x) odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0 if y > 0.0: if odd_y: return x return math_fabs(x) elif y == 0.0: return 1.0 else: # y < 0.0 if odd_y: return math_copysign(0.0, x) return 0.0 if isinf(y): if math_fabs(x) == 1.0: return 1.0 elif y > 0.0 and math_fabs(x) > 1.0: return y elif y < 0.0 and math_fabs(x) < 1.0: if x == 0.0: raise ValueError("0**-inf: divide by zero") return -y # result is +inf else: return 0.0 r = math_pow(x, y) errno = rposix.get_saved_errno() if not isfinite(r): if isnan(r): # a NaN result should arise only from (-ve)**(finite non-integer) errno = EDOM else: # isinf(r) # an infinite result here arises either from: # (A) (+/-0.)**negative (-> divide-by-zero) # (B) overflow of x**y with x and y finite if x == 0.0: errno = EDOM else: errno = ERANGE if errno: _likely_raise(errno, r) return r
def js_atan2(this, args): arg0 = get_arg(args, 0) arg1 = get_arg(args, 1) y = arg0.ToNumber() x = arg1.ToNumber() if isnan(x) or isnan(y): return NAN return math.atan2(y, x)
def check_roundtrip(x, size): s = c_pack(x, size) if not isnan(x): # pack uses copysign which is ambiguous for NAN assert s == pack(x, size) assert unpack(s) == x assert c_unpack(s) == x else: assert isnan(unpack(s)) assert isnan(c_unpack(s))
def js_pow(this, args): w_x = get_arg(args, 0) w_y = get_arg(args, 1) x = w_x.ToNumber() y = w_y.ToNumber() if isnan(y): return NAN if y == 0: return 1 if isnan(x): return NAN if abs(x) > 1 and y == INFINITY: return INFINITY if abs(x) > 1 and y == -INFINITY: return 0 if abs(x) == 1 and isinf(y): return NAN if abs(x) < 1 and y == INFINITY: return 0 if abs(x) < 1 and y == -INFINITY: return INFINITY if x == INFINITY and y > 0: return INFINITY if x == INFINITY and y < 0: return 0 if x == -INFINITY and y > 0 and isodd(y): return -INFINITY if x == -INFINITY and y > 0 and not isodd(y): return INFINITY if x == -INFINITY and y < 0 and isodd(y): return -0.0 if x == -INFINITY and y < 0 and not isodd(y): return 0 if eq_signed_zero(x, 0.0) and y > 0: return 0 if eq_signed_zero(x, 0.0) and y < 0: return INFINITY if eq_signed_zero(x, -0.0) and y > 0 and isodd(y): return -0.0 if eq_signed_zero(x, -0.0) and y > 0 and not isodd(y): return +0 if eq_signed_zero(x, -0.0) and y < 0 and isodd(y): return -INFINITY if eq_signed_zero(x, -0.0) and y < 0 and not isodd(y): return INFINITY if x < 0 and not isinstance(y, int): return NAN try: return math.pow(x, y) except OverflowError: return INFINITY
def __eq__(self, other): if (type(self) is SomeFloat and type(other) is SomeFloat and self.is_constant() and other.is_constant()): from rpython.rlib.rfloat import isnan, copysign # NaN unpleasantness. if isnan(self.const) and isnan(other.const): return True # 0.0 vs -0.0 unpleasantness. if not self.const and not other.const: return copysign(1., self.const) == copysign(1., other.const) # return super(SomeFloat, self).__eq__(other)
def rAlmostEqual(a, b, rel_err=2e-15, abs_err=5e-323, msg=''): """Fail if the two floating-point numbers are not almost equal. Determine whether floating-point values a and b are equal to within a (small) rounding error. The default values for rel_err and abs_err are chosen to be suitable for platforms where a float is represented by an IEEE 754 double. They allow an error of between 9 and 19 ulps. """ # special values testing if isnan(a): if isnan(b): return True,'' raise AssertionError(msg + '%r should be nan' % (b,)) if isinf(a): if a == b: return True,'' raise AssertionError(msg + 'finite result where infinity expected: '+ \ 'expected %r, got %r' % (a, b)) # if both a and b are zero, check whether they have the same sign # (in theory there are examples where it would be legitimate for a # and b to have opposite signs; in practice these hardly ever # occur). if not a and not b: # only check it if we are running on top of CPython >= 2.6 if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b): raise AssertionError( msg + \ 'zero has wrong sign: expected %r, got %r' % (a, b)) # if a-b overflows, or b is infinite, return False. Again, in # theory there are examples where a is within a few ulps of the # max representable float, and then b could legitimately be # infinite. In practice these examples are rare. try: absolute_error = abs(b-a) except OverflowError: pass else: # test passes if either the absolute error or the relative # error is sufficiently small. The defaults amount to an # error of between 9 ulps and 19 ulps on an IEEE-754 compliant # machine. if absolute_error <= max(abs_err, rel_err * abs(a)): return True,'' raise AssertionError(msg + \ '%r and %r are not sufficiently close, %g > %g' %\ (a, b, absolute_error, max(abs_err, rel_err*abs(a))))
def rAlmostEqual(a, b, rel_err=2e-15, abs_err=5e-323, msg=''): """Fail if the two floating-point numbers are not almost equal. Determine whether floating-point values a and b are equal to within a (small) rounding error. The default values for rel_err and abs_err are chosen to be suitable for platforms where a float is represented by an IEEE 754 double. They allow an error of between 9 and 19 ulps. """ # special values testing if isnan(a): if isnan(b): return True, '' raise AssertionError(msg + '%r should be nan' % (b, )) if isinf(a): if a == b: return True, '' raise AssertionError(msg + 'finite result where infinity expected: '+ \ 'expected %r, got %r' % (a, b)) # if both a and b are zero, check whether they have the same sign # (in theory there are examples where it would be legitimate for a # and b to have opposite signs; in practice these hardly ever # occur). if not a and not b: # only check it if we are running on top of CPython >= 2.6 if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b): raise AssertionError( msg + \ 'zero has wrong sign: expected %r, got %r' % (a, b)) # if a-b overflows, or b is infinite, return False. Again, in # theory there are examples where a is within a few ulps of the # max representable float, and then b could legitimately be # infinite. In practice these examples are rare. try: absolute_error = abs(b - a) except OverflowError: pass else: # test passes if either the absolute error or the relative # error is sufficiently small. The defaults amount to an # error of between 9 ulps and 19 ulps on an IEEE-754 compliant # machine. if absolute_error <= max(abs_err, rel_err * abs(a)): return True, '' raise AssertionError(msg + \ '%r and %r are not sufficiently close, %g > %g' %\ (a, b, absolute_error, max(abs_err, rel_err*abs(a))))
def interp_operations(self, f, args, **kwds): # get the JitCodes for the function f _get_jitcodes(self, self.CPUClass, f, args, **kwds) # try to run it with blackhole.py result1 = _run_with_blackhole(self, args) # try to run it with pyjitpl.py result2 = _run_with_pyjitpl(self, args) assert result1 == result2 or isnan(result1) and isnan(result2) # try to run it by running the code compiled just before result3 = _run_with_machine_code(self, args) assert result1 == result3 or result3 == NotImplemented or isnan(result1) and isnan(result3) # if longlong.supports_longlong and isinstance(result1, longlong.r_float_storage): result1 = longlong.getrealfloat(result1) return result1
def ll_math_fmod(x, y): # fmod(x, +/-Inf) returns x for finite x. if isinf(y) and isfinite(x): return x r = math_fmod(x, y) errno = rposix.get_saved_errno() if isnan(r): if isnan(x) or isnan(y): errno = 0 else: errno = EDOM if errno: _likely_raise(errno, r) return r
def ovfcheck_float_to_int(x): from rpython.rlib.rfloat import isnan if isnan(x): raise OverflowError if -2147483649.0 < x < 2147483648.0: return int(x) raise OverflowError
def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: pass elif TYPE is ootype.Bool: ilasm.opcode('ldc.i4', str(int(value))) elif TYPE is ootype.Char or TYPE is ootype.UniChar: ilasm.opcode('ldc.i4', ord(value)) elif TYPE is ootype.Float: if isinf(value): if value < 0.0: ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 ff)') else: ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f0 7f)') elif isnan(value): ilasm.opcode('ldc.r8', '(00 00 00 00 00 00 f8 ff)') else: ilasm.opcode('ldc.r8', repr(value)) elif isinstance(value, CDefinedIntSymbolic): ilasm.opcode('ldc.i4', DEFINED_INT_SYMBOLICS[value.expr]) elif TYPE in (ootype.Signed, ootype.Unsigned, rffi.SHORT): ilasm.opcode('ldc.i4', str(value)) elif TYPE in (ootype.SignedLongLong, ootype.UnsignedLongLong): ilasm.opcode('ldc.i8', str(value)) elif TYPE in (ootype.String, ootype.Unicode): if value._str is None: ilasm.opcode('ldnull') else: ilasm.opcode("ldstr", string_literal(value._str)) else: assert False, "Unexpected constant type"
def descr_repr(self, space): if self.realval == 0 and copysign(1., self.realval) == 1.: return space.newtext(repr_format(self.imagval) + 'j') sign = (copysign(1., self.imagval) == 1. or isnan(self.imagval)) and '+' or '' return space.newtext('(' + repr_format(self.realval) + sign + repr_format(self.imagval) + 'j)')
def test_nan_and_special_values(): from rpython.rlib.rfloat import isnan, isinf, isfinite, copysign inf = 1e300 * 1e300 assert isinf(inf) nan = inf/inf assert isnan(nan) for value, checker in [ (inf, lambda x: isinf(x) and x > 0.0), (-inf, lambda x: isinf(x) and x < 0.0), (nan, isnan), (42.0, isfinite), (0.0, lambda x: not x and copysign(1., x) == 1.), (-0.0, lambda x: not x and copysign(1., x) == -1.), ]: def f(): return value f1 = compile(f, []) res = f1() assert checker(res) l = [value] def g(x): return l[x] g2 = compile(g, [int]) res = g2(0) assert checker(res) l2 = [(-value, -value), (value, value)] def h(x): return l2[x][1] h3 = compile(h, [int]) res = h3(1) assert checker(res)
def format_float(self, w_value, char): space = self.space x = space.float_w(maybe_float(space, w_value)) if isnan(x): if char in 'EFG': r = 'NAN' else: r = 'nan' elif isinf(x): if x < 0: if char in 'EFG': r = '-INF' else: r = '-inf' else: if char in 'EFG': r = 'INF' else: r = 'inf' else: prec = self.prec if prec < 0: prec = 6 if char in 'fF' and x/1e25 > 1e25: char = chr(ord(char) + 1) # 'f' => 'g' flags = 0 if self.f_alt: flags |= DTSF_ALT r = formatd(x, char, prec, flags) self.std_wp_number(r)
def ovfcheck_float_to_longlong(x): from rpython.rlib.rfloat import isnan if isnan(x): raise OverflowError if -9223372036854776832.0 <= x < 9223372036854775296.0: return r_longlong(x) raise OverflowError
def var_dump(self, space, indent, recursion): if isinf(self.floatval): inf = "%s" % self.floatval return "%sfloat(%s)\n" % (indent, inf.upper()) if isnan(self.floatval): return "%sfloat(NAN)\n" % (indent, ) return "%sfloat(%s)\n" % (indent, self.str(space))
def ovfcheck_float_to_int(x): from rpython.rlib.rfloat import isnan if isnan(x): raise OverflowError if -9223372036854776832.0 <= x < 9223372036854775296.0: return int(x) raise OverflowError
def c_rect(r, phi): if not isfinite(r) or not isfinite(phi): # if r is +/-infinity and phi is finite but nonzero then # result is (+-INF +-INF i), but we need to compute cos(phi) # and sin(phi) to figure out the signs. if isinf(r) and isfinite(phi) and phi != 0.: if r > 0: real = copysign(INF, math.cos(phi)) imag = copysign(INF, math.sin(phi)) else: real = -copysign(INF, math.cos(phi)) imag = -copysign(INF, math.sin(phi)) z = (real, imag) else: z = rect_special_values[special_type(r)][special_type(phi)] # need to raise ValueError if r is a nonzero number and phi # is infinite if r != 0. and not isnan(r) and isinf(phi): raise ValueError("math domain error") return z real = r * math.cos(phi) imag = r * math.sin(phi) return real, imag
def round(space, number, w_ndigits): """round(number[, ndigits]) -> floating point number Round a number to a given precision in decimal digits (default 0 digits). This always returns a floating point number. Precision may be negative.""" # Algorithm copied directly from CPython # interpret 2nd argument as a Py_ssize_t; clip on overflow ndigits = space.getindex_w(w_ndigits, None) # nans, infinities and zeros round to themselves if number == 0 or isinf(number) or isnan(number): return space.newfloat(number) # Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x # always rounds to itself. For ndigits < NDIGITS_MIN, x always # rounds to +-0.0. if ndigits > NDIGITS_MAX: return space.newfloat(number) elif ndigits < NDIGITS_MIN: # return 0.0, but with sign of x return space.newfloat(0.0 * number) # finite x, and ndigits is not unreasonably large z = round_double(number, ndigits) if isinf(z): raise oefmt(space.w_OverflowError, "rounded value too large to represent") return space.newfloat(z)
def c_div(x, y): #x/y (r1, i1), (r2, i2) = x, y if r2 < 0: abs_r2 = -r2 else: abs_r2 = r2 if i2 < 0: abs_i2 = -i2 else: abs_i2 = i2 if abs_r2 >= abs_i2: if abs_r2 == 0.0: raise ZeroDivisionError else: ratio = i2 / r2 denom = r2 + i2 * ratio rr = (r1 + i1 * ratio) / denom ir = (i1 - r1 * ratio) / denom elif isnan(r2): rr = NAN ir = NAN else: ratio = r2 / i2 denom = r2 * ratio + i2 assert i2 != 0.0 rr = (r1 * ratio + i1) / denom ir = (i1 * ratio - r1) / denom return (rr, ir)
def descr_str(self, space): if self.realval == 0 and copysign(1., self.realval) == 1.: return space.wrap(str_format(self.imagval) + 'j') sign = (copysign(1., self.imagval) == 1. or isnan(self.imagval)) and '+' or '' return space.wrap('(' + str_format(self.realval) + sign + str_format(self.imagval) + 'j)')
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 c_cosh(x, y): if not isfinite(x) or not isfinite(y): if isinf(x) and isfinite(y) and y != 0.: if x > 0: real = copysign(INF, math.cos(y)) imag = copysign(INF, math.sin(y)) else: real = copysign(INF, math.cos(y)) imag = -copysign(INF, math.sin(y)) r = (real, imag) else: r = cosh_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/- infinity and x is not # a NaN if isinf(y) and not isnan(x): raise ValueError("math domain error") return r if fabs(x) > CM_LOG_LARGE_DOUBLE: # deal correctly with cases where cosh(x) overflows but # cosh(z) does not. x_minus_one = x - copysign(1., x) real = math.cos(y) * math.cosh(x_minus_one) * math.e imag = math.sin(y) * math.sinh(x_minus_one) * math.e else: real = math.cos(y) * math.cosh(x) imag = math.sin(y) * math.sinh(x) if isinf(real) or isinf(imag): raise OverflowError("math range error") return real, imag
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 test_primitive_log_n(): assert prim(primitives.FLOAT_LOG_N, [1.0]).value == 0.0 assert prim(primitives.FLOAT_LOG_N, [math.e]).value == 1.0 assert float_equals(prim(primitives.FLOAT_LOG_N, [10.0]), math.log(10)) assert isinf(prim(primitives.FLOAT_LOG_N, [0.0]).value) # works also for negative infinity assert isnan(prim(primitives.FLOAT_LOG_N, [-1.0]).value)
def last_index_of(this, args): search_string = get_arg(args, 0) position = get_arg(args, 1) s = this.to_string() search_str = search_string.to_string() num_pos = position.ToNumber() from rpython.rlib.rfloat import INFINITY, isnan, isinf if isnan(num_pos): pos = INFINITY elif isinf(num_pos): pos = num_pos else: pos = int(num_pos) length = len(s) start = min(max(pos, 0), length) search_len = len(search_str) if isinf(start): idx = s.rfind(search_str) return idx end = int(start + search_len) assert end >= 0 idx = s.rfind(search_str, 0, end) return idx
def c_sinh(x, y): # special treatment for sinh(+/-inf + iy) if y is finite and nonzero if not isfinite(x) or not isfinite(y): if isinf(x) and isfinite(y) and y != 0.: if x > 0: real = copysign(INF, math.cos(y)) imag = copysign(INF, math.sin(y)) else: real = -copysign(INF, math.cos(y)) imag = copysign(INF, math.sin(y)) r = (real, imag) else: r = sinh_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/- infinity and x is not # a NaN if isinf(y) and not isnan(x): raise ValueError("math domain error") return r if fabs(x) > CM_LOG_LARGE_DOUBLE: x_minus_one = x - copysign(1., x) real = math.cos(y) * math.sinh(x_minus_one) * math.e imag = math.sin(y) * math.cosh(x_minus_one) * math.e else: real = math.cos(y) * math.sinh(x) imag = math.sin(y) * math.cosh(x) if isinf(real) or isinf(imag): raise OverflowError("math range error") return real, imag
def round(space, number, w_ndigits): """round(number[, ndigits]) -> floating point number Round a number to a given precision in decimal digits (default 0 digits). This always returns a floating point number. Precision may be negative.""" # Algorithm copied directly from CPython # interpret 2nd argument as a Py_ssize_t; clip on overflow ndigits = space.getindex_w(w_ndigits, None) # nans, infinities and zeros round to themselves if number == 0 or isinf(number) or isnan(number): return space.wrap(number) # Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x # always rounds to itself. For ndigits < NDIGITS_MIN, x always # rounds to +-0.0. if ndigits > NDIGITS_MAX: return space.wrap(number) elif ndigits < NDIGITS_MIN: # return 0.0, but with sign of x return space.wrap(0.0 * number) # finite x, and ndigits is not unreasonably large z = round_double(number, ndigits) if isinf(z): raise oefmt(space.w_OverflowError, "rounded value too large to represent") return space.wrap(z)
def format_float(self, w_value, char): space = self.space x = space.float_w(maybe_float(space, w_value)) if isnan(x): if char in 'EFG': r = 'NAN' else: r = 'nan' elif isinf(x): if x < 0: if char in 'EFG': r = '-INF' else: r = '-inf' else: if char in 'EFG': r = 'INF' else: r = 'inf' else: prec = self.prec if prec < 0: prec = 6 if char in 'fF' and x / 1e25 > 1e25: char = chr(ord(char) + 1) # 'f' => 'g' flags = 0 if self.f_alt: flags |= DTSF_ALT r = formatd(x, char, prec, flags) self.std_wp_number(r)
def var_dump(self, space, indent, recursion): if isinf(self.floatval): inf = "%s" % self.floatval return "%sfloat(%s)\n" % (indent, inf.upper()) if isnan(self.floatval): return "%sfloat(NAN)\n" % (indent,) return "%sfloat(%s)\n" % (indent, self.str(space))
def ToInteger(self): if isnan(self._floatval_): return 0 if self._floatval_ == 0 or isinf(self._floatval_): return int(self._floatval_) return intmask(int(self._floatval_))
def isfinitejs(ctx, args, this): if len(args) < 1: return newbool(True) n = args[0].ToNumber(ctx) if isinf(n) or isnan(n): return newbool(False) else: return newbool(True)
def var_export(self, space, indent, recursion, suffix): if isinf(self.floatval): inf = "%s" % self.floatval return "%s" % inf.upper() if isnan(self.floatval): return "NAN" out = "%s%s%s" % (indent, self.str(space), suffix) return out
def js_cos(this, args): arg0 = get_arg(args, 0) x = arg0.ToNumber() if isnan(x) or isinf(x): return NAN return math.cos(x)
def js_abs(this, args): arg0 = get_arg(args, 0) x = arg0.ToNumber() if isnan(x): return NAN return abs(x)