summaryrefslogtreecommitdiff
path: root/math
diff options
context:
space:
mode:
Diffstat (limited to 'math')
-rwxr-xr-xmath/gen-libm-test.pl10
-rw-r--r--math/libm-test.inc134
-rw-r--r--math/w_scalb.c30
-rw-r--r--math/w_scalbf.c30
-rw-r--r--math/w_scalbl.c30
5 files changed, 159 insertions, 75 deletions
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index 6b3a21df40..5f62872b21 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -160,6 +160,8 @@ sub parse_args {
my ($ignore_result_any, $ignore_result_all);
my ($num_res, @args_res, @start_rm, $rm);
my (@plus_oflow, @minus_oflow, @plus_uflow, @minus_uflow);
+ my (@errno_plus_oflow, @errno_minus_oflow);
+ my (@errno_plus_uflow, @errno_minus_uflow);
($descr_args, $descr_res) = split /_/,$descr, 2;
@@ -258,6 +260,10 @@ sub parse_args {
@minus_oflow = qw(minus_infty minus_infty -max_value -max_value);
@plus_uflow = qw(plus_zero plus_zero plus_zero min_subnorm_value);
@minus_uflow = qw(-min_subnorm_value minus_zero minus_zero minus_zero);
+ @errno_plus_oflow = qw(0 ERRNO_ERANGE 0 ERRNO_ERANGE);
+ @errno_minus_oflow = qw(ERRNO_ERANGE ERRNO_ERANGE 0 0);
+ @errno_plus_uflow = qw(ERRNO_ERANGE ERRNO_ERANGE ERRNO_ERANGE 0);
+ @errno_minus_uflow = qw(0 ERRNO_ERANGE ERRNO_ERANGE ERRNO_ERANGE);
for ($rm = 0; $rm <= 3; $rm++) {
$current_arg = $start_rm[$rm];
$ignore_result_any = 0;
@@ -322,6 +328,10 @@ sub parse_args {
$cline_res =~ s/minus_oflow/$minus_oflow[$rm]/g;
$cline_res =~ s/plus_uflow/$plus_uflow[$rm]/g;
$cline_res =~ s/minus_uflow/$minus_uflow[$rm]/g;
+ $cline_res =~ s/ERRNO_PLUS_OFLOW/$errno_plus_oflow[$rm]/g;
+ $cline_res =~ s/ERRNO_MINUS_OFLOW/$errno_minus_oflow[$rm]/g;
+ $cline_res =~ s/ERRNO_PLUS_UFLOW/$errno_plus_uflow[$rm]/g;
+ $cline_res =~ s/ERRNO_MINUS_UFLOW/$errno_minus_uflow[$rm]/g;
$cline .= ", { $cline_res }";
}
print $file " $cline },\n";
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 0eff34a0ca..19194f63e9 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9087,72 +9087,74 @@ round_test (void)
static const struct test_ff_f_data scalb_test_data[] =
{
- TEST_ff_f (scalb, 2.0, 0.5, qnan_value, INVALID_EXCEPTION),
- TEST_ff_f (scalb, 3.0, -2.5, qnan_value, INVALID_EXCEPTION),
-
- TEST_ff_f (scalb, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-
- TEST_ff_f (scalb, 1, 0, 1),
- TEST_ff_f (scalb, -1, 0, -1),
-
- TEST_ff_f (scalb, 0, plus_infty, qnan_value, INVALID_EXCEPTION),
- TEST_ff_f (scalb, minus_zero, plus_infty, qnan_value, INVALID_EXCEPTION),
-
- TEST_ff_f (scalb, 0, 2, 0),
- TEST_ff_f (scalb, minus_zero, -4, minus_zero),
- TEST_ff_f (scalb, 0, 0, 0),
- TEST_ff_f (scalb, minus_zero, 0, minus_zero),
- TEST_ff_f (scalb, 0, -1, 0),
- TEST_ff_f (scalb, minus_zero, -10, minus_zero),
- TEST_ff_f (scalb, 0, minus_infty, 0),
- TEST_ff_f (scalb, minus_zero, minus_infty, minus_zero),
-
- TEST_ff_f (scalb, plus_infty, -1, plus_infty),
- TEST_ff_f (scalb, minus_infty, -10, minus_infty),
- TEST_ff_f (scalb, plus_infty, 0, plus_infty),
- TEST_ff_f (scalb, minus_infty, 0, minus_infty),
- TEST_ff_f (scalb, plus_infty, 2, plus_infty),
- TEST_ff_f (scalb, minus_infty, 100, minus_infty),
-
- TEST_ff_f (scalb, 0.1L, minus_infty, 0.0),
- TEST_ff_f (scalb, -0.1L, minus_infty, minus_zero),
-
- TEST_ff_f (scalb, 1, plus_infty, plus_infty),
- TEST_ff_f (scalb, -1, plus_infty, minus_infty),
- TEST_ff_f (scalb, plus_infty, plus_infty, plus_infty),
- TEST_ff_f (scalb, minus_infty, plus_infty, minus_infty),
-
- TEST_ff_f (scalb, plus_infty, minus_infty, qnan_value, INVALID_EXCEPTION),
- TEST_ff_f (scalb, minus_infty, minus_infty, qnan_value, INVALID_EXCEPTION),
-
- TEST_ff_f (scalb, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
- TEST_ff_f (scalb, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-
- TEST_ff_f (scalb, max_value, max_value, plus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, max_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, 1, max_value, plus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, 1, -max_value, plus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, min_value, max_value, plus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, min_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, min_subnorm_value, max_value, plus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, min_subnorm_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -max_value, max_value, minus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -max_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -1, max_value, minus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -1, -max_value, minus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -min_value, max_value, minus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -min_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -min_subnorm_value, max_value, minus_oflow, OVERFLOW_EXCEPTION),
- TEST_ff_f (scalb, -min_subnorm_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION),
-
- TEST_ff_f (scalb, 0.8L, 4, 12.8L),
- TEST_ff_f (scalb, -0.854375L, 5, -27.34L),
+ TEST_ff_f (scalb, 2.0, 0.5, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+ TEST_ff_f (scalb, 3.0, -2.5, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+
+ TEST_ff_f (scalb, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, 1, 0, 1, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, -1, 0, -1, ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, 0, plus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+ TEST_ff_f (scalb, minus_zero, plus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+
+ TEST_ff_f (scalb, 0, 2, 0, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_zero, -4, minus_zero, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 0, 0, 0, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_zero, 0, minus_zero, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 0, -1, 0, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_zero, -10, minus_zero, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 0, minus_infty, 0, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_zero, minus_infty, minus_zero, ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, plus_infty, -1, plus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_infty, -10, minus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, plus_infty, 0, plus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_infty, 0, minus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, plus_infty, 2, plus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_infty, 100, minus_infty, ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, 0.1L, minus_infty, 0.0, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, -0.1L, minus_infty, minus_zero, ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, 1, plus_infty, plus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, -1, plus_infty, minus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, plus_infty, plus_infty, plus_infty, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, minus_infty, plus_infty, minus_infty, ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, plus_infty, minus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+ TEST_ff_f (scalb, minus_infty, minus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+
+ TEST_ff_f (scalb, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, qnan_value, 0.5, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 0.5, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+ TEST_ff_f (scalb, max_value, max_value, plus_oflow, OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
+ TEST_ff_f (scalb, max_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW),
+ TEST_ff_f (scalb, 1, max_value, plus_oflow, OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
+ TEST_ff_f (scalb, 1, -max_value, plus_uflow, UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW),
+ TEST_ff_f (scalb, min_value, max_value, plus_oflow, OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
+ TEST_ff_f (scalb, min_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW),
+ TEST_ff_f (scalb, min_subnorm_value, max_value, plus_oflow, OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW),
+ TEST_ff_f (scalb, min_subnorm_value, -max_value, plus_uflow, UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW),
+ TEST_ff_f (scalb, -max_value, max_value, minus_oflow, OVERFLOW_EXCEPTION|ERRNO_MINUS_OFLOW),
+ TEST_ff_f (scalb, -max_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION|ERRNO_MINUS_UFLOW),
+ TEST_ff_f (scalb, -1, max_value, minus_oflow, OVERFLOW_EXCEPTION|ERRNO_MINUS_OFLOW),
+ TEST_ff_f (scalb, -1, -max_value, minus_uflow, UNDERFLOW_EXCEPTION|ERRNO_MINUS_UFLOW),
+ TEST_ff_f (scalb, -min_value, max_value, minus_oflow, OVERFLOW_EXCEPTION|ERRNO_MINUS_OFLOW),
+ TEST_ff_f (scalb, -min_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION|ERRNO_MINUS_UFLOW),
+ TEST_ff_f (scalb, -min_subnorm_value, max_value, minus_oflow, OVERFLOW_EXCEPTION|ERRNO_MINUS_OFLOW),
+ TEST_ff_f (scalb, -min_subnorm_value, -max_value, minus_uflow, UNDERFLOW_EXCEPTION|ERRNO_MINUS_UFLOW),
+
+ TEST_ff_f (scalb, 0.8L, 4, 12.8L, ERRNO_UNCHANGED),
+ TEST_ff_f (scalb, -0.854375L, 5, -27.34L, ERRNO_UNCHANGED),
};
static void
diff --git a/math/w_scalb.c b/math/w_scalb.c
index dbfefaf9d5..0f1e2df8ef 100644
--- a/math/w_scalb.c
+++ b/math/w_scalb.c
@@ -45,9 +45,33 @@ sysv_scalb (double x, double fn)
double
__scalb (double x, double fn)
{
- return (__builtin_expect (_LIB_VERSION == _SVID_, 0)
- ? sysv_scalb (x, fn)
- : __ieee754_scalb (x, fn));
+ if (__glibc_unlikely (_LIB_VERSION == _SVID_))
+ return sysv_scalb (x, fn);
+ else
+ {
+ double z = __ieee754_scalb (x, fn);
+
+ if (__glibc_unlikely (!__finite (z) || z == 0.0))
+ {
+ if (__isnan (z))
+ {
+ if (!__isnan (x) && !__isnan (fn))
+ __set_errno (EDOM);
+ }
+ else if (__isinf_ns (z))
+ {
+ if (!__isinf_ns (x) && !__isinf_ns (fn))
+ __set_errno (ERANGE);
+ }
+ else
+ {
+ /* z == 0. */
+ if (x != 0.0 && !__isinf_ns (fn))
+ __set_errno (ERANGE);
+ }
+ }
+ return z;
+ }
}
weak_alias (__scalb, scalb)
#ifdef NO_LONG_DOUBLE
diff --git a/math/w_scalbf.c b/math/w_scalbf.c
index 244fd1e91b..7ab0b8a4ac 100644
--- a/math/w_scalbf.c
+++ b/math/w_scalbf.c
@@ -45,8 +45,32 @@ sysv_scalbf (float x, float fn)
float
__scalbf (float x, float fn)
{
- return (__builtin_expect (_LIB_VERSION == _SVID_, 0)
- ? sysv_scalbf (x, fn)
- : __ieee754_scalbf (x, fn));
+ if (__glibc_unlikely (_LIB_VERSION == _SVID_))
+ return sysv_scalbf (x, fn);
+ else
+ {
+ float z = __ieee754_scalbf (x, fn);
+
+ if (__glibc_unlikely (!__finitef (z) || z == 0.0f))
+ {
+ if (__isnanf (z))
+ {
+ if (!__isnanf (x) && !__isnanf (fn))
+ __set_errno (EDOM);
+ }
+ else if (__isinf_nsf (z))
+ {
+ if (!__isinf_nsf (x) && !__isinf_nsf (fn))
+ __set_errno (ERANGE);
+ }
+ else
+ {
+ /* z == 0. */
+ if (x != 0.0f && !__isinf_nsf (fn))
+ __set_errno (ERANGE);
+ }
+ }
+ return z;
+ }
}
weak_alias (__scalbf, scalbf)
diff --git a/math/w_scalbl.c b/math/w_scalbl.c
index cffaa67cc7..40cc68e865 100644
--- a/math/w_scalbl.c
+++ b/math/w_scalbl.c
@@ -45,8 +45,32 @@ sysv_scalbl (long double x, long double fn)
long double
__scalbl (long double x, long double fn)
{
- return (__builtin_expect (_LIB_VERSION == _SVID_, 0)
- ? sysv_scalbl (x, fn)
- : __ieee754_scalbl (x, fn));
+ if (__glibc_unlikely (_LIB_VERSION == _SVID_))
+ return sysv_scalbl (x, fn);
+ else
+ {
+ long double z = __ieee754_scalbl (x, fn);
+
+ if (__glibc_unlikely (!__finitel (z) || z == 0.0L))
+ {
+ if (__isnanl (z))
+ {
+ if (!__isnanl (x) && !__isnanl (fn))
+ __set_errno (EDOM);
+ }
+ else if (__isinf_nsl (z))
+ {
+ if (!__isinf_nsl (x) && !__isinf_nsl (fn))
+ __set_errno (ERANGE);
+ }
+ else
+ {
+ /* z == 0. */
+ if (x != 0.0L && !__isinf_nsl (fn))
+ __set_errno (ERANGE);
+ }
+ }
+ return z;
+ }
}
weak_alias (__scalbl, scalbl)