def _round_float(space, w_float, w_ndigits=None): # Algorithm copied directly from CPython x = w_float.floatval if w_ndigits is None: # single-argument round: round to nearest integer rounded = rfloat.round_away(x) if math.fabs(x - rounded) == 0.5: # halfway case: round to even rounded = 2.0 * rfloat.round_away(x / 2.0) return newlong_from_float(space, rounded) # interpret 2nd argument as a Py_ssize_t; clip on overflow ndigits = space.getindex_w(w_ndigits, None) # nans and infinities round to themselves if not rfloat.isfinite(x): return space.newfloat(x) # 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(x) elif ndigits < NDIGITS_MIN: # return 0.0, but with sign of x return space.newfloat(0.0 * x) # finite x, and ndigits is not unreasonably large z = rfloat.round_double(x, ndigits, half_even=True) if math.isinf(z): raise oefmt(space.w_OverflowError, "overflow occurred during round") return space.newfloat(z)
def descr_trunc(self, space): try: value = ovfcheck_float_to_int(self.floatval) except OverflowError: return newlong_from_float(space, self.floatval) else: return space.newint(value)
def _round_float(space, w_float, w_ndigits=None): # Algorithm copied directly from CPython x = w_float.floatval if w_ndigits is None: # single-argument round: round to nearest integer rounded = rfloat.round_away(x) if math.fabs(x - rounded) == 0.5: # halfway case: round to even rounded = 2.0 * rfloat.round_away(x / 2.0) return newlong_from_float(space, rounded) # interpret 2nd argument as a Py_ssize_t; clip on overflow ndigits = space.getindex_w(w_ndigits, None) # nans and infinities round to themselves if not rfloat.isfinite(x): return space.wrap(x) # 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(x) elif ndigits < NDIGITS_MIN: # return 0.0, but with sign of x return space.wrap(0.0 * x) # finite x, and ndigits is not unreasonably large z = rfloat.round_double(x, ndigits, half_even=True) if rfloat.isinf(z): raise oefmt(space.w_OverflowError, "overflow occurred during round") return space.wrap(z)
def descr_trunc(self, space): whole = math.modf(self.floatval)[1] try: value = ovfcheck_float_to_int(whole) except OverflowError: return newlong_from_float(space, whole) else: return space.newint(value)
def newint_from_float(space, floatval): """This is also used from module/math/interp_math.py""" try: value = ovfcheck_float_to_int(floatval) except OverflowError: return newlong_from_float(space, floatval) else: return space.newint(value)
def int(self, space): if (type(self) is not W_FloatObject and space.is_overloaded(self, space.w_float, '__int__')): return W_Root.int(self, space) try: value = ovfcheck_float_to_int(self.floatval) except OverflowError: return newlong_from_float(space, self.floatval) else: return space.newint(value)
def ceil(space, w_x): """ceil(x) Return the ceiling of x as an int. This is the smallest integral value >= x. """ from pypy.objspace.std.longobject import newlong_from_float w_descr = space.lookup(w_x, '__ceil__') if w_descr is not None: return space.get_and_call_function(w_descr, w_x) return newlong_from_float(space, math1_w(space, math.ceil, w_x))
def floor(space, w_x): """floor(x) Return the floor of x as an int. This is the largest integral value <= x. """ from pypy.objspace.std.longobject import newlong_from_float w_descr = space.lookup(w_x, '__floor__') if w_descr is not None: return space.get_and_call_function(w_descr, w_x) x = _get_double(space, w_x) return newlong_from_float(space, math.floor(x))