diff options
author | pelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4> | 2005-02-10 15:43:41 +0000 |
---|---|---|
committer | pelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4> | 2005-02-10 15:43:41 +0000 |
commit | 667b2763ad6e7b02174303e6646e49f37e80a677 (patch) | |
tree | 820dfe4fc5f18fec632e9ee60ada8d3add40b89b /exp.c | |
parent | a9c75f5b66a8b6379b0c8d4782949ba935cb86c8 (diff) | |
download | mpfr-667b2763ad6e7b02174303e6646e49f37e80a677.tar.gz |
Add log for other functions.
Add ZivLoop too.
Cleanup exp3.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3290 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'exp.c')
-rw-r--r-- | exp.c | 64 |
1 files changed, 38 insertions, 26 deletions
@@ -60,6 +60,7 @@ mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) } } MPFR_CLEAR_FLAGS(y); + MPFR_LOG_BEGIN (("x[%#R]=%R rnd=%d", x, x, rnd_mode)); expx = MPFR_GET_EXP (x); precy = MPFR_PREC (y); @@ -69,48 +70,59 @@ mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) /* TODO: Don't convert to double! */ d = mpfr_get_d1 (x); if (MPFR_UNLIKELY (d >= (double) __gmpfr_emax * LOG2)) - return mpfr_overflow (y, rnd_mode, 1); + inexact = mpfr_overflow (y, rnd_mode, 1); /* result is 0 when exp(x) < 1/2*2^(__gmpfr_emin), i.e. x < (__gmpfr_emin-1) * LOG2 */ - if (MPFR_UNLIKELY(d < ((double) __gmpfr_emin - 1.0) * LOG2)) + else if (MPFR_UNLIKELY(d < ((double) __gmpfr_emin - 1.0) * LOG2)) { /* warning: mpfr_underflow rounds away for RNDN */ if (rnd_mode == GMP_RNDN && d < ((double) __gmpfr_emin - 2.0) * LOG2) rnd_mode = GMP_RNDZ; - return mpfr_underflow (y, rnd_mode, 1); + inexact = mpfr_underflow (y, rnd_mode, 1); } /* if x < 2^(-precy), then exp(x) i.e. gives 1 +/- 1 ulp(1) */ - if (MPFR_UNLIKELY (expx < 0 && (mpfr_uexp_t) (-expx) > precy)) + else if (MPFR_UNLIKELY (expx < 0 && (mpfr_uexp_t) (-expx) > precy)) { - int signx = MPFR_SIGN(x); + int signx = MPFR_SIGN (x); - MPFR_SET_POS(y); - if (MPFR_IS_NEG_SIGN(signx) && rnd_mode == GMP_RNDD) + MPFR_SET_POS (y); + if (MPFR_IS_NEG_SIGN (signx) && rnd_mode == GMP_RNDD) { mpfr_setmax (y, 0); /* y = 1 - epsilon */ - return -1; + inexact = -1; } - mpfr_setmin (y, 1); /* y = 1 */ - if (MPFR_IS_POS_SIGN(signx) && rnd_mode == GMP_RNDU) - { - mp_size_t yn; - int sh; + else + { + mpfr_setmin (y, 1); /* y = 1 */ + if (MPFR_IS_POS_SIGN (signx) && rnd_mode == GMP_RNDU) + { + mp_size_t yn; + int sh; + + yn = 1 + (MPFR_PREC(y) - 1) / BITS_PER_MP_LIMB; + sh = (mp_prec_t) yn * BITS_PER_MP_LIMB - MPFR_PREC(y); + MPFR_MANT(y)[0] += MPFR_LIMB_ONE << sh; + inexact = 1; + } + else + inexact = -MPFR_FROM_SIGN_TO_INT(signx); + } + } - yn = 1 + (MPFR_PREC(y) - 1) / BITS_PER_MP_LIMB; - sh = (mp_prec_t) yn * BITS_PER_MP_LIMB - MPFR_PREC(y); - MPFR_MANT(y)[0] += MPFR_LIMB_ONE << sh; - return 1; - } - return -MPFR_FROM_SIGN_TO_INT(signx); + /* General case */ + else + { + MPFR_SAVE_EXPO_MARK (expo); + if (MPFR_UNLIKELY (precy > MPFR_EXP_THRESHOLD)) + inexact = mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */ + else + inexact = mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */ + MPFR_SAVE_EXPO_FREE (expo); + inexact = mpfr_check_range (y, inexact, rnd_mode); } - MPFR_SAVE_EXPO_MARK (expo); - if (MPFR_UNLIKELY (precy > MPFR_EXP_THRESHOLD)) - inexact = mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */ - else - inexact = mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */ - MPFR_SAVE_EXPO_FREE (expo); - return mpfr_check_range (y, inexact, rnd_mode); + MPFR_LOG_END (("y[%#R]=%R inexact=%d", y, y, inexact)); + return inexact; } |