Improve c99 math and allow _matherr for internal functions.


git-svn-id: svn+ssh://svn.code.sf.net/p/mingw-w64/code/trunk@3076 4407c894-4637-0410-b4f5-ada5f102cad1
diff --git a/mingw-w64-crt/complex/complex_internal.h b/mingw-w64-crt/complex/complex_internal.h
index 5531430..ab4b78a 100644
--- a/mingw-w64-crt/complex/complex_internal.h
+++ b/mingw-w64-crt/complex/complex_internal.h
@@ -78,6 +78,7 @@
 # define __FLT_MAXLOG	88.72283905206835F
 # define __FLT_MINLOG	-103.278929903431851103F
 # define __FLT_LOGE2	0.693147180559945309F
+# define __FLT_REPORT(NAME) NAME "f"
 #elif defined(_NEW_COMPLEX_DOUBLE)
 # define __FLT_TYPE	double
 # define __FLT_ABI(N)	N
@@ -92,6 +93,7 @@
 # define __FLT_MAXLOG	7.09782712893383996843E2
 # define __FLT_MINLOG	-7.08396418532264106224E2
 # define __FLT_LOGE2	6.93147180559945309417E-1
+# define __FLT_REPORT(NAME)	NAME
 #elif defined(_NEW_COMPLEX_LDOUBLE)
 # define __FLT_TYPE	long double
 # define __FLT_ABI(N)	N##l
@@ -106,6 +108,18 @@
 # define __FLT_MAXLOG	1.1356523406294143949492E4L
 # define __FLT_MINLOG	-1.13994985314888605586758E4L
 # define __FLT_LOGE2	6.9314718055994530941723E-1L
+# define __FLT_REPORT(NAME) NAME "l"
 #else
 # error "Unknown complex number type"
 #endif
+
+#define __FLT_RPT_DOMAIN(NAME, ARG1, ARG2, RSLT) \
+	errno = EDOM, \
+	__mingw_raise_matherr (_DOMAIN, __FLT_REPORT(NAME), (double) (ARG1), \
+			       (double) (ARG2), (double) (RSLT))
+#define __FLT_RPT_ERANGE(NAME, ARG1, ARG2, RSLT, OVL) \
+	errno = ERANGE, \
+        __mingw_raise_matherr (((OVL) ? _OVERFLOW : _UNDERFLOW), \
+			       __FLT_REPORT(NAME), (double) (ARG1), \
+                               (double) (ARG2), (double) (RSLT))
+
diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c
index a89ba15..802990c 100644
--- a/mingw-w64-crt/crt/crtexe.c
+++ b/mingw-w64-crt/crt/crtexe.c
@@ -49,7 +49,6 @@
 #define _commode (* __MINGW_IMP_SYMBOL(_commode))
 extern int _dowildcard;
 
-extern int __defaultmatherr;
 extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
 
 static int __cdecl check_managed_app (void);
@@ -124,11 +123,7 @@
 #endif
   if (_MINGW_INSTALL_DEBUG_MATHERR)
     {
-      if (! __defaultmatherr)
-	{
-	  __setusermatherr (_matherr);
-	  __defaultmatherr = 1;
-	}
+      __setusermatherr (_matherr);
     }
 
   if (__globallocalestatus == -1)
diff --git a/mingw-w64-crt/crt/merr.c b/mingw-w64-crt/crt/merr.c
index 0f2491e..94f0a06 100644
--- a/mingw-w64-crt/crt/merr.c
+++ b/mingw-w64-crt/crt/merr.c
@@ -8,7 +8,6 @@
 #include <math.h>
 #include <stdio.h>
 
-int __defaultmatherr = 0;
 typedef int (__cdecl *fUserMathErr)(struct _exception *);
 static fUserMathErr stUserMathErr;
 
@@ -16,7 +15,7 @@
 			    double rslt)
 {
   struct _exception ex;
-  if (!__defaultmatherr || !stUserMathErr)
+  if (!stUserMathErr)
     return;
   ex.type = typ;
   ex.name = name;
@@ -31,7 +30,6 @@
 void __mingw_setusermatherr (int (__cdecl *f)(struct _exception *))
 {
   stUserMathErr = f;
-  __defaultmatherr = (!f ? 0 : 1);
   __setusermatherr (f);
 }
 
diff --git a/mingw-w64-crt/math/cos.def.h b/mingw-w64-crt/math/cos.def.h
index 7a7d16b..f082f37 100644
--- a/mingw-w64-crt/math/cos.def.h
+++ b/mingw-w64-crt/math/cos.def.h
@@ -53,12 +53,12 @@
   int x_class = fpclassify (x);
   if (x_class == FP_NAN)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("cos", x, 0.0, x);
       return x;
     }
   else if (x_class == FP_INFINITE)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("cos", x, 0.0, __FLT_NAN);
       return __FLT_NAN;
     }
   return (__FLT_TYPE) __cosl_internal ((long double) x);
