diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2006-08-14 22:23:01 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2006-08-14 22:23:01 +0000 |
commit | 452e19e6a64cfca7f2490829e48cce1f8a2f06ed (patch) | |
tree | 956a9dc446b05b1236f4c2589bae817bc8369ea0 /log1p.c | |
parent | 6d17415673b6aa803a1421d96a6ceb49569e33db (diff) | |
download | mpfr-452e19e6a64cfca7f2490829e48cce1f8a2f06ed.tar.gz |
Fixed bug in log1p for small negative values of x and added testcase.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@4114 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'log1p.c')
-rw-r--r-- | log1p.c | 13 |
1 files changed, 11 insertions, 2 deletions
@@ -29,6 +29,7 @@ int mpfr_log1p (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) { int comp, inexact; + mp_exp_t ex; MPFR_SAVE_EXPO_DECL (expo); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) @@ -62,8 +63,16 @@ mpfr_log1p (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) } } - /* log(1+x) = x-x^2/2 + ... so the error is < 2^(2*EXP(x)-1) */ - MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -MPFR_GET_EXP (x)+1,0,rnd_mode,{}); + ex = MPFR_GET_EXP (x); + if (ex < 0) /* -0.5 < x < 0.5 */ + { + /* For x > 0, abs(log(1+x)-x) < x^2/2. + For x > -0.5, abs(log(1+x)-x) < x^2. */ + if (MPFR_IS_POS (x)) + MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex - 1, 0, rnd_mode, {}); + else + MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex, 1, rnd_mode, {}); + } comp = mpfr_cmp_si (x, -1); /* log1p(x) is undefined for x < -1 */ |