]> Git Repo - uclibc-ng.git/commitdiff
docs/probe_math_exception.c:
authorDenis Vlasenko <[email protected]>
Wed, 11 Feb 2009 17:37:21 +0000 (17:37 -0000)
committerDenis Vlasenko <[email protected]>
Wed, 11 Feb 2009 17:37:21 +0000 (17:37 -0000)
update example
libc/sysdeps/linux/i386/bits/mathinline.h:
improve __finite() macro, add __finitef macro
(why they aren't always macros? why aren't they arch independent?)
libm/math_private.h:
much better comments on math_opt_barrier() and math_force_eval()
libm/s_finite[f].c:
improve out-of-line __finite[f]() too (one byte less, yay...)

docs/probe_math_exception.c
libc/sysdeps/linux/i386/bits/mathinline.h
libm/math_private.h
libm/s_finite.c
libm/s_finitef.c

index dbeccc5ccabd19d76c38f8d10107c1538b2b4f8e..dbc9020d4a16618289104dc8c2a5cee70bef400b 100644 (file)
@@ -5,20 +5,40 @@
 #define _ISOC99_SOURCE 1
 #define _GNU_SOURCE    1
 
+#include <stdint.h>
 #include <math.h>
 #include <fenv.h>
 #include <stdio.h>
 
 int main(int argc, char **argv)
 {
-       float infF = HUGE_VALF * 2;
+       float largest, small, t, inf_float;
+
+       largest = small = 1;
+       while (1) {
+               t = largest + small;
+               /* optimizations may make plain "t == largest" unreliable */
+               if (memcmp(&t, &largest, sizeof(float)) == 0)
+                       break;
+               if (isfinite(t)) {
+                       largest = t;
+                       small *= 2;
+                       continue;
+               }
+               small /= 2;
+       }
+       inf_float = largest + largest;
+       //printf("%.40g ", largest);
+       //printf("[%llx]\n", (long long) (*(uint32_t *)&largest));
 
        feclearexcept(FE_ALL_EXCEPT);
 
-//     printf("%.40e\n", 1.0 / 0.0); // FE_DIVBYZERO
-//     printf("%.40e\n", nextafterf(HUGE_VALF, infF)); // no exceptions in glibc 2.4
+       //t = 1.0 / 0.0; // simple test: FE_DIVBYZERO
+       //t = nextafterf(largest, 1); // glibc 2.8: no math exceptions raised
+       //t = nextafterf(largest, largest); // glibc 2.8: no math exceptions raised
+       //t = nextafterf(largest, inf_float); // glibc 2.8: FE_INEXACT FE_OVERFLOW
 
-#define PREX(ex) do { if (fetestexcept(ex)) printf(#ex); } while(0)
+#define PREX(ex) do { if (fetestexcept(ex)) printf(#ex " "); } while(0)
 #ifdef FE_INEXACT
        PREX(FE_INEXACT);
 #endif
@@ -36,6 +56,9 @@ int main(int argc, char **argv)
 #endif
        if (fetestexcept(FE_ALL_EXCEPT))
                printf("\n");
-       printf("done\n");
+       else
+               printf("no math exceptions raised\n");
+
+       printf("%.40g\n", t);
        return 0;
 }
index ca7277d760b783d5895f17b55213494d14a86990..5caf733538b2d54ee2d39de47ff5eabe3ea75a57 100644 (file)
@@ -713,11 +713,22 @@ __inline_mathcodeNP2 (drem, __x, __y, \
 __MATH_INLINE int
 __NTH (__finite (double __x))
 {
-  return (__extension__
-         (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
-            | 0x800fffffu) + 1) >> 31));
+  union { double __d; int __i[2]; } u;
+  u.__d = __x;
+  /* Finite numbers have at least one zero bit in exponent. */
+  /* All other numbers will result in 0xffffffff after OR: */
+  return (u.__i[1] | 0x800fffff) != 0xffffffff;
 }
 
