about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-28 09:32:12 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-28 09:32:12 +0000
commit41bf21a1e72c907b1a065727c3b5da43821ca6b0 (patch)
tree93612a0bb49dfead686c656b36da812fb810c2cf
parentbdc6f13012da775a124596c81e40139ee8d2ca91 (diff)
downloadglibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.tar.gz
glibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.tar.xz
glibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.zip
Avoid overflows from long double functions using __kernel_standard.
-rw-r--r--ChangeLog63
-rw-r--r--NEWS5
-rw-r--r--math/libm-test.inc42
-rw-r--r--math/w_acoshl.c2
-rw-r--r--math/w_acosl.c2
-rw-r--r--math/w_asinl.c2
-rw-r--r--math/w_atan2l.c4
-rw-r--r--math/w_atanhl.c8
-rw-r--r--math/w_coshl.c2
-rw-r--r--math/w_exp10l.c4
-rw-r--r--math/w_exp2l.c2
-rw-r--r--math/w_fmodl.c4
-rw-r--r--math/w_hypotl.c2
-rw-r--r--math/w_j0l.c8
-rw-r--r--math/w_j1l.c8
-rw-r--r--math/w_jnl.c8
-rw-r--r--math/w_lgammal.c8
-rw-r--r--math/w_log10l.c4
-rw-r--r--math/w_log2l.c4
-rw-r--r--math/w_logl.c4
-rw-r--r--math/w_powl.c16
-rw-r--r--math/w_remainderl.c4
-rw-r--r--math/w_scalbl.c6
-rw-r--r--math/w_sinhl.c2
-rw-r--r--math/w_sqrtl.c2
-rw-r--r--math/w_tgammal.c6
-rw-r--r--sysdeps/generic/math_private.h1
-rw-r--r--sysdeps/ieee754/k_standard.c32
-rw-r--r--sysdeps/ieee754/ldbl-128/w_expl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/w_expl.c4
30 files changed, 197 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index ad72281ecb..2d4beb47f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
+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.
+
 2012-03-27  Anton Blanchard  <anton@samba.org>
 
 	* sysdeps/unix/sysv/linux/powerpc/bits/mman.h: Define MAP_STACK and
diff --git a/NEWS b/NEWS
index e54abbef05..ea7a17815b 100644
--- a/NEWS
+++ b/NEWS
@@ -16,8 +16,9 @@ Version 2.16
   13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547,
   13551, 13552, 13553, 13555, 13559, 13566, 13583, 13618, 13637, 13656,
   13658, 13673, 13695, 13704, 13706, 13726, 13738, 13786, 13792, 13806,
-  13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13883,
-  13892
+  13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13879,
+  13883, 13892, 13910, 13911, 13912, 13913, 13915, 13916, 13917, 13918,
+  13919, 13920, 13921
 
 * ISO C11 support:
 
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3851855fec..68f6ef25c1 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 cc823b88e9..def7be435d 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 05023b4298..394fce1944 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 e4036d8806..e56e2e5273 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 855437699d..30f9512f91 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 319535d172..6b00bbb4ea 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 abca8b05f5..9c638e91e0 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 bea6a1ee41..7f426ea32b 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 f05a8fe6d6..7f06805a0d 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 b088cc3707..f508a1f647 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 522eb63c39..2e942cae30 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 54c9c89029..1532d2ebde 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 208377ecaf..0b0136026a 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 2028d488df..0263147b2f 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 7df38e761b..1dc7e58622 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 0e5a137508..3371b7bd51 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 eed04ff6cc..1400c938ee 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 593b37d81f..9ea4ff726a 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 5bb85976e3..37863889c3 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 3f67b5875f..a21065cd74 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 b3584dea0f..1181874cec 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 5e65cf9b95..f801b4dd92 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 2a4a0481b0..74529f9e2c 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 6910f923aa..86adab29ea 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 813ad93611..e2172246f2 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 5d84543b95..c3326d9ef5 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 f4deda872f..10193befa9 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 d61c0a37bb..55c68462bd 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);