This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Avoid overflows from long double functions using __kernel_standard


Error handling for various libm functions involves the function
__kernel_standard that provides support for errno setting and
"matherr".

This function takes double arguments; matherr is defined that way.
This causes problems for long double functions when converting long
double arguments to double causes overflow although the original
function did not overflow.  This patch addresses that by adding a
variant __kernel_standard_l that wraps __kernel_standard and reduces
out-of-range arguments to DBL_MAX or DBL_MIN (or minus those values)
to avoid spurious exceptions.

Tested x86 and x86_64.  Cases where there were spurious or missing
exceptions unrelated to this particular cause had appropriate comments
put in the tests (pointing to existing or new bugs) and
OVERFLOW_EXCEPTION_OK used to allow overflow exceptions to vary from
the desired results, or where other exceptions were involved some
tests were disabled for long double.

Aurelien, this should make it particularly easy to provide testsuite
coverage for your bug 13705 fix: simply remove ",
OVERFLOW_EXCEPTION_OK" and the comment from the test with a comment
pointing to bug 13705.

(This is actually the next piece of attempting to sort out bug 369; I
found too many of the new tests I added for that bug were failing for
long double because of issues with using __kernel_standard, so it
seemed appropriate to fix those issues first.)

2012-03-28  Joseph Myers  <joseph@codesourcery.com>

	[BZ #13879]
	[BZ #13910]
	[BZ #13911]
	[BZ #13912]
	[BZ #13913]
	[BZ #13915]
	[BZ #13916]
	[BZ #13917]
	[BZ #13918]
	[BZ #13919]
	[BZ #13920]
	[BZ #13921]
	* sysdeps/generic/math_private.h (__kernel_standard_l): Declare.
	* sysdeps/ieee754/k_standard.c: Include <float.h>.
	(__kernel_standard_l): New function.
	* math/w_acoshl.c (__acoshl): Use __kernel_standard_l instead of
	__kernel_standard.
	* math/w_acosl.c (__acosl): Likewise.
	* math/w_asinl.c (__asinl): Likewise.
	* math/w_atan2l.c (__atan2l): Likewise.
	* math/w_atanhl.c (__atanhl): Likewise.
	* math/w_coshl.c (__coshl): Likewise.
	* math/w_exp10l.c (__exp10l): Likewise.
	* math/w_exp2l.c (__exp2l): Likewise.
	* math/w_fmodl.c (__fmodl): Likewise.
	* math/w_hypotl.c (__hypotl): Likewise.
	* math/w_j0l.c (__j0l, __y0l): Likewise.
	* math/w_j1l.c (__j1l, __y1l): Likewise.
	* math/w_jnl.c (__jnl, __ynl): Likewise.
	* math/w_lgammal.c (__lgammal): Likewise.
	* math/w_log10l.c (__log10l): Likewise.
	* math/w_log2l.c (__log2l): Likewise.
	* math/w_logl.c (__logl): Likewise.
	* math/w_powl.c (__powl): Likewise.
	* math/w_remainderl.c (__remainderl): Likewise.
	* math/w_scalbl.c (sysv_scalbl): Likewise.
	* math/w_sinhl.c (__sinhl): Likewise.
	* math/w_sqrtl.c (__sqrtl): Likewise.
	* math/w_tgammal.c (__tgammal): Likewise.
	* sysdeps/ieee754/ldbl-128/w_expl.c (__expl): Likewise.
	* sysdeps/ieee754/ldbl-96/w_expl.c (__expl): Likewise.
	* math/libm-test.inc (acos_test): Add more tests.
	(acosh_test): Likewise.
	(asin_test): Likewise.
	(atanh_test): Likewise.
	(exp_test): Likewise.
	(exp10_test): Likewise.
	(exp2_test): Likewise.
	(expm1_test): Likewise.
	(lgamma_test): Likewise.
	(log_test): Likewise.
	(log10_test): Likewise.
	(log1p_test): Likewise.
	(log2_test): Likewise.
	(pow_test): Do not allow some spurious overflow exceptions.
	(sqrt_test): Add more tests.
	(tgamma_test): Likewise.
	(y0_test): Likewise.
	(y1_test): Likewise.
	(yn_test): Likewise.

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3851855..68f6ef2 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -746,6 +746,8 @@ acos_test (void)
   /* |x| > 1: */
   TEST_f_f (acos, 1.125L, nan_value, INVALID_EXCEPTION);
   TEST_f_f (acos, -1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acos, max_value, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acos, -max_value, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (acos, 0, M_PI_2l);
   TEST_f_f (acos, minus_zero, M_PI_2l);
@@ -775,6 +777,7 @@ acosh_test (void)
 
   /* x < 1:  */
   TEST_f_f (acosh, -1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acosh, -max_value, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (acosh, 1, 0);
   TEST_f_f (acosh, 7, 2.63391579384963341725009269461593689L);
@@ -800,6 +803,8 @@ asin_test (void)
   /* asin x == NaN plus invalid exception for |x| > 1.  */
   TEST_f_f (asin, 1.125L, nan_value, INVALID_EXCEPTION);
   TEST_f_f (asin, -1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (asin, max_value, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (asin, -max_value, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (asin, 0, 0);
   TEST_f_f (asin, minus_zero, minus_zero);
@@ -885,6 +890,8 @@ atanh_test (void)
   /* atanh (x) == NaN plus invalid exception if |x| > 1.  */
   TEST_f_f (atanh, 1.125L, nan_value, INVALID_EXCEPTION);
   TEST_f_f (atanh, -1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (atanh, max_value, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (atanh, -max_value, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (atanh, 0.75L, 0.972955074527656652552676371721589865L);
 
@@ -2994,6 +3001,11 @@ exp_test (void)
   TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L);
 #endif
 
+  /* Bug 13922: OVERFLOW exception may be missing.  */
+  TEST_f_f (exp, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
+  /* Bug 13705: spurious OVERFLOW exception may be present.  */
+  TEST_f_f (exp, -max_value, 0, OVERFLOW_EXCEPTION_OK);
+
   END (exp);
 }
 
@@ -3127,6 +3139,11 @@ exp10_test (void)
   TEST_f_f (exp10, -1, 0.1L);
   TEST_f_f (exp10, 1e6, plus_infty, OVERFLOW_EXCEPTION);
   TEST_f_f (exp10, -1e6, 0);
+#ifndef TEST_LDOUBLE /* Bug 13914: spurious exceptions.  */
+  TEST_f_f (exp10, max_value, plus_infty, OVERFLOW_EXCEPTION);
+  /* Bug 13924: spurious OVERFLOW exception may be present.  */
+  TEST_f_f (exp10, -max_value, 0, OVERFLOW_EXCEPTION_OK);
+#endif
   TEST_f_f (exp10, 0.75L, 5.62341325190349080394951039776481231L);
 
   END (exp10);
@@ -3154,6 +3171,8 @@ exp2_test (void)
   TEST_f_f (exp2, -1, 0.5);
   TEST_f_f (exp2, 1e6, plus_infty, OVERFLOW_EXCEPTION);
   TEST_f_f (exp2, -1e6, 0);
+  TEST_f_f (exp2, max_value, plus_infty, OVERFLOW_EXCEPTION);
+  TEST_f_f (exp2, -max_value, 0);
   TEST_f_f (exp2, 0.75L, 1.68179283050742908606225095246642979L);
 
   TEST_f_f (exp2, 100.5, 1.792728671193156477399422023278661496394e+30L);
@@ -3206,6 +3225,11 @@ expm1_test (void)
   /* Bug 13787: OVERFLOW exception may be missing.  */
   TEST_f_f (expm1, 100000.0, plus_infty, OVERFLOW_EXCEPTION_OK);
   check_int ("errno for expm1(large) == ERANGE", errno, ERANGE, 0, 0, 0);
+  /* Bug 13787: OVERFLOW exception may be missing.  */
+  TEST_f_f (expm1, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
+#ifndef TEST_LDOUBLE /* Bug 13923.  */
+  TEST_f_f (expm1, -max_value, -1);
+#endif
 
   END (expm1);
 }
@@ -3968,6 +3992,8 @@ lgamma_test (void)
   TEST_f_f (lgamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   check_int ("errno for lgamma(-integer) == ERANGE", errno, ERANGE, 0, 0, 0);
   TEST_f_f (lgamma, minus_infty, plus_infty);
+  TEST_f_f (lgamma, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (lgamma, max_value, plus_infty, OVERFLOW_EXCEPTION);
 
   TEST_f_f1 (lgamma, 1, 0, 1);
 
@@ -4869,6 +4895,7 @@ log_test (void)
   TEST_f_f (log, 1, 0);
 
   TEST_f_f (log, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (log, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (log, minus_infty, nan_value, INVALID_EXCEPTION);
   TEST_f_f (log, plus_infty, plus_infty);
   TEST_f_f (log, nan_value, nan_value);
@@ -4901,6 +4928,7 @@ log10_test (void)
 
   /* log10 (x) == NaN plus invalid exception if x < 0.  */
   TEST_f_f (log10, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (log10, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (log10, minus_infty, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (log10, plus_infty, plus_infty);
@@ -4933,6 +4961,7 @@ log1p_test (void)
 
   TEST_f_f (log1p, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   TEST_f_f (log1p, -2, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (log1p, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (log1p, minus_infty, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (log1p, plus_infty, plus_infty);
@@ -4964,6 +4993,7 @@ log2_test (void)
   TEST_f_f (log2, 1, 0);
 
   TEST_f_f (log2, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (log2, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (log2, minus_infty, nan_value, INVALID_EXCEPTION);
 
   TEST_f_f (log2, plus_infty, plus_infty);
@@ -5572,8 +5602,7 @@ pow_test (void)
   TEST_ff_f (pow, 0, -0x1p127, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   check_int ("errno for pow(0,-num) == ERANGE", errno, ERANGE, 0, 0, 0);
   errno = 0;
-  /* Bug 13879: spurious OVERFLOW exception may be present.  */
-  TEST_ff_f (pow, 0, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION|OVERFLOW_EXCEPTION_OK);
+  TEST_ff_f (pow, 0, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   check_int ("errno for pow(0,-num) == ERANGE", errno, ERANGE, 0, 0, 0);
   errno = 0;
   TEST_ff_f (pow, minus_zero, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
@@ -5588,8 +5617,7 @@ pow_test (void)
   TEST_ff_f (pow, minus_zero, -0x1p127, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   check_int ("errno for pow(-0,-num) == ERANGE", errno, ERANGE, 0, 0, 0);
   errno = 0;
-  /* Bug 13879: spurious OVERFLOW exception may be present.  */
-  TEST_ff_f (pow, minus_zero, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION|OVERFLOW_EXCEPTION_OK);
+  TEST_ff_f (pow, minus_zero, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   check_int ("errno for pow(-0,-num) == ERANGE", errno, ERANGE, 0, 0, 0);
 
   TEST_ff_f (pow, 0x1p72L, 0x1p72L, plus_infty, OVERFLOW_EXCEPTION);
@@ -7083,6 +7111,7 @@ sqrt_test (void)
 
   /* sqrt (x) == NaN plus invalid exception for x < 0.  */
   TEST_f_f (sqrt, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (sqrt, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (sqrt, minus_infty, nan_value, INVALID_EXCEPTION);
   TEST_f_f (sqrt, nan_value, nan_value);
 
@@ -7321,10 +7350,12 @@ tgamma_test (void)
   START (tgamma);
 
   TEST_f_f (tgamma, plus_infty, plus_infty);
+  TEST_f_f (tgamma, max_value, plus_infty, OVERFLOW_EXCEPTION);
   TEST_f_f (tgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   TEST_f_f (tgamma, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
   /* tgamma (x) == NaN plus invalid exception for integer x <= 0.  */
   TEST_f_f (tgamma, -2, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (tgamma, -max_value, nan_value, INVALID_EXCEPTION);
   TEST_f_f (tgamma, minus_infty, nan_value, INVALID_EXCEPTION);
   TEST_f_f (tgamma, nan_value, nan_value);
 
@@ -7468,6 +7499,7 @@ y0_test (void)
   START (y0);
 
   TEST_f_f (y0, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_f_f (y0, -max_value, minus_infty, INVALID_EXCEPTION);
   TEST_f_f (y0, 0.0, minus_infty);
   TEST_f_f (y0, nan_value, nan_value);
   TEST_f_f (y0, plus_infty, 0);
@@ -7508,6 +7540,7 @@ y1_test (void)
   START (y1);
 
   TEST_f_f (y1, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_f_f (y1, -max_value, minus_infty, INVALID_EXCEPTION);
   TEST_f_f (y1, 0.0, minus_infty);
   TEST_f_f (y1, plus_infty, 0);
   TEST_f_f (y1, nan_value, nan_value);
@@ -7549,6 +7582,7 @@ yn_test (void)
 
   /* yn (0, x) == y0 (x)  */
   TEST_ff_f (yn, 0, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_ff_f (yn, 0, -max_value, minus_infty, INVALID_EXCEPTION);
   TEST_ff_f (yn, 0, 0.0, minus_infty);
   TEST_ff_f (yn, 0, nan_value, nan_value);
   TEST_ff_f (yn, 0, plus_infty, 0);
diff --git a/math/w_acoshl.c b/math/w_acoshl.c
index cc823b8..def7be4 100644
--- a/math/w_acoshl.c
+++ b/math/w_acoshl.c
@@ -26,7 +26,7 @@ __acoshl (long double x)
 {
   if (__builtin_expect (isless (x, 1.0L), 0) && _LIB_VERSION != _IEEE_)
     /* acosh(x<1) */
-    return __kernel_standard (x, x, 229);
+    return __kernel_standard_l (x, x, 229);
 
   return __ieee754_acoshl (x);
 }
diff --git a/math/w_acosl.c b/math/w_acosl.c
index 05023b4..394fce1 100644
--- a/math/w_acosl.c
+++ b/math/w_acosl.c
@@ -30,7 +30,7 @@ __acosl (long double x)
     {
       /* acos(|x|>1) */
       feraiseexcept (FE_INVALID);
-      return __kernel_standard (x, x, 201);
+      return __kernel_standard_l (x, x, 201);
     }
 
   return __ieee754_acosl (x);
diff --git a/math/w_asinl.c b/math/w_asinl.c
index e4036d8..e56e2e5 100644
--- a/math/w_asinl.c
+++ b/math/w_asinl.c
@@ -30,7 +30,7 @@ __asinl (long double x)
     {
       /* asin(|x|>1) */
       feraiseexcept (FE_INVALID);
-      return __kernel_standard (x, x, 202);
+      return __kernel_standard_l (x, x, 202);
     }
 
   return __ieee754_asinl (x);
diff --git a/math/w_atan2l.c b/math/w_atan2l.c
index 8554376..30f9512 100644
--- a/math/w_atan2l.c
+++ b/math/w_atan2l.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -28,7 +28,7 @@ long double
 __atan2l (long double y, long double x)
 {
   if (__builtin_expect (x == 0.0L && y == 0.0L, 0) && _LIB_VERSION == _SVID_)
-    return __kernel_standard (y, x, 203); /* atan2(+-0,+-0) */
+    return __kernel_standard_l (y, x, 203); /* atan2(+-0,+-0) */
 
   return __ieee754_atan2l (y, x);
 }
diff --git a/math/w_atanhl.c b/math/w_atanhl.c
index 319535d..6b00bbb 100644
--- a/math/w_atanhl.c
+++ b/math/w_atanhl.c
@@ -26,10 +26,10 @@ __atanhl (long double x)
 {
   if (__builtin_expect (isgreaterequal (fabsl (x), 1.0L), 0)
       && _LIB_VERSION != _IEEE_)
-    return __kernel_standard (x, x,
-			      fabsl (x) > 1.0L
-			      ? 230		/* atanh(|x|>1) */
-			      : 231);		/* atanh(|x|==1) */
+    return __kernel_standard_l (x, x,
+				fabsl (x) > 1.0L
+				? 230		/* atanh(|x|>1) */
+				: 231);		/* atanh(|x|==1) */
 
   return __ieee754_atanhl (x);
 }
diff --git a/math/w_coshl.c b/math/w_coshl.c
index abca8b0..9c638e9 100644
--- a/math/w_coshl.c
+++ b/math/w_coshl.c
@@ -28,7 +28,7 @@ __coshl (long double x)
 	long double z = __ieee754_coshl (x);
 	if (__builtin_expect (!__finitel (z), 0) && __finitel (x)
 	    && _LIB_VERSION != _IEEE_)
-		return __kernel_standard (x, x, 205); /* cosh overflow */
+		return __kernel_standard_l (x, x, 205); /* cosh overflow */
 
 	return z;
 }
diff --git a/math/w_exp10l.c b/math/w_exp10l.c
index bea6a1e..7f426ea 100644
--- a/math/w_exp10l.c
+++ b/math/w_exp10l.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -31,7 +31,7 @@ __exp10l (long double x)
   if (__builtin_expect (!__finitel (z), 0)
       && __finitel (x) && _LIB_VERSION != _IEEE_)
     /* exp10l overflow (246) if x > 0, underflow (247) if x < 0.  */
-    return __kernel_standard (x, x, 246 + !!__signbitl (x));
+    return __kernel_standard_l (x, x, 246 + !!__signbitl (x));
 
   return z;
 }
diff --git a/math/w_exp2l.c b/math/w_exp2l.c
index f05a8fe..7f06805 100644
--- a/math/w_exp2l.c
+++ b/math/w_exp2l.c
@@ -12,7 +12,7 @@ __exp2l (long double x)
   if (__builtin_expect (!__finitel (z), 0)
       && __finitel (x) && _LIB_VERSION != _IEEE_)
     /* exp2 overflow: 244, exp2 underflow: 245 */
-    return __kernel_standard (x, x, 244 + !!__signbitl (x));
+    return __kernel_standard_l (x, x, 244 + !!__signbitl (x));
 
   return z;
 }
diff --git a/math/w_fmodl.c b/math/w_fmodl.c
index b088cc3..f508a1f 100644
--- a/math/w_fmodl.c
+++ b/math/w_fmodl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -26,7 +26,7 @@ __fmodl (long double x, long double y)
   if (__builtin_expect (__isinf_nsl (x) || y == 0.0L, 0)
       && _LIB_VERSION != _IEEE_ && !__isnanl (y) && !__isnanl (x))
     /* fmod(+-Inf,y) or fmod(x,0) */
-    return __kernel_standard (x, y, 227);
+    return __kernel_standard_l (x, y, 227);
 
   return __ieee754_fmodl (x, y);
 }
diff --git a/math/w_hypotl.c b/math/w_hypotl.c
index 522eb63..2e942ca 100644
--- a/math/w_hypotl.c
+++ b/math/w_hypotl.c
@@ -29,7 +29,7 @@ __hypotl(long double x, long double y)
 	z = __ieee754_hypotl(x,y);
 	if(__builtin_expect(!__finitel(z), 0)
 	   && __finitel(x) && __finitel(y) && _LIB_VERSION != _IEEE_)
-	    return __kernel_standard(x, y, 204); /* hypot overflow */
+	    return __kernel_standard_l(x, y, 204); /* hypot overflow */
 
 	return z;
 }
diff --git a/math/w_j0l.c b/math/w_j0l.c
index 54c9c89..1532d2e 100644
--- a/math/w_j0l.c
+++ b/math/w_j0l.c
@@ -28,7 +28,7 @@ __j0l (long double x)
   if (__builtin_expect (isgreater (fabsl (x), X_TLOSS), 0)
       && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_)
     /* j0(|x|>X_TLOSS) */
-    return __kernel_standard (x, x, 234);
+    return __kernel_standard_l (x, x, 234);
 
   return __ieee754_j0l (x);
 }
@@ -46,14 +46,14 @@ __y0l (long double x)
 	{
 	  /* d = zero/(x-x) */
 	  feraiseexcept (FE_INVALID);
-	  return __kernel_standard (x, x, 209);
+	  return __kernel_standard_l (x, x, 209);
 	}
       else if (x == 0.0L)
 	/* d = -one/(x-x) */
-	return __kernel_standard (x, x, 208);
+	return __kernel_standard_l (x, x, 208);
       else if (_LIB_VERSION != _POSIX_)
 	/* y0(x>X_TLOSS) */
-	return __kernel_standard (x, x, 235);
+	return __kernel_standard_l (x, x, 235);
     }
 
   return __ieee754_y0l (x);
diff --git a/math/w_j1l.c b/math/w_j1l.c
index 208377e..0b01360 100644
--- a/math/w_j1l.c
+++ b/math/w_j1l.c
@@ -28,7 +28,7 @@ __j1l (long double x)
   if (__builtin_expect (isgreater (fabsl (x), X_TLOSS), 0)
       && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_)
     /* j1(|x|>X_TLOSS) */
-    return __kernel_standard (x, x, 236);
+    return __kernel_standard_l (x, x, 236);
 
   return __ieee754_j1l (x);
 }
@@ -46,14 +46,14 @@ __y1l (long double x)
 	{
 	  /* d = zero/(x-x) */
 	  feraiseexcept (FE_INVALID);
-	  return __kernel_standard (x, x, 211);
+	  return __kernel_standard_l (x, x, 211);
 	}
       else if (x == 0.0L)
 	/* d = -one/(x-x) */
-	return __kernel_standard (x, x, 210);
+	return __kernel_standard_l (x, x, 210);
       else if (_LIB_VERSION != _POSIX_)
 	/* y1(x>X_TLOSS) */
-	return __kernel_standard (x, x, 237);
+	return __kernel_standard_l (x, x, 237);
     }
 
   return __ieee754_y1l (x);
diff --git a/math/w_jnl.c b/math/w_jnl.c
index 2028d48..0263147 100644
--- a/math/w_jnl.c
+++ b/math/w_jnl.c
@@ -59,7 +59,7 @@ long double __jnl(int n, long double x)	/* wrapper jnl */
 	    || __isnanl(x))
 	  return z;
 	if(fabsl(x)>X_TLOSS) {
-	    return __kernel_standard((double)n,x,238); /* jn(|x|>X_TLOSS,n) */
+	    return __kernel_standard_l((double)n,x,238); /* jn(|x|>X_TLOSS,n) */
 	} else
 	    return z;
 #endif
@@ -77,13 +77,13 @@ long double __ynl(int n, long double x)	/* wrapper ynl */
         if(x <= 0.0){
                 if(x==0.0)
                     /* d= -one/(x-x); */
-                    return __kernel_standard((double)n,x,212);
+                    return __kernel_standard_l((double)n,x,212);
                 else
                     /* d = zero/(x-x); */
-                    return __kernel_standard((double)n,x,213);
+                    return __kernel_standard_l((double)n,x,213);
         }
 	if(x>X_TLOSS && _LIB_VERSION != _POSIX_) {
-	    return __kernel_standard((double)n,x,239); /* yn(x>X_TLOSS,n) */
+	    return __kernel_standard_l((double)n,x,239); /* yn(x>X_TLOSS,n) */
 	} else
 	    return z;
 #endif
diff --git a/math/w_lgammal.c b/math/w_lgammal.c
index 7df38e7..1dc7e58 100644
--- a/math/w_lgammal.c
+++ b/math/w_lgammal.c
@@ -35,10 +35,10 @@ __lgammal(long double x)
 					    : &local_signgam);
 	if(__builtin_expect(!__finitel(y), 0)
 	   && __finitel(x) && _LIB_VERSION != _IEEE_)
-		return __kernel_standard(x, x,
-					 __floorl(x)==x&&x<=0.0L
-					 ? 215 /* lgamma pole */
-					 : 214); /* lgamma overflow */
+		return __kernel_standard_l(x, x,
+					   __floorl(x)==x&&x<=0.0L
+					   ? 215 /* lgamma pole */
+					   : 214); /* lgamma overflow */
 
 	return y;
 }
diff --git a/math/w_log10l.c b/math/w_log10l.c
index 0e5a137..3371b7b 100644
--- a/math/w_log10l.c
+++ b/math/w_log10l.c
@@ -30,12 +30,12 @@ __log10l (long double x)
       if (x == 0.0L)
 	{
 	  feraiseexcept (FE_DIVBYZERO);
-	  return __kernel_standard (x, x, 218); /* log10(0) */
+	  return __kernel_standard_l (x, x, 218); /* log10(0) */
 	}
       else
 	{
 	  feraiseexcept (FE_INVALID);
-	  return __kernel_standard (x, x, 219); /* log10(x<0) */
+	  return __kernel_standard_l (x, x, 219); /* log10(x<0) */
 	}
     }
 
diff --git a/math/w_log2l.c b/math/w_log2l.c
index eed04ff6c..1400c93 100644
--- a/math/w_log2l.c
+++ b/math/w_log2l.c
@@ -30,12 +30,12 @@ __log2l (long double x)
       if (x == 0.0L)
 	{
 	  feraiseexcept (FE_DIVBYZERO);
-	  return __kernel_standard (x, x, 248); /* log2(0) */
+	  return __kernel_standard_l (x, x, 248); /* log2(0) */
 	}
       else
 	{
 	  feraiseexcept (FE_INVALID);
-	  return __kernel_standard (x, x, 249); /* log2(x<0) */
+	  return __kernel_standard_l (x, x, 249); /* log2(x<0) */
 	}
     }
 
diff --git a/math/w_logl.c b/math/w_logl.c
index 593b37d..9ea4ff7 100644
--- a/math/w_logl.c
+++ b/math/w_logl.c
@@ -30,12 +30,12 @@ __logl (long double x)
       if (x == 0.0L)
 	{
 	  feraiseexcept (FE_DIVBYZERO);
-	  return __kernel_standard (x, x, 216); /* log(0) */
+	  return __kernel_standard_l (x, x, 216); /* log(0) */
 	}
       else
 	{
 	  feraiseexcept (FE_INVALID);
-	  return __kernel_standard (x, x, 217); /* log(x<0) */
+	  return __kernel_standard_l (x, x, 217); /* log(x<0) */
 	}
     }
 
diff --git a/math/w_powl.c b/math/w_powl.c
index 5bb8597..3786388 100644
--- a/math/w_powl.c
+++ b/math/w_powl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -33,25 +33,25 @@ __powl (long double x, long double y)
 	    {
 	      if (y == 0.0L)
 		/* pow(NaN,0.0) */
-		return __kernel_standard (x, y, 242);
+		return __kernel_standard_l (x, y, 242);
 	    }
 	  else if (__finitel (x) && __finitel (y))
 	    {
 	      if (__isnanl (z))
 		/* pow neg**non-int */
-		return __kernel_standard (x, y, 224);
+		return __kernel_standard_l (x, y, 224);
 	      else if (x == 0.0L && y < 0.0L)
 		{
 		  if (signbit (x) && signbit (z))
 		    /* pow(-0.0,negative) */
-		    return __kernel_standard (x, y, 223);
+		    return __kernel_standard_l (x, y, 223);
 		  else
 		    /* pow(+0.0,negative) */
-		    return __kernel_standard (x, y, 243);
+		    return __kernel_standard_l (x, y, 243);
 		}
 	      else
 		/* pow overflow */
-		return __kernel_standard (x, y, 221);
+		return __kernel_standard_l (x, y, 221);
 	    }
 	}
     }
@@ -62,11 +62,11 @@ __powl (long double x, long double y)
 	{
 	  if (y == 0.0L)
 	    /* pow(0.0,0.0) */
-	    return __kernel_standard (x, y, 220);
+	    return __kernel_standard_l (x, y, 220);
 	}
       else
 	/* pow underflow */
-	return __kernel_standard (x, y, 222);
+	return __kernel_standard_l (x, y, 222);
     }
 
   return z;
diff --git a/math/w_remainderl.c b/math/w_remainderl.c
index 3f67b58..a21065c 100644
--- a/math/w_remainderl.c
+++ b/math/w_remainderl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -27,7 +27,7 @@ __remainderl (long double x, long double y)
   if (((__builtin_expect (y == 0.0L, 0) && ! __isnanl (x))
        || (__builtin_expect (__isinf_nsl (x), 0) && ! __isnanl (y)))
       && _LIB_VERSION != _IEEE_)
-    return __kernel_standard (x, y, 228); /* remainder domain */
+    return __kernel_standard_l (x, y, 228); /* remainder domain */
 
   return __ieee754_remainderl (x, y);
 }
diff --git a/math/w_scalbl.c b/math/w_scalbl.c
index b3584de..1181874 100644
--- a/math/w_scalbl.c
+++ b/math/w_scalbl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -30,12 +30,12 @@ sysv_scalbl (long double x, long double fn)
   if (__builtin_expect (__isinfl (z), 0))
     {
       if (__finitel (x))
-	return __kernel_standard (x, fn, 232); /* scalb overflow */
+	return __kernel_standard_l (x, fn, 232); /* scalb overflow */
       else
 	__set_errno (ERANGE);
     }
   else if (__builtin_expect (z == 0.0L, 0) && z != x)
-    return __kernel_standard (x, fn, 233); /* scalb underflow */
+    return __kernel_standard_l (x, fn, 233); /* scalb underflow */
 
   return z;
 }
diff --git a/math/w_sinhl.c b/math/w_sinhl.c
index 5e65cf9..f801b4d 100644
--- a/math/w_sinhl.c
+++ b/math/w_sinhl.c
@@ -27,7 +27,7 @@ __sinhl (long double x)
 	long double z = __ieee754_sinhl (x);
 	if (__builtin_expect (!__finitel (z), 0) && __finitel (x)
 	    && _LIB_VERSION != _IEEE_)
-	    return __kernel_standard (x, x, 225); /* sinh overflow */
+	    return __kernel_standard_l (x, x, 225); /* sinh overflow */
 
 	return z;
 }
diff --git a/math/w_sqrtl.c b/math/w_sqrtl.c
index 2a4a048..74529f9 100644
--- a/math/w_sqrtl.c
+++ b/math/w_sqrtl.c
@@ -25,7 +25,7 @@ long double
 __sqrtl (long double x)
 {
   if (__builtin_expect (isless (x, 0.0L), 0) && _LIB_VERSION != _IEEE_)
-    return __kernel_standard (x, x, 226); /* sqrt(negative) */
+    return __kernel_standard_l (x, x, 226); /* sqrt(negative) */
 
   return __ieee754_sqrtl (x);
 }
diff --git a/math/w_tgammal.c b/math/w_tgammal.c
index 6910f92..86adab2 100644
--- a/math/w_tgammal.c
+++ b/math/w_tgammal.c
@@ -30,11 +30,11 @@ __tgammal(long double x)
 	if(__builtin_expect(!__finitel(y), 0) && __finitel(x)
 	   && _LIB_VERSION != _IEEE_) {
 	  if(x==0.0)
-	    return __kernel_standard(x,x,250); /* tgamma pole */
+	    return __kernel_standard_l(x,x,250); /* tgamma pole */
 	  else if(__floorl(x)==x&&x<0.0L)
-	    return __kernel_standard(x,x,241); /* tgamma domain */
+	    return __kernel_standard_l(x,x,241); /* tgamma domain */
 	  else
-	    return __kernel_standard(x,x,240); /* tgamma overflow */
+	    return __kernel_standard_l(x,x,240); /* tgamma overflow */
 	}
 	return local_signgam < 0 ? - y : y;
 }
diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h
index 813ad93..e217224 100644
--- a/sysdeps/generic/math_private.h
+++ b/sysdeps/generic/math_private.h
@@ -217,6 +217,7 @@ extern double __ieee754_scalb (double,double);
 /* fdlibm kernel function */
 extern double __kernel_standard (double,double,int);
 extern float __kernel_standard_f (float,float,int);
+extern long double __kernel_standard_l (long double,long double,int);
 extern double __kernel_sin (double,double,int);
 extern double __kernel_cos (double,double);
 extern double __kernel_tan (double,double,int);
diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c
index 5d84543..c3326d9 100644
--- a/sysdeps/ieee754/k_standard.c
+++ b/sysdeps/ieee754/k_standard.c
@@ -16,6 +16,7 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $
 
 #include <math.h>
 #include <math_private.h>
+#include <float.h>
 #include <errno.h>
 
 #include <assert.h>
@@ -998,3 +999,34 @@ __kernel_standard_f(float x, float y, int type)
 {
 	return __kernel_standard(x, y, type);
 }
+
+long double
+__kernel_standard_l (long double x, long double y, int type)
+{
+  double dx, dy;
+  if (isfinite (x))
+    {
+      long double ax = fabsl (x);
+      if (ax > DBL_MAX)
+	dx = __copysignl (DBL_MAX, x);
+      else if (ax > 0 && ax < DBL_MIN)
+	dx = __copysignl (DBL_MIN, x);
+      else
+	dx = x;
+    }
+  else
+    dx = x;
+  if (isfinite (y))
+    {
+      long double ay = fabsl (y);
+      if (ay > DBL_MAX)
+	dy = __copysignl (DBL_MAX, y);
+      else if (ay > 0 && ay < DBL_MIN)
+	dy = __copysignl (DBL_MIN, y);
+      else
+	dy = y;
+    }
+  else
+    dy = y;
+  return __kernel_standard (dx, dy, type);
+}
diff --git a/sysdeps/ieee754/ldbl-128/w_expl.c b/sysdeps/ieee754/ldbl-128/w_expl.c
index f4deda8..10193be 100644
--- a/sysdeps/ieee754/ldbl-128/w_expl.c
+++ b/sysdeps/ieee754/ldbl-128/w_expl.c
@@ -39,9 +39,9 @@ long double __expl(long double x)	/* wrapper exp */
 	if(_LIB_VERSION == _IEEE_) return z;
 	if(__finitel(x)) {
 	    if(x>o_threshold)
-	        return __kernel_standard(x,x,206); /* exp overflow */
+	        return __kernel_standard_l(x,x,206); /* exp overflow */
 	    else if(x<u_threshold)
-	        return __kernel_standard(x,x,207); /* exp underflow */
+	        return __kernel_standard_l(x,x,207); /* exp underflow */
 	}
 	return z;
 #endif
diff --git a/sysdeps/ieee754/ldbl-96/w_expl.c b/sysdeps/ieee754/ldbl-96/w_expl.c
index d61c0a3..55c6846 100644
--- a/sysdeps/ieee754/ldbl-96/w_expl.c
+++ b/sysdeps/ieee754/ldbl-96/w_expl.c
@@ -33,12 +33,12 @@ __expl (long double x)
   if (__builtin_expect (isgreater (x, o_threshold), 0))
     {
       if (_LIB_VERSION != _IEEE_)
-	return __kernel_standard (x, x, 206);
+	return __kernel_standard_l (x, x, 206);
     }
   else if (__builtin_expect (isless (x, u_threshold), 0))
     {
       if (_LIB_VERSION != _IEEE_)
-	return __kernel_standard (x, x, 207);
+	return __kernel_standard_l (x, x, 207);
     }
 
   return __ieee754_expl (x);

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]