nearbyint optimization (only clear inexact when necessary)
authornsz <nsz@port70.net>
Tue, 20 Mar 2012 21:49:19 +0000 (22:49 +0100)
committernsz <nsz@port70.net>
Tue, 20 Mar 2012 21:49:19 +0000 (22:49 +0100)
old code saved/restored the fenv (the new code is only as slow
as that when inexact is not set before the call, but some other
flag is set and the rounding is inexact, which is rare)

before:
bench_nearbyint_exact              5000000 N        261 ns/op
bench_nearbyint_inexact_set        5000000 N        262 ns/op
bench_nearbyint_inexact_unset      5000000 N        261 ns/op

after:
bench_nearbyint_exact             10000000 N         94.99 ns/op
bench_nearbyint_inexact_set       25000000 N         65.81 ns/op
bench_nearbyint_inexact_unset     10000000 N         94.97 ns/op

src/math/nearbyint.c
src/math/nearbyintf.c
src/math/nearbyintl.c

index 714c55cadb68ed95a357a3bf900b00fe651b78d4..7a4c58cf5af64833c1460ca8772810aa19c16cda 100644 (file)
@@ -1,20 +1,19 @@
 #include <fenv.h>
 #include <math.h>
 
-/*
-rint may raise inexact (and it should not alter the fenv otherwise)
-nearbyint must not raise inexact
+/* nearbyint is the same as rint, but it must not raise the inexact exception */
 
-(according to ieee754r section 7.9 both functions should raise invalid
-when the input is signaling nan, but c99 does not define snan so saving
-and restoring the entire fenv should be fine)
-*/
+double nearbyint(double x)
+{
+#ifdef FE_INEXACT
+       int e;
 
-double nearbyint(double x) {
-       fenv_t e;
-
-       fegetenv(&e);
+       e = fetestexcept(FE_INEXACT);
+#endif
        x = rint(x);
-       fesetenv(&e);
+#ifdef FE_INEXACT
+       if (!e)
+               feclearexcept(FE_INEXACT);
+#endif
        return x;
 }
index 07df8f540507a43580c7945d910121c026fe45ab..39c3d73b5edb3deac52d193196e34a66f00ab359 100644 (file)
@@ -1,11 +1,17 @@
 #include <fenv.h>
 #include <math.h>
 
-float nearbyintf(float x) {
-       fenv_t e;
+float nearbyintf(float x)
+{
+#ifdef FE_INEXACT
+       int e;
 
-       fegetenv(&e);
+       e = fetestexcept(FE_INEXACT);
+#endif
        x = rintf(x);
-       fesetenv(&e);
+#ifdef FE_INEXACT
+       if (!e)
+               feclearexcept(FE_INEXACT);
+#endif
        return x;
 }
index 2906f38310b4d5359678da113fd62878f2cb05d9..0ff4b1f9e25ec4921ce9acae1495897ffeddf259 100644 (file)
@@ -10,11 +10,16 @@ long double nearbyintl(long double x)
 #include <fenv.h>
 long double nearbyintl(long double x)
 {
-       fenv_t e;
+#ifdef FE_INEXACT
+       int e;
 
-       fegetenv(&e);
+       e = fetestexcept(FE_INEXACT);
+#endif
        x = rintl(x);
-       fesetenv(&e);
+#ifdef FE_INEXACT
+       if (!e)
+               feclearexcept(FE_INEXACT);
+#endif
        return x;
 }
 #endif