This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH 7/8] Create and use SET_RESTORE_{ENV_,}ROUND{,F,L}.
I meant to also provide a diff -b version, to show where
the real changes are, modulo indentation changes...
r~
diff --git a/math/math_private.h b/math/math_private.h
index 20b4b5a..c9cb4e8 100644
--- a/math/math_private.h
+++ b/math/math_private.h
@@ -449,6 +449,31 @@ default_libc_feupdateenv (fenv_t *e)
# define libc_feupdateenvl default_libc_feupdateenv
#endif
+/* Save and restore the rounding mode within a lexical block. */
+
+#define SET_RESTORE_ROUND(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feupdateenv))); \
+ libc_feholdexcept_setround (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUNDF(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feupdateenvf))); \
+ libc_feholdexcept_setroundf (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUNDL(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feupdateenvl))); \
+ libc_feholdexcept_setroundl (&__libc_save_rm, (RM))
+
+/* Save and restore the rounding mode within a lexical block, and also
+ the set of exceptions raised within the block may be discarded. */
+
+#define SET_RESTORE_ENV_ROUND(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_fesetenv))); \
+ libc_feholdexcept_setround (&__libc_save_rm, (RM))
+#define SET_RESTORE_ENV_ROUNDF(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_fesetenvf))); \
+ libc_feholdexcept_setroundf (&__libc_save_rm, (RM))
+#define SET_RESTORE_ENV_ROUNDL(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_fesetenvl))); \
+ libc_feholdexcept_setroundl (&__libc_save_rm, (RM))
+
#define __nan(str) \
(__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
#define __nanf(str) \
diff --git a/sysdeps/ieee754/dbl-64/e_exp.c b/sysdeps/ieee754/dbl-64/e_exp.c
index 8231c56..e6af6b8 100644
--- a/sysdeps/ieee754/dbl-64/e_exp.c
+++ b/sysdeps/ieee754/dbl-64/e_exp.c
@@ -59,10 +59,9 @@ __ieee754_exp(double x) {
int4 k;
#endif
int4 i,j,m,n,ex;
- fenv_t env;
double retval;
- libc_feholdexcept_setround (&env, FE_TONEAREST);
+ SET_RESTORE_ROUND (FE_TONEAREST);
junk1.x = x;
m = junk1.i[HIGH_HALF];
@@ -157,7 +156,6 @@ __ieee754_exp(double x) {
else { retval = __slowexp(x); goto ret; }
}
ret:
- libc_feupdateenv (&env);
return retval;
}
#ifndef __ieee754_exp
diff --git a/sysdeps/ieee754/dbl-64/e_exp2.c b/sysdeps/ieee754/dbl-64/e_exp2.c
index 4cf879b..477ecf2 100644
--- a/sysdeps/ieee754/dbl-64/e_exp2.c
+++ b/sysdeps/ieee754/dbl-64/e_exp2.c
@@ -61,9 +61,9 @@ __ieee754_exp2 (double x)
int tval, unsafe;
double rx, x22, result;
union ieee754_double ex2_u, scale_u;
- fenv_t oldenv;
- libc_feholdexcept_setround (&oldenv, FE_TONEAREST);
+ {
+ SET_RESTORE_ENV_ROUND (FE_TONEAREST);
/* 1. Argument reduction.
Choose integers ex, -256 <= t < 256, and some real
@@ -75,8 +75,8 @@ __ieee754_exp2 (double x)
rx -= THREEp42;
x -= rx; /* Compute x=x1. */
/* Compute tval = (ex*512 + t)+256.
- Now, t = (tval mod 512)-256 and ex=tval/512 [that's mod, NOT %; and
- /-round-to-nearest not the usual c integer /]. */
+ Now, t = (tval mod 512)-256 and ex=tval/512 [that's mod, NOT %;
+ and /-round-to-nearest not the usual c integer /]. */
tval = (int) (rx * 512.0 + 256.0);
/* 2. Adjust for accurate table entry.
@@ -108,10 +108,9 @@ __ieee754_exp2 (double x)
* x + .240226506959100583)
* x + .69314718055994495) * ex2_u.d;
math_opt_barrier (x22);
+ }
/* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex). */
- libc_fesetenv (&oldenv);
-
result = x22 * x + ex2_u.d;
if (!unsafe)
diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index f668b4b..aa73a9f 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -85,10 +85,9 @@ __ieee754_pow(double x, double y) {
(u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0)) &&
/* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */
(v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */
- fenv_t env;
double retval;
- libc_feholdexcept_setround (&env, FE_TONEAREST);
+ SET_RESTORE_ROUND (FE_TONEAREST);
z = log1(x,&aa,&error); /* x^y =e^(y log (X)) */
t = y*134217729.0;
@@ -105,7 +104,6 @@ __ieee754_pow(double x, double y) {
t = __exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */
retval = (t>0)?t:power1(x,y);
- libc_feupdateenv (&env);
return retval;
}
diff --git a/sysdeps/ieee754/dbl-64/s_fma.c b/sysdeps/ieee754/dbl-64/s_fma.c
index a27e246..54a69d4 100644
--- a/sysdeps/ieee754/dbl-64/s_fma.c
+++ b/sysdeps/ieee754/dbl-64/s_fma.c
@@ -147,8 +147,9 @@ __fma (double x, double y, double z)
t2 = z - t2;
double a2 = t1 + t2;
- fenv_t env;
- libc_feholdexcept_setround (&env, FE_TOWARDZERO);
+ {
+ SET_RESTORE_ROUND (FE_TOWARDZERO);
+
/* Perform m2 + a2 addition with round to odd. */
u.d = a2 + m2;
@@ -156,7 +157,6 @@ __fma (double x, double y, double z)
{
if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0;
- libc_feupdateenv (&env);
/* Result is a1 + u.d. */
return a1 + u.d;
}
@@ -164,22 +164,21 @@ __fma (double x, double y, double z)
{
if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0;
- libc_feupdateenv (&env);
/* Result is a1 + u.d, scaled up. */
return (a1 + u.d) * 0x1p53;
}
- else
- {
+
if ((u.ieee.mantissa1 & 1) == 0)
u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0;
v.d = a1 + u.d;
- int j = libc_fetestexcept (FE_INEXACT) != 0;
- libc_feupdateenv (&env);
+ }
+
/* Ensure the following computations are performed in default rounding
mode instead of just reusing the round to zero computation. */
- asm volatile ("" : "=m" (u) : "m" (u));
- /* If a1 + u.d is exact, the only rounding happens during
- scaling down. */
+ math_opt_barrier (u);
+
+ int j = libc_fetestexcept (FE_INEXACT) != 0;
+ /* If a1 + u.d is exact, the only rounding happens during scaling down. */
if (j == 0)
return v.d * 0x1p-106;
/* If result rounded to zero is not subnormal, no double
@@ -199,8 +198,7 @@ __fma (double x, double y, double z)
v.ieee.mantissa1 & 1 is the round bit and j is our sticky
bit. In round-to-nearest 001 rounds down like 00,
011 rounds up, even though 01 rounds down (thus we need
- to adjust), 101 rounds down like 10 and 111 rounds up
- like 11. */
+ to adjust), 101 rounds down like 10 and 111 rounds up like 11. */
if ((v.ieee.mantissa1 & 3) == 1)
{
v.d *= 0x1p-106;
@@ -214,7 +212,6 @@ __fma (double x, double y, double z)
}
v.ieee.mantissa1 |= j;
return v.d * 0x1p-106;
- }
}
#ifndef __fma
weak_alias (__fma, fma)
diff --git a/sysdeps/ieee754/dbl-64/s_fmaf.c b/sysdeps/ieee754/dbl-64/s_fmaf.c
index 00cd382..30e4e33 100644
--- a/sysdeps/ieee754/dbl-64/s_fmaf.c
+++ b/sysdeps/ieee754/dbl-64/s_fmaf.c
@@ -31,16 +31,18 @@
float
__fmaf (float x, float y, float z)
{
- fenv_t env;
/* Multiplication is always exact. */
double temp = (double) x * (double) y;
union ieee754_double u;
- libc_feholdexcept_setroundf (&env, FE_TOWARDZERO);
+
+ {
+ SET_RESTORE_ROUND (FE_TOWARDZERO);
/* Perform addition with round to odd. */
u.d = temp + (double) z;
if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0;
- libc_feupdateenv (&env);
+ }
+
/* And finally truncation with round to nearest. */
return (float) u.d;
}
diff --git a/sysdeps/ieee754/dbl-64/s_sin.c b/sysdeps/ieee754/dbl-64/s_sin.c
index 32ba66d..1f02a54 100644
--- a/sysdeps/ieee754/dbl-64/s_sin.c
+++ b/sysdeps/ieee754/dbl-64/s_sin.c
@@ -108,10 +108,9 @@ __sin(double x){
#if 0
int4 nn;
#endif
- fenv_t env;
double retval = 0;
- libc_feholdexcept_setround (&env, FE_TONEAREST);
+ SET_RESTORE_ROUND (FE_TONEAREST);
u.x = x;
m = u.i[HIGH_HALF];
@@ -365,7 +364,6 @@ __sin(double x){
}
ret:
- libc_feupdateenv (&env);
return retval;
}
@@ -383,10 +381,9 @@ __cos(double x)
mynumber u,v;
int4 k,m,n;
- fenv_t env;
double retval = 0;
- libc_feholdexcept_setround (&env, FE_TONEAREST);
+ SET_RESTORE_ROUND (FE_TONEAREST);
u.x = x;
m = u.i[HIGH_HALF];
@@ -635,7 +632,6 @@ __cos(double x)
}
ret:
- libc_feupdateenv (&env);
return retval;
}
diff --git a/sysdeps/ieee754/dbl-64/s_tan.c b/sysdeps/ieee754/dbl-64/s_tan.c
index 2c26756..c155603 100644
--- a/sysdeps/ieee754/dbl-64/s_tan.c
+++ b/sysdeps/ieee754/dbl-64/s_tan.c
@@ -68,13 +68,12 @@ tan(double x) {
mp_no mpy;
#endif
- fenv_t env;
double retval;
int __branred(double, double *, double *);
int __mpranred(double, mp_no *, int);
- libc_feholdexcept_setround (&env, FE_TONEAREST);
+ SET_RESTORE_ROUND (FE_TONEAREST);
/* x=+-INF, x=NaN */
num.d = x; ux = num.i[HIGH_HALF];
@@ -503,7 +502,6 @@ tan(double x) {
goto ret;
ret:
- libc_feupdateenv (&env);
return retval;
}
diff --git a/sysdeps/ieee754/flt-32/e_exp2f.c b/sysdeps/ieee754/flt-32/e_exp2f.c
index e728e6e..4ea4811 100644
--- a/sysdeps/ieee754/flt-32/e_exp2f.c
+++ b/sysdeps/ieee754/flt-32/e_exp2f.c
@@ -54,9 +54,9 @@ __ieee754_exp2f (float x)
int tval, unsafe;
float rx, x22, result;
union ieee754_float ex2_u, scale_u;
- fenv_t oldenv;
- libc_feholdexcept_setroundf (&oldenv, FE_TONEAREST);
+ {
+ SET_RESTORE_ENV_ROUNDF (FE_TONEAREST);
/* 1. Argument reduction.
Choose integers ex, -128 <= t < 128, and some real
@@ -68,8 +68,8 @@ __ieee754_exp2f (float x)
rx -= THREEp14;
x -= rx; /* Compute x=x1. */
/* Compute tval = (ex*256 + t)+128.
- Now, t = (tval mod 256)-128 and ex=tval/256 [that's mod, NOT %; and
- /-round-to-nearest not the usual c integer /]. */
+ Now, t = (tval mod 256)-128 and ex=tval/256 [that's mod, NOT %;
+ and /-round-to-nearest not the usual c integer /]. */
tval = (int) (rx * 256.0f + 128.0f);
/* 2. Adjust for accurate table entry.
@@ -97,10 +97,9 @@ __ieee754_exp2f (float x)
less than 1.3e-10. */
x22 = (.24022656679f * x + .69314736128f) * ex2_u.f;
+ }
/* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex). */
- libc_fesetenv (&oldenv);
-
result = x22 * x + ex2_u.f;
if (!unsafe)
diff --git a/sysdeps/ieee754/flt-32/e_expf.c b/sysdeps/ieee754/flt-32/e_expf.c
index e69e7f6..af5bf9e 100644
--- a/sysdeps/ieee754/flt-32/e_expf.c
+++ b/sysdeps/ieee754/flt-32/e_expf.c
@@ -80,9 +80,9 @@ __ieee754_expf (float x)
double x22, t, result, dx;
float n, delta;
union ieee754_double ex2_u;
- fenv_t oldenv;
- libc_feholdexcept_setroundf (&oldenv, FE_TONEAREST);
+ {
+ SET_RESTORE_ENV_ROUNDF (FE_TONEAREST);
/* Calculate n. */
n = x * M_1_LN2 + THREEp22;
@@ -110,10 +110,9 @@ __ieee754_expf (float x)
with maximum error in [-2^-10-2^-28,2^-10+2^-28]
less than 5e-11. */
x22 = (0.5000000496709180453 * dx + 1.0000001192102037084) * dx + delta;
+ }
/* Return result. */
- libc_fesetenvf (&oldenv);
-
result = x22 * ex2_u.d + ex2_u.d;
return (float) result;
}