diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-08-09 12:12:56 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-08-09 12:12:56 +0000 |
commit | 1d9f876a23d6b6416aeaa89967626537b757975f (patch) | |
tree | e3fac4f8c2b03b155e2472927e0758f01b823e46 /pow.c | |
parent | f516310ddce001f8c496edf1bbee86644bd926fc (diff) | |
download | mpfr-1d9f876a23d6b6416aeaa89967626537b757975f.tar.gz |
pow.c: added MPFR_SMALL_INPUT_AFTER_SAVE_EXPO for the case where
|y * log(x)| is very small (I can't really test because this code
currently fails due to a bug in mpfr_log: see test x_near_one
added to tlog.c as changeset 4736; this bug is also present in
the 2.2 branch).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@4737 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'pow.c')
-rw-r--r-- | pow.c | 21 |
1 files changed, 20 insertions, 1 deletions
@@ -179,6 +179,7 @@ int mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) { int inexact; + int cmp_x_1; MPFR_SAVE_EXPO_DECL (expo); MPFR_LOG_FUNC (("x[%#R]=%R y[%#R]=%R rnd=%d", x, x, y, y, rnd_mode), @@ -270,7 +271,8 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) } } - if (mpfr_cmp (x, __gmpfr_one) == 0) /* 1^y is always 1 */ + cmp_x_1 = mpfr_cmp (x, __gmpfr_one); + if (cmp_x_1 == 0) /* 1^y is always 1 */ return mpfr_set (z, __gmpfr_one, rnd_mode); /* detect overflows: |x^y| >= 2^EMAX when (EXP(x)-1) * y >= EMAX for y > 0, @@ -348,6 +350,23 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) MPFR_SAVE_EXPO_MARK (expo); + /* Case where |y * log(x)| is very small. */ + { + mpfr_t t; + mp_exp_t err; + + /* We need an upper bound on the exponent of y * log(x). */ + mpfr_init2 (t, 16); + mpfr_log (t, x, cmp_x_1 < 0 ? GMP_RNDD : GMP_RNDU); /* round away from 0 */ + MPFR_ASSERTN (MPFR_IS_PURE_FP (t)); + err = MPFR_GET_EXP (y) + MPFR_GET_EXP (t); + mpfr_clear (t); + mpfr_clear_flags (); + MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (z, __gmpfr_one, - err, 0, + (MPFR_SIGN (y) > 0) ^ (cmp_x_1 < 0), + rnd_mode, expo, {}); + } + /* General case */ { /* Declaration of the intermediary variable */ |