diff --git a/mingw-w64-crt/math/exp.def.h b/mingw-w64-crt/math/exp.def.h
index b23b091..4650fd7 100644
--- a/mingw-w64-crt/math/exp.def.h
+++ b/mingw-w64-crt/math/exp.def.h
@@ -86,13 +86,14 @@
   int x_class = fpclassify (x);
   if (x_class == FP_NAN)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("exp", x, 0.0, x);
       return x;
     }
   else if (x_class == FP_INFINITE)
     {
-      errno = ERANGE;
-      return (signbit (x) ? __FLT_CST (0.0) : __FLT_HUGE_VAL);
+      __FLT_TYPE r = (signbit (x) ? __FLT_CST (0.0) : __FLT_HUGE_VAL);
+      __FLT_RPT_ERANGE ("exp", x, 0.0, r, signbit (x));
+      return r;
     }
   else if (x_class == FP_ZERO)
     {
@@ -100,12 +101,12 @@
     }
   else if (x > __FLT_MAXLOG)
     {
-      errno = ERANGE;
+      __FLT_RPT_ERANGE ("exp", x, 0.0, __FLT_HUGE_VAL, 1);
       return __FLT_HUGE_VAL;
     }
   else if (x < __FLT_MINLOG)
     {
-      errno = ERANGE;
+      __FLT_RPT_ERANGE ("exp", x, 0.0, 0.0, 0);
       return __FLT_CST(0.0);
     }
   else
diff --git a/mingw-w64-crt/math/expm1.def.h b/mingw-w64-crt/math/expm1.def.h
index d307809..00fa1d6 100644
--- a/mingw-w64-crt/math/expm1.def.h
+++ b/mingw-w64-crt/math/expm1.def.h
@@ -51,7 +51,7 @@
   int x_class = fpclassify (x);
   if (x_class == FP_NAN)
   {
-    errno = EDOM;
+    __FLT_RPT_DOMAIN ("expm1", x, 0.0, x);
     return x;
   }
   else if (x_class == FP_INFINITE)
diff --git a/mingw-w64-crt/math/log.def.h b/mingw-w64-crt/math/log.def.h
index 5a03c4e..9eddcb8 100644
--- a/mingw-w64-crt/math/log.def.h
+++ b/mingw-w64-crt/math/log.def.h
@@ -53,12 +53,12 @@
   int x_class = fpclassify (x);
   if (signbit (x))
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("log", x, 0.0, __FLT_NAN);
       return __FLT_NAN;
     }
   else if (x_class == FP_ZERO)
     {
-      errno = ERANGE;
+      __FLT_RPT_ERANGE ("log", x, 0.0, -__FLT_HUGE_VAL, 1);
       return -__FLT_HUGE_VAL;
     }
   else if (x_class == FP_INFINITE)
diff --git a/mingw-w64-crt/math/pow.def.h b/mingw-w64-crt/math/pow.def.h
index d9f7d1e..8a08508 100644
--- a/mingw-w64-crt/math/pow.def.h
+++ b/mingw-w64-crt/math/pow.def.h
@@ -81,8 +81,9 @@
     return __FLT_CST(1.0);
   else if (x_class == FP_NAN || y_class == FP_NAN)
     {
-      errno = EDOM;
-      return (signbit(x) ? -__FLT_NAN : __FLT_NAN);
+      rslt = (signbit(x) ? -__FLT_NAN : __FLT_NAN);
+      __FLT_RPT_DOMAIN ("pow", x, y, rslt);
+      return rslt;
     }
   else if (x_class == FP_ZERO)
     {
@@ -91,7 +92,7 @@
 
       if (signbit(x) && __FLT_ABI(modf) (y, &d) != 0.0)
 	{
-	  errno = EDOM;
+	  __FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN);
 	  return -__FLT_NAN;
 	}
       odd_y = (__FLT_ABI (modf) (__FLT_ABI (ldexp) (y, -1), &d) != 0.0) ? 1 : 0;
@@ -124,7 +125,7 @@
       /* pow (x, y) signals the invalid operation exception for finite x < 0 and finite non-integer y.  */
       if (signbit(x) && __FLT_ABI(modf) (y, &d) != 0.0)
 	{
-	  errno = EDOM;
+	  __FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN);
 	  return -__FLT_NAN;
 	}
       odd_y = (__FLT_ABI (modf) (__FLT_ABI (ldexp) (y, -1), &d) != 0.0) ? 1 : 0;
@@ -150,7 +151,7 @@
 
   if (signbit (x) && (__FLT_TYPE) __FLT_ABI(modf) (y, &d) != 0.0)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN);
       return -__FLT_NAN;
     }
   /* As exp already checks for minlog and maxlog no further checks are necessary.  */
diff --git a/mingw-w64-crt/math/sin.def.h b/mingw-w64-crt/math/sin.def.h
index 473f954..1673b34 100644
--- a/mingw-w64-crt/math/sin.def.h
+++ b/mingw-w64-crt/math/sin.def.h
@@ -53,12 +53,12 @@
   int x_class = fpclassify (x);
   if (x_class == FP_NAN)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("sin", x, 0.0, x);
       return x;
     }
   else if (x_class == FP_INFINITE)
     {
-      errno = EDOM;
+      __FLT_RPT_DOMAIN ("sin", x, 0.0, __FLT_NAN);
       return __FLT_NAN;
     }
   return (__FLT_TYPE) __sinl_internal ((long double) x);
diff --git a/mingw-w64-crt/math/sqrt.def.h b/mingw-w64-crt/math/sqrt.def.h
index 9002bc0..af349bc 100644
--- a/mingw-w64-crt/math/sqrt.def.h
+++ b/mingw-w64-crt/math/sqrt.def.h
@@ -52,8 +52,9 @@
   int x_class = fpclassify (x);
   if (x_class == FP_NAN || signbit (x))
     {
-      errno = EDOM;
-      return (signbit (x) ? -__FLT_NAN : __FLT_NAN);
+      res = (signbit (x) ? -__FLT_NAN : __FLT_NAN);
+      __FLT_RPT_DOMAIN ("sqrt", x, 0.0, res);
+      return res;
     }
   else if (x_class == FP_ZERO)
     return __FLT_CST (0.0);