+__MATH_INLINE int
+__NTH (__finitef (float __x))
+{
+  union { float __d; int __i; } u;
+  u.__d = __x;
+  return (u.__i | 0x807fffff) != 0xffffffff;
+}
+
+
 /* Miscellaneous functions */
 # ifdef __FAST_MATH__
 __inline_mathcode (__coshm1, __x, \
index 0601f2c3d679dade103369cdfe8d867b50000096..2c5a30ac201bc1c5d41662a844aaf85c29d4efca 100644 (file)
@@ -188,14 +188,24 @@ extern double __kernel_tan (double,double,int) attribute_hidden;
 extern int    __kernel_rem_pio2 (double*,double*,int,int,int,const int*) attribute_hidden;
 
 /*
- * math_opt_barrier(x): force expression x to be evaluated and put into
- * a floating point register or memory. This macro returns the value.
+ * math_opt_barrier(x): safely load x, even if it was manipulated
+ * by non-floationg point operations. This macro returns the value of x.
+ * This ensures compiler does not (ab)use its knowledge about x value
+ * and don't optimize future operations. Example:
+ * float x;
+ * SET_FLOAT_WORD(x, 0x80000001); // sets a bit pattern
+ * y = math_opt_barrier(x); // "compiler, do not cheat!"
+ * y = y * y; // compiler can't optimize, must use real multiply insn
  *
- * math_force_eval(x): force expression x to be evaluated and put into
+ * math_force_eval(x): force expression x to be evaluated.
+ * Useful if otherwise compiler may eliminate the expression
+ * as unused. This macro returns no value.
+ * Example: "void fn(float f) { f = f * f; }"
+ *   versus "void fn(float f) { f = f * f; math_force_eval(f); }"
+ *
+ * Currently, math_force_eval(x) stores x into
  * a floating point register or memory *of the appropriate size*.
- * This forces floating point flags to be set correctly
- * (for example, when float value is overflowing, but FPU registers
- * are wide enough to "hide" this).
+ * There is no guarantee this will not change.
  */
 #if defined(__i386__)
 #define math_opt_barrier(x) ({ \
@@ -205,19 +215,20 @@ extern int    __kernel_rem_pio2 (double*,double*,int,int,int,const int*) attribu
        __x; \
 })
 #define math_force_eval(x) do {        \
-       if (sizeof(x) <= sizeof(double)) \
+       __typeof(x) __x = (x); \
+       if (sizeof(__x) <= sizeof(double)) \
                /* "m": store x into a memory location */ \
-               __asm __volatile ("" : : "m" (x)); \
+               __asm __volatile ("" : : "m" (__x)); \
        else /* long double */ \
                /* "f": load x into (any) fpreg */ \
-               __asm __volatile ("" : : "f" (x)); \
+               __asm __volatile ("" : : "f" (__x)); \
 } while (0)
 #endif
 
 #if defined(__x86_64__)
 #define math_opt_barrier(x) ({ \
        __typeof(x) __x = (x); \
-       if (sizeof(x) <= sizeof(double)) \
+       if (sizeof(__x) <= sizeof(double)) \
                /* "x": load into XMM SSE register */ \
                __asm ("" : "=x" (__x) : "0" (__x)); \
        else /* long double */ \
@@ -226,19 +237,22 @@ extern int    __kernel_rem_pio2 (double*,double*,int,int,int,const int*) attribu
        __x; \
 })
 #define math_force_eval(x) do { \
-       if (sizeof(x) <= sizeof(double)) \
+       __typeof(x) __x = (x); \
+       if (sizeof(__x) <= sizeof(double)) \
                /* "x": load into XMM SSE register */ \
-               __asm __volatile ("" : : "x" (x)); \
+               __asm __volatile ("" : : "x" (__x)); \
        else /* long double */ \
                /* "f": load x into (any) fpreg */ \
-               __asm __volatile ("" : : "f" (x)); \
+               __asm __volatile ("" : : "f" (__x)); \
 } while (0)
 #endif
 
-/* Default implementation forces store to a memory location */
+/* Default implementations force store to a memory location */
 #ifndef math_opt_barrier
 #define math_opt_barrier(x) ({ __typeof(x) __x = (x); __asm ("" : "+m" (__x)); __x; })
-#define math_force_eval(x)  __asm __volatile ("" : : "m" (x))
+#endif
+#ifndef math_force_eval
+#define math_force_eval(x)  do { __typeof(x) __x = (x); __asm __volatile ("" : : "m" (__x)); } while (0)
 #endif
 
 
index 50fc11b5074243adb2a273d56aa8f659c6d74a9f..9bbc00286c7f814c67c20e387721038033b0c72a 100644 (file)
 
 int __finite(double x)
 {
-       int32_t hx;
-       GET_HIGH_WORD(hx,x);
-       return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31);
+       u_int32_t hx;
+
+       GET_HIGH_WORD(hx, x);
+       /* Finite numbers have at least one zero bit in exponent. */
+       /* All other numbers will result in 0xffffffff after OR: */
+       return (hx | 0x800fffff) != 0xffffffff;
 }
 libm_hidden_def(__finite)
index b7c853d4a61390d76caef9b704b6af446dd0b261..b427ea6913f94ca29d203b7c53e9e6950e3a960a 100644 (file)
 
 int __finitef(float x)
 {
-       int32_t ix;
-       GET_FLOAT_WORD(ix,x);
-       return (int)((u_int32_t)((ix&0x7fffffff)-0x7f800000)>>31);
+       u_int32_t ix;
+
+       GET_FLOAT_WORD(ix, x);
+       /* Finite numbers have at least one zero bit in exponent. */
+       /* All other numbers will result in 0xffffffff after OR: */
+       return (ix | 0x807fffff) != 0xffffffff;
 }
 libm_hidden_def(__finitef)
This page took 0.038557 seconds and 4 git commands to generate.