[BZ,#6803] Set errno for scalbln, scalbn

Message ID lj8io2$hgi$1@ger.gmane.org
State Superseded
Headers

Commit Message

Stefan Liebler April 23, 2014, 2:29 p.m. UTC
  Hi,

this patch sets errno to ERANGE on overflow and underflow.
The corresponding tests in libm-test.inc are updated to check for errno, 
too.

Tested on S390/S390x.

ok to commit?

Bye

---
2014-04-23  Stefan Liebler  <stli@linux.vnet.ibm.com>

	[BZ #6803]
	* sysdeps/ieee754/flt-32/s_scalbnf.c (__scalbnf):
	Set errno on underflow / overflow.
	* sysdeps/ieee754/dbl-64/s_scalbn.c (__scalbn): Likewise.
	* sysdeps/ieee754/ldbl-128/s_scalbnl.c (__scalbnl): Likewise.
	* sysdeps/ieee754/flt-32/s_scalblnf.c (__scalblnf): Likewise.
	* sysdeps/ieee754/dbl-64/s_scalbln.c (__scalbln): Likewise.
	* sysdeps/ieee754/ldbl-128/s_scalblnl.c (__scalblnl): Likewise.
	* math/libm-test.inc
	(scalbn_test_data): Add errno expectations.
	(scalbln_test_data): Likewise.
---
  

Comments

Joseph Myers April 25, 2014, 2:35 p.m. UTC | #1
On Wed, 23 Apr 2014, Stefan Liebler wrote:

> Hi,
> 
> this patch sets errno to ERANGE on overflow and underflow.
> The corresponding tests in libm-test.inc are updated to check for errno, too.
> 
> Tested on S390/S390x.
> 
> ok to commit?

I don't think this is the best approach.  Apart from needing lots of 
architecture-specific versions updated (so you'd need to draw the 
attention of relevant architecture maintainers to the issue), we already 
have a scalbn wrapper that checks for overflow/underflow and sets errno, 
in the form of ldexp.  So for scalbn it would be most natural to make 
scalbn an alias for __ldexp instead of __scalbn; for scalbln you'd need to 
add a new wrapper, replacing scalbln being an alias for __scalbln.

(The tests will then need to use ERRNO_PLUS_OFLOW etc. so the expectations 
only cover the cases where glibc guarantees errno setting.)
  

Patch

diff --git a/math/libm-test.inc b/math/libm-test.inc
index a4bf0b8..696aa96 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9175,35 +9175,35 @@  scalb_test (void)
 
 static const struct test_fi_f_data scalbn_test_data[] =
   {
-    TEST_fi_f (scalbn, 0, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_fi_f (scalbn, minus_zero, 0, minus_zero, NO_INEXACT_EXCEPTION),
-
-    TEST_fi_f (scalbn, plus_infty, 1, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_fi_f (scalbn, minus_infty, 1, minus_infty, NO_INEXACT_EXCEPTION),
-    TEST_fi_f (scalbn, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION),
-
-    TEST_fi_f (scalbn, 0.8L, 4, 12.8L, NO_INEXACT_EXCEPTION),
-    TEST_fi_f (scalbn, -0.854375L, 5, -27.34L, NO_INEXACT_EXCEPTION),
-
-    TEST_fi_f (scalbn, 1, 0L, 1, NO_INEXACT_EXCEPTION),
-
-    TEST_fi_f (scalbn, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, max_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, min_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, min_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, min_value / 4, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, min_value / 4, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-
-    TEST_fi_f (scalbn, -1, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -1, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -max_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -max_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -min_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -min_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -min_value / 4, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fi_f (scalbn, -min_value / 4, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
+    TEST_fi_f (scalbn, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fi_f (scalbn, minus_zero, 0, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fi_f (scalbn, plus_infty, 1, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fi_f (scalbn, minus_infty, 1, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fi_f (scalbn, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fi_f (scalbn, 0.8L, 4, 12.8L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fi_f (scalbn, -0.854375L, 5, -27.34L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fi_f (scalbn, 1, 0L, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fi_f (scalbn, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, max_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, min_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, min_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, min_value / 4, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, min_value / 4, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_fi_f (scalbn, -1, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -1, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -max_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -max_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -min_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -min_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -min_value / 4, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fi_f (scalbn, -min_value / 4, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
   };
 
 static void
@@ -9222,72 +9222,72 @@  ldexp_test (void)
 
 static const struct test_fl_f_data scalbln_test_data[] =
   {
-    TEST_fl_f (scalbln, 0, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_fl_f (scalbln, minus_zero, 0, minus_zero, NO_INEXACT_EXCEPTION),
-
-    TEST_fl_f (scalbln, plus_infty, 1, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_fl_f (scalbln, minus_infty, 1, minus_infty, NO_INEXACT_EXCEPTION),
-    TEST_fl_f (scalbln, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION),
-
-    TEST_fl_f (scalbln, 0.8L, 4, 12.8L, NO_INEXACT_EXCEPTION),
-    TEST_fl_f (scalbln, -0.854375L, 5, -27.34L, NO_INEXACT_EXCEPTION),
-
-    TEST_fl_f (scalbln, 1, 0L, 1, NO_INEXACT_EXCEPTION),
-
-    TEST_fl_f (scalbln, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-
-    TEST_fl_f (scalbln, -1, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -1, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-
-    TEST_fl_f (scalbln, 1, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, 1, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-
-    TEST_fl_f (scalbln, -1, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -1, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
+    TEST_fl_f (scalbln, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fl_f (scalbln, minus_zero, 0, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fl_f (scalbln, plus_infty, 1, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fl_f (scalbln, minus_infty, 1, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fl_f (scalbln, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fl_f (scalbln, 0.8L, 4, 12.8L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_fl_f (scalbln, -0.854375L, 5, -27.34L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fl_f (scalbln, 1, 0L, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_fl_f (scalbln, 1, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, 1, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, INT_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, INT_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_fl_f (scalbln, -1, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -1, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, INT_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, INT_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_fl_f (scalbln, 1, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, 1, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, LONG_MAX, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, LONG_MIN, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_fl_f (scalbln, -1, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -1, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, LONG_MAX, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, LONG_MIN, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
 
 #if LONG_MAX >= 0x100000000
-    TEST_fl_f (scalbln, 1, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, 1, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, max_value, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, min_value / 4, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-
-    TEST_fl_f (scalbln, -1, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -1, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -max_value, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION),
-    TEST_fl_f (scalbln, -min_value / 4, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION),
+    TEST_fl_f (scalbln, 1, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, 1, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, max_value, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, 0x88000000L, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, min_value / 4, -0x88000000L, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_fl_f (scalbln, -1, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -1, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -max_value, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, 0x88000000L, minus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+    TEST_fl_f (scalbln, -min_value / 4, -0x88000000L, minus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_ERANGE),
 #endif
   };
 
diff --git a/sysdeps/ieee754/dbl-64/s_scalbln.c b/sysdeps/ieee754/dbl-64/s_scalbln.c
index 874b98e..0970b8b 100644
--- a/sysdeps/ieee754/dbl-64/s_scalbln.c
+++ b/sysdeps/ieee754/dbl-64/s_scalbln.c
@@ -16,6 +16,7 @@ 
  * exponentiation or a multiplication.
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -42,9 +43,15 @@  __scalbln (double x, long int n)
   if (__glibc_unlikely (k == 0x7ff))
     return x + x;                                       /* NaN or Inf */
   if (__glibc_unlikely (n < -50000))
-    return tiny * __copysign (tiny, x);   /*underflow*/
+    {
+      __set_errno (ERANGE);
+      return tiny * __copysign (tiny, x);   /*underflow*/
+    }
   if (__glibc_unlikely (n > 50000 || k + n > 0x7fe))
-    return huge * __copysign (huge, x);   /* overflow  */
+    {
+      __set_errno (ERANGE);
+      return huge * __copysign (huge, x);   /* overflow  */
+    }
   /* Now k and n are bounded we know that k = k+n does not
      overflow.  */
   k = k + n;
@@ -53,7 +60,10 @@  __scalbln (double x, long int n)
       SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20)); return x;
     }
   if (k <= -54)
-    return tiny * __copysign (tiny, x);         /*underflow*/
+    {
+      __set_errno (ERANGE);
+      return tiny * __copysign (tiny, x);         /*underflow*/
+    }
   k += 54;                                      /* subnormal result */
   SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20));
   return x * twom54;
diff --git a/sysdeps/ieee754/dbl-64/s_scalbn.c b/sysdeps/ieee754/dbl-64/s_scalbn.c
index 0f58034..228c2f2 100644
--- a/sysdeps/ieee754/dbl-64/s_scalbn.c
+++ b/sysdeps/ieee754/dbl-64/s_scalbn.c
@@ -16,6 +16,7 @@ 
  * exponentiation or a multiplication.
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -42,9 +43,15 @@  __scalbn (double x, int n)
   if (__glibc_unlikely (k == 0x7ff))
     return x + x;                                       /* NaN or Inf */
   if (__glibc_unlikely (n < -50000))
-    return tiny * __copysign (tiny, x);   /*underflow*/
+    {
+      __set_errno (ERANGE);
+      return tiny * __copysign (tiny, x);   /*underflow*/
+    }
   if (__glibc_unlikely (n > 50000 || k + n > 0x7fe))
-    return huge * __copysign (huge, x);   /* overflow  */
+    {
+      __set_errno (ERANGE);
+      return huge * __copysign (huge, x);   /* overflow  */
+    }
   /* Now k and n are bounded we know that k = k+n does not
      overflow.  */
   k = k + n;
@@ -53,7 +60,10 @@  __scalbn (double x, int n)
       SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20)); return x;
     }
   if (k <= -54)
-    return tiny * __copysign (tiny, x);         /*underflow*/
+    {
+      __set_errno (ERANGE);
+      return tiny * __copysign (tiny, x);         /*underflow*/
+    }
   k += 54;                                      /* subnormal result */
   SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20));
   return x * twom54;
diff --git a/sysdeps/ieee754/flt-32/s_scalblnf.c b/sysdeps/ieee754/flt-32/s_scalblnf.c
index aa45164..2e985c5 100644
--- a/sysdeps/ieee754/flt-32/s_scalblnf.c
+++ b/sysdeps/ieee754/flt-32/s_scalblnf.c
@@ -13,6 +13,7 @@ 
  * ====================================================
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -35,17 +36,23 @@  __scalblnf (float x, long int n)
 	    k = ((ix&0x7f800000)>>23) - 25;
 	    }
 	if (__builtin_expect(k==0xff, 0)) return x+x;	/* NaN or Inf */
-	if (__builtin_expect(n< -50000, 0))
-	  return tiny*copysignf(tiny,x);	/*underflow*/
-	if (__builtin_expect(n> 50000 || k+n > 0xfe, 0))
-	  return huge*copysignf(huge,x); /* overflow  */
+	if (__builtin_expect(n< -50000, 0)) {
+	    __set_errno (ERANGE);
+	    return tiny*copysignf(tiny,x);	/*underflow*/
+	    }
+	if (__builtin_expect(n> 50000 || k+n > 0xfe, 0)) {
+	    __set_errno (ERANGE);
+	    return huge*copysignf(huge,x); /* overflow  */
+	    }
 	/* Now k and n are bounded we know that k = k+n does not
 	   overflow.  */
 	k = k+n;
 	if (__builtin_expect(k > 0, 1))		/* normal result */
 	    {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
-	if (k <= -25)
+	if (k <= -25) {
+	    __set_errno (ERANGE);
 	    return tiny*copysignf(tiny,x);	/*underflow*/
+	    }
 	k += 25;				/* subnormal result */
 	SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
 	return x*twom25;
diff --git a/sysdeps/ieee754/flt-32/s_scalbnf.c b/sysdeps/ieee754/flt-32/s_scalbnf.c
index 5d9bdd6..f78877d 100644
--- a/sysdeps/ieee754/flt-32/s_scalbnf.c
+++ b/sysdeps/ieee754/flt-32/s_scalbnf.c
@@ -13,6 +13,7 @@ 
  * ====================================================
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -35,17 +36,23 @@  __scalbnf (float x, int n)
 	    k = ((ix&0x7f800000)>>23) - 25;
 	    }
 	if (__builtin_expect(k==0xff, 0)) return x+x;	/* NaN or Inf */
-	if (__builtin_expect(n< -50000, 0))
-	  return tiny*__copysignf(tiny,x);	/*underflow*/
-	if (__builtin_expect(n> 50000 || k+n > 0xfe, 0))
-	  return huge*__copysignf(huge,x); /* overflow  */
+	if (__builtin_expect(n< -50000, 0)) {
+	    __set_errno (ERANGE);
+	    return tiny*__copysignf(tiny,x);	/*underflow*/
+	    }
+	if (__builtin_expect(n> 50000 || k+n > 0xfe, 0)) {
+	    __set_errno (ERANGE);
+	    return huge*__copysignf(huge,x); /* overflow  */
+	    }
 	/* Now k and n are bounded we know that k = k+n does not
 	   overflow.  */
 	k = k+n;
 	if (__builtin_expect(k > 0, 1))		/* normal result */
 	    {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
-	if (k <= -25)
+	if (k <= -25) {
+	    __set_errno (ERANGE);
 	    return tiny*__copysignf(tiny,x);	/*underflow*/
+	    }
 	k += 25;				/* subnormal result */
 	SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
 	return x*twom25;
diff --git a/sysdeps/ieee754/ldbl-128/s_scalblnl.c b/sysdeps/ieee754/ldbl-128/s_scalblnl.c
index f552393..9db43f9 100644
--- a/sysdeps/ieee754/ldbl-128/s_scalblnl.c
+++ b/sysdeps/ieee754/ldbl-128/s_scalblnl.c
@@ -25,6 +25,7 @@  static char rcsid[] = "$NetBSD: $";
  * exponentiation or a multiplication.
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -46,16 +47,23 @@  long double __scalblnl (long double x, long int n)
 	    k = ((hx>>48)&0x7fff) - 114;
 	}
         if (k==0x7fff) return x+x;		/* NaN or Inf */
-	if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow*/
-        if (n> 50000 || k+n > 0x7ffe)
-	  return huge*__copysignl(huge,x); /* overflow  */
+        if (n< -50000) {
+	    __set_errno (ERANGE);
+            return tiny*__copysignl(tiny,x); /*underflow*/
+        }
+	if (n> 50000 || k+n > 0x7ffe) {
+	    __set_errno (ERANGE);
+	    return huge*__copysignl(huge,x); /* overflow  */
+	}
 	/* Now k and n are bounded we know that k = k+n does not
 	   overflow.  */
         k = k+n;
         if (k > 0) 				/* normal result */
 	    {SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48)); return x;}
-        if (k <= -114)
+        if (k <= -114) {
+	  __set_errno (ERANGE);
 	  return tiny*__copysignl(tiny,x); 	/*underflow*/
+        }
         k += 114;				/* subnormal result */
 	SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48));
         return x*twom114;
diff --git a/sysdeps/ieee754/ldbl-128/s_scalbnl.c b/sysdeps/ieee754/ldbl-128/s_scalbnl.c
index 8916dcb..446c56e 100644
--- a/sysdeps/ieee754/ldbl-128/s_scalbnl.c
+++ b/sysdeps/ieee754/ldbl-128/s_scalbnl.c
@@ -25,6 +25,7 @@  static char rcsid[] = "$NetBSD: $";
  * exponentiation or a multiplication.
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -46,16 +47,23 @@  long double __scalbnl (long double x, int n)
 	    k = ((hx>>48)&0x7fff) - 114;
 	}
         if (k==0x7fff) return x+x;		/* NaN or Inf */
-	if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow*/
-        if (n> 50000 || k+n > 0x7ffe)
-	  return huge*__copysignl(huge,x); /* overflow  */
+        if (n< -50000) {
+	    __set_errno (ERANGE);
+	    return tiny*__copysignl(tiny,x); /*underflow*/
+        }
+        if (n> 50000 || k+n > 0x7ffe) {
+	    __set_errno (ERANGE);
+	    return huge*__copysignl(huge,x); /* overflow  */
+        }
 	/* Now k and n are bounded we know that k = k+n does not
 	   overflow.  */
         k = k+n;
         if (k > 0) 				/* normal result */
 	    {SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48)); return x;}
-        if (k <= -114)
-	  return tiny*__copysignl(tiny,x); 	/*underflow*/
+        if (k <= -114) {
+	    __set_errno (ERANGE);
+	    return tiny*__copysignl(tiny,x); 	/*underflow*/
+        }
         k += 114;				/* subnormal result */
 	SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48));
         return x*twom114;