From 49c11f49544fd4ee9b0f88f4bdc742a86583852e Mon Sep 17 00:00:00 2001 From: vlefevre Date: Fri, 26 Jul 2002 15:52:58 +0000 Subject: Prototype of mpfr_setmax and mpfr_setmin changed (exponent given). In mpfr_exp for x ~= 0, add_one_ulp and sub_one_ulp are no longer used (sub_one_ulp was incorrect). These cases should now be faster. Small fix in mpfr_nextabove, mpfr_nextbelow and mpfr_nexttoward. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2002 280ebfd0-de03-0410-8827-d642c229c3f4 --- TODO | 2 -- exceptions.c | 4 ++-- exp.c | 27 +++++++++++++++++---------- mpfr-impl.h | 4 ++-- next.c | 21 +++++++++++++++------ setmax.c | 4 ++-- setmin.c | 4 ++-- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/TODO b/TODO index 341f32edc..ef941b31b 100644 --- a/TODO +++ b/TODO @@ -25,8 +25,6 @@ Changes in existing functions: Possibly accept other strings, like those accepted by strtod. - implement ternary flag for mpfr_agm: result is exact when u=v, or u=0, or v=0. -- use nextafter/nexttoward instead of add_one_ulp/sub_one_ulp in mpfr_exp - (they differ for a power of 2) New functions to implement: diff --git a/exceptions.c b/exceptions.c index be922a08c..ec7887308 100644 --- a/exceptions.c +++ b/exceptions.c @@ -196,7 +196,7 @@ mpfr_set_underflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign) || (rnd_mode == GMP_RNDU && sign > 0) || (rnd_mode == GMP_RNDD && sign < 0)) { - mpfr_setmin (x); + mpfr_setmin (x, __mpfr_emin); inex = 1; } else @@ -221,7 +221,7 @@ mpfr_set_overflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign) if ((rnd_mode == GMP_RNDU && sign < 0) || (rnd_mode == GMP_RNDD && sign > 0)) { - mpfr_setmax (x); + mpfr_setmax (x, __mpfr_emax); inex = -1; } else diff --git a/exp.c b/exp.c index 32d35ec8c..4aa50f612 100644 --- a/exp.c +++ b/exp.c @@ -85,17 +85,24 @@ mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) { int signx = MPFR_SIGN(x); - mpfr_set_ui (y, 1, rnd_mode); + if (signx < 0 && (rnd_mode == GMP_RNDD || rnd_mode == GMP_RNDZ)) + { + MPFR_CLEAR_FLAGS(y); + MPFR_SET_POS(y); + mpfr_setmax (y, 0); /* y = 1 - epsilon */ + return -1; + } + mpfr_setmin (y, 1); /* y = 1 */ if (signx > 0 && rnd_mode == GMP_RNDU) - { - mpfr_add_one_ulp (y, rnd_mode); - return 1; - } - else if (signx < 0 && (rnd_mode == GMP_RNDD || rnd_mode == GMP_RNDZ)) - { - mpfr_sub_one_ulp (y, rnd_mode); - return -1; - } + { + 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] += MP_LIMB_T_ONE << sh; + return 1; + } return -signx; } diff --git a/mpfr-impl.h b/mpfr-impl.h index d0b2fad1d..eb1ac8a26 100644 --- a/mpfr-impl.h +++ b/mpfr-impl.h @@ -198,8 +198,8 @@ unsigned long _mpfr_cuberoot _PROTO ((unsigned long)); int mpfr_exp_2 _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t)); int mpfr_exp3 _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t)); int mpfr_powerof2_raw _PROTO ((mpfr_srcptr)); -void mpfr_setmax _PROTO ((mpfr_ptr)); -void mpfr_setmin _PROTO ((mpfr_ptr)); +void mpfr_setmax _PROTO ((mpfr_ptr, mp_exp_t)); +void mpfr_setmin _PROTO ((mpfr_ptr, mp_exp_t)); #define mpfr_round_raw(yp, xp, xprec, neg, yprec, r, inexp) \ mpfr_round_raw_generic((yp), (xp), (xprec), (neg), (yprec), (r), (inexp), 0) diff --git a/next.c b/next.c index f545ee964..2f612d3df 100644 --- a/next.c +++ b/next.c @@ -32,14 +32,14 @@ mpfr_nexttozero (mpfr_ptr x) if (MPFR_IS_INF(x)) { MPFR_CLEAR_FLAGS(x); - mpfr_setmax (x); + mpfr_setmax (x, __mpfr_emax); return; } if (MPFR_IS_ZERO(x)) { MPFR_CHANGE_SIGN(x); - mpfr_setmin (x); + mpfr_setmin (x, __mpfr_emin); } else { @@ -75,7 +75,7 @@ mpfr_nexttoinf (mpfr_ptr x) return; if (MPFR_IS_ZERO(x)) - mpfr_setmin (x); + mpfr_setmin (x, __mpfr_emin); else { mp_size_t xn; @@ -103,7 +103,10 @@ void mpfr_nextabove (mpfr_ptr x) { if (MPFR_IS_NAN(x)) - MPFR_RET_NAN; + { + __mpfr_flags |= MPFR_FLAGS_NAN; + return; + } if (MPFR_SIGN(x) < 0) mpfr_nexttozero (x); @@ -115,7 +118,10 @@ void mpfr_nextbelow (mpfr_ptr x) { if (MPFR_IS_NAN(x)) - MPFR_RET_NAN; + { + __mpfr_flags |= MPFR_FLAGS_NAN; + return; + } if (MPFR_SIGN(x) < 0) mpfr_nexttoinf (x); @@ -129,7 +135,10 @@ mpfr_nexttoward (mpfr_ptr x, mpfr_srcptr y) int s; if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y)) - MPFR_RET_NAN; + { + __mpfr_flags |= MPFR_FLAGS_NAN; + return; + } s = mpfr_cmp (x, y); if (s == 0) diff --git a/setmax.c b/setmax.c index 4e9bf8d8e..141036908 100644 --- a/setmax.c +++ b/setmax.c @@ -27,13 +27,13 @@ MA 02111-1307, USA. */ /* Note: the flags are not cleared and the current sign is kept. */ -void mpfr_setmax (mpfr_ptr x) +void mpfr_setmax (mpfr_ptr x, mp_exp_t e) { mp_size_t xn, i; int sh; mp_limb_t *xp; - MPFR_EXP(x) = __mpfr_emax; + MPFR_EXP(x) = e; xn = 1 + (MPFR_PREC(x) - 1) / BITS_PER_MP_LIMB; sh = (mp_prec_t) xn * BITS_PER_MP_LIMB - MPFR_PREC(x); xp = MPFR_MANT(x); diff --git a/setmin.c b/setmin.c index 42eb30693..f4b0ca2b6 100644 --- a/setmin.c +++ b/setmin.c @@ -27,12 +27,12 @@ MA 02111-1307, USA. */ /* Note: the flags are not cleared and the current sign is kept. */ -void mpfr_setmin (mpfr_ptr x) +void mpfr_setmin (mpfr_ptr x, mp_exp_t e) { mp_size_t xn; mp_limb_t *xp; - MPFR_EXP(x) = __mpfr_emin; + MPFR_EXP(x) = e; xn = (MPFR_PREC(x) - 1) / BITS_PER_MP_LIMB; xp = MPFR_MANT(x); xp[xn] = MPFR_LIMB_HIGHBIT; -- cgit v1.2.1