diff options
author | Joseph Myers <joseph@codesourcery.com> | 2012-03-02 15:12:53 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2012-03-02 15:12:53 +0000 |
commit | 28afd92dbdb4fef4358051aad5cb944a9527a4b5 (patch) | |
tree | 3ebb910316034d2c7766c4eade3a2609b2b27bed /sysdeps/ieee754/dbl-64/e_exp.c | |
parent | b1eeb65d491c0fec94b29cfbbd2e384c9f3765cc (diff) | |
download | glibc-28afd92dbdb4fef4358051aad5cb944a9527a4b5.tar.gz glibc-28afd92dbdb4fef4358051aad5cb944a9527a4b5.tar.xz glibc-28afd92dbdb4fef4358051aad5cb944a9527a4b5.zip |
Fix exp in non-default rounding modes (bug 3976).
Diffstat (limited to 'sysdeps/ieee754/dbl-64/e_exp.c')
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_exp.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_exp.c b/sysdeps/ieee754/dbl-64/e_exp.c index cfdb8e2c7d..8231c5698c 100644 --- a/sysdeps/ieee754/dbl-64/e_exp.c +++ b/sysdeps/ieee754/dbl-64/e_exp.c @@ -1,7 +1,7 @@ /* * IBM Accurate Mathematical Library * written by International Business Machines Corp. - * Copyright (C) 2001, 2011 Free Software Foundation + * Copyright (C) 2001-2012 Free Software Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -38,6 +38,7 @@ #include "MathLib.h" #include "uexp.tbl" #include "math_private.h" +#include <fenv.h> #ifndef SECTION # define SECTION @@ -58,6 +59,10 @@ __ieee754_exp(double x) { int4 k; #endif int4 i,j,m,n,ex; + fenv_t env; + double retval; + + libc_feholdexcept_setround (&env, FE_TONEAREST); junk1.x = x; m = junk1.i[HIGH_HALF]; @@ -90,18 +95,19 @@ __ieee754_exp(double x) { rem=(bet + bet*eps)+al*eps; res = al + rem; cor = (al - res) + rem; - if (res == (res+cor*err_0)) return res*binexp.x; - else return __slowexp(x); /*if error is over bound */ + if (res == (res+cor*err_0)) { retval = res*binexp.x; goto ret; } + else { retval = __slowexp(x); goto ret; } /*if error is over bound */ } - if (n <= smallint) return 1.0; + if (n <= smallint) { retval = 1.0; goto ret; } if (n >= badint) { - if (n > infint) return(x+x); /* x is NaN */ - if (n < infint) return ( (x>0) ? (hhuge*hhuge) : (tiny*tiny) ); + if (n > infint) { retval = x+x; goto ret; } /* x is NaN */ + if (n < infint) { retval = (x>0) ? (hhuge*hhuge) : (tiny*tiny); goto ret; } /* x is finite, cause either overflow or underflow */ - if (junk1.i[LOW_HALF] != 0) return (x+x); /* x is NaN */ - return ((x>0)?inf.x:zero ); /* |x| = inf; return either inf or 0 */ + if (junk1.i[LOW_HALF] != 0) { retval = x+x; goto ret; } /* x is NaN */ + retval = (x>0)?inf.x:zero; /* |x| = inf; return either inf or 0 */ + goto ret; } y = x*log2e.x + three51.x; @@ -126,8 +132,8 @@ __ieee754_exp(double x) { if (res < 1.0) {res+=res; cor+=cor; ex-=1;} if (ex >=-1022) { binexp.i[HIGH_HALF] = (1023+ex)<<20; - if (res == (res+cor*err_0)) return res*binexp.x; - else return __slowexp(x); /*if error is over bound */ + if (res == (res+cor*err_0)) { retval = res*binexp.x; goto ret; } + else { retval = __slowexp(x); goto ret; } /*if error is over bound */ } ex = -(1022+ex); binexp.i[HIGH_HALF] = (1023-ex)<<20; @@ -140,15 +146,19 @@ __ieee754_exp(double x) { cor = (t-res)+y; if (res == (res + eps*cor)) { binexp.i[HIGH_HALF] = 0x00100000; - return (res-1.0)*binexp.x; + retval = (res-1.0)*binexp.x; + goto ret; } - else return __slowexp(x); /* if error is over bound */ + else { retval = __slowexp(x); goto ret; } /* if error is over bound */ } else { binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+767)<<20; - if (res == (res+cor*err_0)) return res*binexp.x*t256.x; - else return __slowexp(x); + if (res == (res+cor*err_0)) { retval = res*binexp.x*t256.x; goto ret; } + else { retval = __slowexp(x); goto ret; } } + ret: + libc_feupdateenv (&env); + return retval; } #ifndef __ieee754_exp strong_alias (__ieee754_exp, __exp_finite) |