/* Assumes that the exponent range has already been extended and if y is an integer, then the result is not exact in unbounded exponent range. */ int mpfr_pow_general (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode, int y_is_integer, mpfr_save_expo_t *expo) { mpfr_t t, u, k, absx; int neg_result = 0; int k_non_zero = 0; int check_exact_case = 0; int inexact; /* Declaration of the size variable */ mpfr_prec_t Nz = MPFR_PREC(z); /* target precision */ mpfr_prec_t Nt; /* working precision */ mpfr_exp_t err; /* error */ MPFR_ZIV_DECL (ziv_loop); MPFR_LOG_FUNC (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode), ("z[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (z), mpfr_log_prec, z, inexact)); /* We put the absolute value of x in absx, pointing to the significand of x to avoid allocating memory for the significand of absx. */ MPFR_ALIAS(absx, x, /*sign=*/ 1, /*EXP=*/ MPFR_EXP(x)); /* We will compute the absolute value of the result. So, let's invert the rounding mode if the result is negative. */ if (MPFR_IS_NEG (x) && is_odd (y)) { neg_result = 1; rnd_mode = MPFR_INVERT_RND (rnd_mode); } /* compute the precision of intermediary variable */ /* the optimal number of bits : see algorithms.tex */ Nt = Nz + 5 + MPFR_INT_CEIL_LOG2 (Nz); /* initialise of intermediary variable */ mpfr_init2 (t, Nt); MPFR_ZIV_INIT (ziv_loop, Nt); for (;;) { MPFR_BLOCK_DECL (flags1); /* compute exp(y*ln|x|), using MPFR_RNDU to get an upper bound, so that we can detect underflows. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU); /* ln|x| */ mpfr_mul (t, y, t, MPFR_RNDU); /* y*ln|x| */ if (k_non_zero) { MPFR_LOG_MSG (("subtract k * ln(2)\n", 0)); mpfr_const_log2 (u, MPFR_RNDD); mpfr_mul (u, u, k, MPFR_RNDD); /* Error on u = k * log(2): < k * 2^(-Nt) < 1. */ mpfr_sub (t, t, u, MPFR_RNDU); MPFR_LOG_MSG (("t = y * ln|x| - k * ln(2)\n", 0)); MPFR_LOG_VAR (t); } /* estimate of the error -- see pow function in algorithms.tex. The error on t is at most 1/2 + 3*2^(EXP(t)+1) ulps, which is <= 2^(EXP(t)+3) for EXP(t) >= -1, and <= 2 ulps for EXP(t) <= -2. Additional error if k_no_zero: treal = t * errk, with 1 - |k| * 2^(-Nt) <= exp(-|k| * 2^(-Nt)) <= errk <= 1, i.e., additional absolute error <= 2^(EXP(k)+EXP(t)-Nt). Total error <= 2^err1 + 2^err2 <= 2^(max(err1,err2)+1). */ err = MPFR_NOTZERO (t) && MPFR_GET_EXP (t) >= -1 ? MPFR_GET_EXP (t) + 3 : 1; if (k_non_zero) { if (MPFR_GET_EXP (k) > err) err = MPFR_GET_EXP (k); err++; } MPFR_BLOCK (flags1, mpfr_exp (t, t, MPFR_RNDN)); /* exp(y*ln|x|)*/ /* We need to test */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t) || MPFR_UNDERFLOW (flags1))) { mpfr_prec_t Ntmin; MPFR_BLOCK_DECL (flags2); MPFR_ASSERTN (!k_non_zero); MPFR_ASSERTN (!MPFR_IS_NAN (t)); /* Real underflow? */ if (MPFR_IS_ZERO (t)) { /* Underflow. We computed rndn(exp(t)), where t >= y*ln|x|. Therefore rndn(|x|^y) = 0, and we have a real underflow on |x|^y. */ inexact = mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW); break; } /* Real overflow? */ if (MPFR_IS_INF (t)) { /* Note: we can probably use a low precision for this test. */ mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD); mpfr_mul (t, y, t, MPFR_RNDD); /* y * ln|x| */ MPFR_BLOCK (flags2, mpfr_exp (t, t, MPFR_RNDD)); /* t = lower bound on exp(y * ln|x|) */ if (MPFR_OVERFLOW (flags2)) { /* We have computed a lower bound on |x|^y, and it overflowed. Therefore we have a real overflow on |x|^y. */ inexact = mpfr_overflow (z, rnd_mode, MPFR_SIGN_POS); if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW); break; } } k_non_zero = 1; Ntmin = sizeof(mpfr_exp_t) * CHAR_BIT; if (Ntmin > Nt) { Nt = Ntmin; mpfr_set_prec (t, Nt); } mpfr_init2 (u, Nt); mpfr_init2 (k, Ntmin); mpfr_log2 (k, absx, MPFR_RNDN); mpfr_mul (k, y, k, MPFR_RNDN); mpfr_round (k, k); MPFR_LOG_VAR (k); /* |y| < 2^Ntmin, therefore |k| < 2^Nt. */ continue; } if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Nz, rnd_mode))) { inexact = mpfr_set (z, t, rnd_mode); break; } /* check exact power, except when y is an integer (since the exact cases for y integer have already been filtered out) */ if (check_exact_case == 0 && ! y_is_integer) { if (mpfr_pow_is_exact (z, absx, y, rnd_mode, &inexact)) break; check_exact_case = 1; } /* reactualisation of the precision */ MPFR_ZIV_NEXT (ziv_loop, Nt); mpfr_set_prec (t, Nt); if (k_non_zero) mpfr_set_prec (u, Nt); } MPFR_ZIV_FREE (ziv_loop); if (k_non_zero) { int inex2; long lk; /* The rounded result in an unbounded exponent range is z * 2^k. As * MPFR chooses underflow after rounding, the mpfr_mul_2si below will * correctly detect underflows and overflows. However, in rounding to * nearest, if z * 2^k = 2^(emin - 2), then the double rounding may * affect the result. We need to cope with that before overwriting z. * This can occur only if k < 0 (this test is necessary to avoid a * potential integer overflow). * If inexact >= 0, then the real result is <= 2^(emin - 2), so that * o(2^(emin - 2)) = +0 is correct. If inexact < 0, then the real * result is > 2^(emin - 2) and we need to round to 2^(emin - 1). */ MPFR_ASSERTN (MPFR_EXP_MAX <= LONG_MAX); lk = mpfr_get_si (k, MPFR_RNDN); /* Due to early overflow detection, |k| should not be much larger than * MPFR_EMAX_MAX, and as MPFR_EMAX_MAX <= MPFR_EXP_MAX/2 <= LONG_MAX/2, * an overflow should not be possible in mpfr_get_si (and lk is exact). * And one even has the following assertion. TODO: complete proof. */ MPFR_ASSERTD (lk > LONG_MIN && lk < LONG_MAX); /* Note: even in case of overflow (lk inexact), the code is correct. * Indeed, for the 3 occurrences of lk: * - The test lk < 0 is correct as sign(lk) = sign(k). * - In the test MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk, * if lk is inexact, then lk = LONG_MIN <= MPFR_EXP_MIN * (the minimum value of the mpfr_exp_t type), and * __gmpfr_emin - 1 - lk >= MPFR_EMIN_MIN - 1 - 2 * MPFR_EMIN_MIN * >= - MPFR_EMIN_MIN - 1 = MPFR_EMAX_MAX - 1. However, from the * choice of k, z has been chosen to be around 1, so that the * result of the test is false, as if lk were exact. * - In the mpfr_mul_2si (z, z, lk, rnd_mode), if lk is inexact, * then |lk| >= LONG_MAX >= MPFR_EXP_MAX, and as z is around 1, * mpfr_mul_2si underflows or overflows in the same way as if * lk were exact. * TODO: give a bound on |t|, then on |EXP(z)|. */ if (rnd_mode == MPFR_RNDN && inexact < 0 && lk < 0 && MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk && mpfr_powerof2_raw (z)) { /* Rounding to nearest, real result > z * 2^k = 2^(emin - 2), * underflow case: as the minimum precision is > 1, we will * obtain the correct result and exceptions by replacing z by * nextabove(z). */ MPFR_ASSERTN (MPFR_PREC_MIN > 1); mpfr_nextabove (z); } MPFR_CLEAR_FLAGS (); inex2 = mpfr_mul_2si (z, z, lk, rnd_mode); if (inex2) /* underflow or overflow */ { inexact = inex2; if (expo != NULL) MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, __gmpfr_flags); } mpfr_clears (u, k, (mpfr_ptr) 0); } mpfr_clear (t); /* update the sign of the result if x was negative */ if (neg_result) { MPFR_SET_NEG(z); inexact = -inexact; } return inexact; }
int mpfr_log (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode) { int inexact; mpfr_prec_t p, q; mpfr_t tmp1, tmp2; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); MPFR_GROUP_DECL(group); MPFR_LOG_FUNC (("a[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (a), mpfr_log_prec, a, rnd_mode), ("r[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (r), mpfr_log_prec, r, inexact)); /* Special cases */ if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) { /* If a is NaN, the result is NaN */ if (MPFR_IS_NAN (a)) { MPFR_SET_NAN (r); MPFR_RET_NAN; } /* check for infinity before zero */ else if (MPFR_IS_INF (a)) { if (MPFR_IS_NEG (a)) /* log(-Inf) = NaN */ { MPFR_SET_NAN (r); MPFR_RET_NAN; } else /* log(+Inf) = +Inf */ { MPFR_SET_INF (r); MPFR_SET_POS (r); MPFR_RET (0); } } else /* a is zero */ { MPFR_ASSERTD (MPFR_IS_ZERO (a)); MPFR_SET_INF (r); MPFR_SET_NEG (r); mpfr_set_divby0 (); MPFR_RET (0); /* log(0) is an exact -infinity */ } } /* If a is negative, the result is NaN */ else if (MPFR_UNLIKELY (MPFR_IS_NEG (a))) { MPFR_SET_NAN (r); MPFR_RET_NAN; } /* If a is 1, the result is 0 */ else if (MPFR_UNLIKELY (MPFR_GET_EXP (a) == 1 && mpfr_cmp_ui (a, 1) == 0)) { MPFR_SET_ZERO (r); MPFR_SET_POS (r); MPFR_RET (0); /* only "normal" case where the result is exact */ } q = MPFR_PREC (r); /* use initial precision about q+lg(q)+5 */ p = q + 5 + 2 * MPFR_INT_CEIL_LOG2 (q); /* % ~(mpfr_prec_t)GMP_NUMB_BITS ; m=q; while (m) { p++; m >>= 1; } */ /* if (MPFR_LIKELY(p % GMP_NUMB_BITS != 0)) p += GMP_NUMB_BITS - (p%GMP_NUMB_BITS); */ MPFR_SAVE_EXPO_MARK (expo); MPFR_GROUP_INIT_2 (group, p, tmp1, tmp2); MPFR_ZIV_INIT (loop, p); for (;;) { long m; mpfr_exp_t cancel; /* Calculus of m (depends on p) */ m = (p + 1) / 2 - MPFR_GET_EXP (a) + 1; mpfr_mul_2si (tmp2, a, m, MPFR_RNDN); /* s=a*2^m, err<=1 ulp */ mpfr_div (tmp1, __gmpfr_four, tmp2, MPFR_RNDN);/* 4/s, err<=2 ulps */ mpfr_agm (tmp2, __gmpfr_one, tmp1, MPFR_RNDN); /* AG(1,4/s),err<=3 ulps */ mpfr_mul_2ui (tmp2, tmp2, 1, MPFR_RNDN); /* 2*AG(1,4/s), err<=3 ulps */ mpfr_const_pi (tmp1, MPFR_RNDN); /* compute pi, err<=1ulp */ mpfr_div (tmp2, tmp1, tmp2, MPFR_RNDN); /* pi/2*AG(1,4/s), err<=5ulps */ mpfr_const_log2 (tmp1, MPFR_RNDN); /* compute log(2), err<=1ulp */ mpfr_mul_si (tmp1, tmp1, m, MPFR_RNDN); /* compute m*log(2),err<=2ulps */ mpfr_sub (tmp1, tmp2, tmp1, MPFR_RNDN); /* log(a), err<=7ulps+cancel */ if (MPFR_LIKELY (MPFR_IS_PURE_FP (tmp1) && MPFR_IS_PURE_FP (tmp2))) { cancel = MPFR_GET_EXP (tmp2) - MPFR_GET_EXP (tmp1); MPFR_LOG_MSG (("canceled bits=%ld\n", (long) cancel)); MPFR_LOG_VAR (tmp1); if (MPFR_UNLIKELY (cancel < 0)) cancel = 0; /* we have 7 ulps of error from the above roundings, 4 ulps from the 4/s^2 second order term, plus the canceled bits */ if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp1, p-cancel-4, q, rnd_mode))) break; /* VL: I think it is better to have an increment that it isn't too low; in particular, the increment must be positive even if cancel = 0 (can this occur?). */ p += cancel >= 8 ? cancel : 8; } else { /* TODO: find why this case can occur and what is best to do with it. */ p += 32; } MPFR_ZIV_NEXT (loop, p); MPFR_GROUP_REPREC_2 (group, p, tmp1, tmp2); } MPFR_ZIV_FREE (loop); inexact = mpfr_set (r, tmp1, rnd_mode); /* We clean */ MPFR_GROUP_CLEAR (group); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (r, inexact, rnd_mode); }