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 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) or isnan(y): return NAN if isinf(y): 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 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 AbstractEC(ctx, x, y): """ Implements the Abstract Equality Comparison x == y trying to be fully to the spec """ if isinstance(x, W_IntNumber) and isinstance(y, W_IntNumber): return x.intval == y.intval if isinstance(x, W_FloatNumber) and isinstance(y, W_FloatNumber): if isnan(x.floatval) or isnan(y.floatval): return False return x.floatval == y.floatval type1 = x.type() type2 = y.type() if type1 == type2: if type1 == "undefined" or type1 == "null": return True if type1 == "number": n1 = x.ToNumber(ctx) n2 = y.ToNumber(ctx) if isnan(n1) or isnan(n2): return False if n1 == n2: return True return False elif type1 == "string": return x.ToString(ctx) == y.ToString(ctx) elif type1 == "boolean": return x.ToBoolean() == x.ToBoolean() # XXX rethink it here return x.ToString(ctx) == y.ToString(ctx) else: # step 14 if (type1 == "undefined" and type2 == "null") or (type1 == "null" and type2 == "undefined"): return True if type1 == "number" and type2 == "string": return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber(ctx))) if type1 == "string" and type2 == "number": return AbstractEC(ctx, W_FloatNumber(x.ToNumber(ctx)), y) if type1 == "boolean": return AbstractEC(ctx, W_FloatNumber(x.ToNumber(ctx)), y) if type2 == "boolean": return AbstractEC(ctx, x, W_FloatNumber(y.ToNumber(ctx))) if (type1 == "string" or type1 == "number") and type2 == "object": return AbstractEC(ctx, x, y.ToPrimitive(ctx)) if (type2 == "string" or type2 == "number") and type1 == "object": return AbstractEC(ctx, x.ToPrimitive(ctx), y) return False objtype = x.GetValue().type() if objtype == y.GetValue().type(): if objtype == "undefined" or objtype == "null": return True if isinstance(x, W_String) and isinstance(y, W_String): r = x.ToString(ctx) == y.ToString(ctx) else: r = x.ToNumber(ctx) == y.ToNumber(ctx) return r
def check_roundtrip(x): s = c_pack(x) assert s == pack(x) 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 __eq__(self, other): if (type(self) is SomeFloat and type(other) is SomeFloat and self.is_constant() and other.is_constant()): from pypy.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 rAssertAlmostEqual(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 raise AssertionError(msg + '%r should be nan' % (b,)) if isinf(a): if a == b: return 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 raise AssertionError(msg + '%r and %r are not sufficiently close' % (a, b))
def rAssertAlmostEqual(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 raise AssertionError(msg + '%r should be nan' % (b, )) if isinf(a): if a == b: return 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 raise AssertionError(msg + '%r and %r are not sufficiently close' % (a, b))
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 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 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 test_nan_and_special_values(): from pypy.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_int(x): from pypy.rlib.rfloat import isnan if isnan(x): raise OverflowError if -9223372036854776832.0 <= x < 9223372036854775296.0: return int(x) raise OverflowError
def str__Complex(space, w_complex): if w_complex.realval == 0 and copysign(1., w_complex.realval) == 1.: return space.wrap(str_format(w_complex.imagval) + 'j') sign = (copysign(1., w_complex.imagval) == 1. or isnan(w_complex.imagval)) and '+' or '' return space.wrap('(' + str_format(w_complex.realval) + sign + str_format(w_complex.imagval) + 'j)')
def ovfcheck_float_to_int(x): from pypy.rlib.rfloat import isnan if isnan(x): raise OverflowError if -2147483649.0 < x < 2147483648.0: return int(x) raise OverflowError
def round(space, number, w_ndigits=0): """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 OperationError( space.w_OverflowError, space.wrap("rounded value too large to represent")) return space.wrap(z)
def ll_math_fmod(x, y): # fmod(x, +/-Inf) returns x for finite x. if isinf(y) and isfinite(x): return x _error_reset() r = math_fmod(x, y) errno = rposix.get_errno() if isnan(r): if isnan(x) or isnan(y): errno = 0 else: errno = EDOM if errno: _likely_raise(errno, r) return r
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 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 round(space, number, w_ndigits=0): """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 OperationError(space.w_OverflowError, space.wrap("rounded value too large to represent")) return space.wrap(z)
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 interp_operations(self, f, args, **kwds): # get the JitCodes for the function f _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **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): if isinf(y): if isinf(x): raise ValueError("math domain error") return x # fmod(x, +/-Inf) returns x for finite x (or if x is a NaN). _error_reset() r = math_fmod(x, y) errno = rposix.get_errno() if isnan(r): if isnan(x) or isnan(y): errno = 0 else: errno = EDOM if errno: _likely_raise(errno, r) return r
def ll_math_fmod(x, y): if isinf(x) and not isnan(y): raise ValueError("math domain error") if y == 0: raise ValueError("math domain error") return math_fmod(x, y)
def interp_operations(self, f, args, **kwds): # get the JitCodes for the function f _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **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 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 _erfc(x): if rfloat.isnan(x): return x absx = abs(x) if absx < ERF_SERIES_CUTOFF: return 1. - _erf_series(x) else: cf = _erfc_contfrac(absx) return cf if x > 0. else 2. - cf
def compare(ctx, x, y): if isinstance(x, W_IntNumber) and isinstance(y, W_IntNumber): return x.intval > y.intval if isinstance(x, W_FloatNumber) and isinstance(y, W_FloatNumber): if isnan(x.floatval) or isnan(y.floatval): return -1 return x.floatval > y.floatval s1 = x.ToPrimitive(ctx, "Number") s2 = y.ToPrimitive(ctx, "Number") if not (isinstance(s1, W_String) and isinstance(s2, W_String)): s4 = s1.ToNumber(ctx) s5 = s2.ToNumber(ctx) if isnan(s4) or isnan(s5): return False return s4 > s5 else: s4 = s1.ToString(ctx) s5 = s2.ToString(ctx) return s4 > s5
def long__Float(space, w_floatobj): try: return W_LongObject.fromfloat(space, w_floatobj.floatval) except OverflowError: if isnan(w_floatobj.floatval): raise OperationError( space.w_ValueError, space.wrap("cannot convert float NaN to integer")) raise OperationError(space.w_OverflowError, space.wrap("cannot convert float infinity to long"))
def test_random(self): # construct a Python float from random integer, using struct for _ in xrange(100000): Q = random.randrange(2**64) x = struct.unpack('<d', struct.pack('<Q', Q))[0] # nans are tricky: we can't hope to reproduce the bit # pattern exactly, so check_float will fail for a random nan. if isnan(x): continue self.check_float(x)
def floorjs(ctx, args, this): if len(args) < 1: return W_FloatNumber(NAN) val = args[0].ToNumber(ctx) pos = math.floor(val) if isnan(val): pos = INFINITY return W_FloatNumber(pos)
def long__Float(space, w_floatobj): try: return W_LongObject.fromfloat(space, w_floatobj.floatval) except OverflowError: if isnan(w_floatobj.floatval): raise OperationError( space.w_ValueError, space.wrap("cannot convert float NaN to integer")) raise OperationError( space.w_OverflowError, space.wrap("cannot convert float infinity to long"))
def test_defined_constant_float(): value = rffi_platform.getdefineddouble('BLAH', '#define BLAH 1.0') assert value == 1.0 value = rffi_platform.getdefineddouble('BLAH', '#define BLAH 1.5') assert value == 1.5 value = rffi_platform.getdefineddouble('BLAH', '#define BLAH 1.0e20') assert value == 1.0e20 value = rffi_platform.getdefineddouble('BLAH', '#define BLAH 1.0e50000') assert value == float("inf") value = rffi_platform.getdefineddouble('BLAH', '#define BLAH (double)0/0') assert isnan(value)
def ll_math(x): _error_reset() r = c_func(x) # Error checking fun. Copied from CPython 2.6 errno = rposix.get_errno() if isnan(r): if isnan(x): errno = 0 else: errno = EDOM elif isinf(r): if isinf(x) or isnan(x): errno = 0 elif can_overflow: errno = ERANGE else: errno = EDOM if errno: _likely_raise(errno, r) return r
def format_float(x, code, precision): # like float2string, except that the ".0" is not necessary if isinf(x): if x > 0.0: return "inf" else: return "-inf" elif isnan(x): return "nan" else: return formatd(x, code, precision)
def name_singlefloat(value, db): value = float(value) if isinf(value): if value > 0: return '((float)Py_HUGE_VAL)' else: return '((float)-Py_HUGE_VAL)' elif isnan(value): # XXX are these expressions ok? return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))' else: return repr(value) + 'f'
def name_float(value, db): if isinf(value): if value > 0: return '(Py_HUGE_VAL)' else: return '(-Py_HUGE_VAL)' elif isnan(value): return '(Py_HUGE_VAL/Py_HUGE_VAL)' else: x = repr(value) assert not x.startswith('n') return x
def ll_math(x): _error_reset() r = c_func(x) # Error checking fun. Copied from CPython 2.6 errno = rposix.get_errno() if not isfinite(r): if isnan(r): if isnan(x): errno = 0 else: errno = EDOM else: # isinf(r) if not isfinite(x): errno = 0 elif can_overflow: errno = ERANGE else: errno = EDOM if errno: _likely_raise(errno, r) return r
def _gamma(x): if rfloat.isnan(x) or (rfloat.isinf(x) and x > 0.): return x if rfloat.isinf(x): raise ValueError("math domain error") if x == 0.: raise ValueError("math domain error") if x == math.floor(x): if x < 0.: raise ValueError("math domain error") if x < len(_gamma_integrals): return _gamma_integrals[int(x) - 1] absx = abs(x) if absx < 1e-20: r = 1. / x if rfloat.isinf(r): raise OverflowError("math range error") return r if absx > 200.: if x < 0.: return 0. / -_sinpi(x) else: raise OverflowError("math range error") y = absx + _lanczos_g_minus_half if absx > _lanczos_g_minus_half: q = y - absx z = q - _lanczos_g_minus_half else: q = y - _lanczos_g_minus_half z = q - absx z = z * _lanczos_g / y if x < 0.: r = -math.pi / _sinpi(absx) / absx * math.exp(y) / _lanczos_sum(absx) r -= z * r if absx < 140.: r /= math.pow(y, absx - .5) else: sqrtpow = math.pow(y, absx / 2. - .25) r /= sqrtpow r /= sqrtpow else: r = _lanczos_sum(absx) / math.exp(y) r += z * r if absx < 140.: r *= math.pow(y, absx - .5) else: sqrtpow = math.pow(y, absx / 2. - .25) r *= sqrtpow r *= sqrtpow if rfloat.isinf(r): raise OverflowError("math range error") return r
def _push_double_constant(self, value): if isnan(value): jvm.DOUBLENAN.load(self) elif isinf(value): if value > 0: jvm.DOUBLEPOSINF.load(self) else: jvm.DOUBLENEGINF.load(self) elif value == 0.0: self.emit(jvm.DCONST_0) elif value == 1.0: self.emit(jvm.DCONST_1) else: # Big hack to avoid exponential notation: self.emit(jvm.LDC2, "%22.22f" % value)
def c_phase(x, y): # Windows screws up atan2 for inf and nan, and alpha Tru64 5.1 doesn't # follow C99 for atan2(0., 0.). if isnan(x) or isnan(y): return NAN if isinf(y): if isinf(x): if copysign(1., x) == 1.: # atan2(+-inf, +inf) == +-pi/4 return copysign(0.25 * math.pi, y) else: # atan2(+-inf, -inf) == +-pi*3/4 return copysign(0.75 * math.pi, y) # atan2(+-inf, x) == +-pi/2 for finite x return copysign(0.5 * math.pi, y) if isinf(x) or y == 0.: if copysign(1., x) == 1.: # atan2(+-y, +inf) = atan2(+-0, +x) = +-0. return copysign(0., y) else: # atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. return copysign(math.pi, y) return math.atan2(y, x)
def fsum(space, w_iterable): """Sum an iterable of floats, trying to keep precision.""" w_iter = space.iter(w_iterable) inf_sum = special_sum = 0.0 partials = [] while True: try: w_value = space.next(w_iter) except OperationError, e: if not e.match(space, space.w_StopIteration): raise break v = _get_double(space, w_value) original = v added = 0 for y in partials: if abs(v) < abs(y): v, y = y, v hi = v + y yr = hi - v lo = y - yr if lo != 0.0: partials[added] = lo added += 1 v = hi del partials[added:] if v != 0.0: if rfloat.isinf(v) or rfloat.isnan(v): if (not rfloat.isinf(original) and not rfloat.isnan(original)): raise OperationError(space.w_OverflowError, space.wrap("intermediate overflow")) if rfloat.isinf(original): inf_sum += original special_sum += original del partials[:] else: partials.append(v)
def ll_math_hypot(x, y): # hypot(x, +/-Inf) returns Inf, even if x is a NaN. if isinf(x): return math_fabs(x) if isinf(y): return math_fabs(y) _error_reset() r = math_hypot(x, y) errno = rposix.get_errno() if not isfinite(r): if isnan(r): if isnan(x) or isnan(y): errno = 0 else: errno = EDOM else: # isinf(r) if isfinite(x) and isfinite(y): errno = ERANGE else: errno = 0 if errno: _likely_raise(errno, r) return r