def _apply_function_in_context(cls, f, args, context): """ Apply an MPFR function 'f' to the given arguments 'args', rounding to the given context. Returns a new Mpfr object with precision taken from the current context. """ rounding = context.rounding bf = mpfr.Mpfr_t.__new__(cls) mpfr.mpfr_init2(bf, context.precision) args = (bf,) + args + (rounding,) ternary = f(*args) with _temporary_exponent_bounds(context.emin, context.emax): ternary = mpfr.mpfr_check_range(bf, ternary, rounding) if context.subnormalize: # mpfr_subnormalize doesn't set underflow and # subnormal flags, so we do that ourselves. We choose # to set the underflow flag for *all* cases where the # 'after rounding' result is smaller than the smallest # normal number, even if that result is exact. # if bf is zero but ternary is nonzero, the underflow # flag will already have been set by mpfr_check_range; underflow = ( mpfr.mpfr_number_p(bf) and not mpfr.mpfr_zero_p(bf) and mpfr.mpfr_get_exp(bf) < context.precision - 1 + context.emin) if underflow: mpfr.mpfr_set_underflow() ternary = mpfr.mpfr_subnormalize(bf, ternary, rounding) if ternary: mpfr.mpfr_set_inexflag() return bf
def _quotient_exponent(x, y): """ Given two positive finite MPFR instances x and y, find the exponent of x / y; that is, the unique integer e such that 2**(e-1) <= x / y < 2**e. """ assert mpfr.mpfr_regular_p(x) assert mpfr.mpfr_regular_p(y) # Make copy of x with the exponent of y. x2 = mpfr.Mpfr_t() mpfr.mpfr_init2(x2, mpfr.mpfr_get_prec(x)) mpfr.mpfr_set(x2, x, mpfr.MPFR_RNDN) mpfr.mpfr_set_exp(x2, mpfr.mpfr_get_exp(y)) # Compare x2 and y, disregarding the sign. extra = mpfr.mpfr_cmpabs(x2, y) >= 0 return extra + mpfr.mpfr_get_exp(x) - mpfr.mpfr_get_exp(y)