diff options
Diffstat (limited to 'math')
-rw-r--r-- | math/Makefile | 2 | ||||
-rw-r--r-- | math/Versions | 2 | ||||
-rw-r--r-- | math/bits/mathcalls.h | 3 | ||||
-rw-r--r-- | math/libm-test.inc | 61 | ||||
-rw-r--r-- | math/math.h | 18 | ||||
-rw-r--r-- | math/s_iseqsig_template.c | 42 |
6 files changed, 125 insertions, 3 deletions
diff --git a/math/Makefile b/math/Makefile index d2b4fd1153..a9f06080f4 100644 --- a/math/Makefile +++ b/math/Makefile @@ -51,7 +51,7 @@ gen-libm-calls = cargF conjF cimagF crealF cabsF s_cacosF \ k_casinhF s_csinhF k_casinhF s_csinhF s_catanhF s_catanF \ s_ctanF s_ctanhF s_cexpF s_clogF s_cprojF s_csqrtF \ s_cpowF s_clog10F s_fdimF s_nextdownF s_fmaxF s_fminF \ - s_nanF + s_nanF s_iseqsigF libm-calls = \ e_acosF e_acoshF e_asinF e_atan2F e_atanhF e_coshF e_expF e_fmodF \ diff --git a/math/Versions b/math/Versions index f702051451..e658a1037c 100644 --- a/math/Versions +++ b/math/Versions @@ -216,6 +216,6 @@ libm { } GLIBC_2.25 { fesetexcept; fetestexceptflag; fegetmode; fesetmode; - __iscanonicall; + __iscanonicall; __iseqsigf; __iseqsig; __iseqsigl; } } diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h index 951a3d0090..4fc18659f8 100644 --- a/math/bits/mathcalls.h +++ b/math/bits/mathcalls.h @@ -380,6 +380,9 @@ __END_NAMESPACE_C99 #endif #if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Test equality. */ +__MATHDECL_1 (int, __iseqsig,, (_Mdouble_ __x, _Mdouble_ __y)); + /* Test for signaling NaN. */ __MATHDECL_1 (int, __issignaling,, (_Mdouble_ __value)) __attribute__ ((__const__)); diff --git a/math/libm-test.inc b/math/libm-test.inc index cbc7226aea..4573482f65 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -47,7 +47,7 @@ fabs, fdim, finite, floor, fma, fmax, fmin, fmod, fpclassify, frexp, gamma, hypot, ilogb, iscanonical, isfinite, isinf, isnan, isnormal, issignaling, - issubnormal, iszero, isless, islessequal, isgreater, + issubnormal, iszero, iseqsig, isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered, j0, j1, jn, ldexp, lgamma, log, log10, log1p, log2, logb, modf, nearbyint, nextafter, nexttoward, @@ -8185,6 +8185,64 @@ iscanonical_test (void) ALL_RM_TEST (iscanonical, 1, iscanonical_test_data, RUN_TEST_LOOP_f_b_tg, END); } +static const struct test_ff_i_data iseqsig_test_data[] = + { + TEST_ff_i (iseqsig, minus_zero, minus_zero, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, minus_zero, plus_zero, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, minus_zero, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, minus_zero, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, minus_zero, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, minus_zero, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, minus_zero, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, plus_zero, minus_zero, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, plus_zero, plus_zero, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, plus_zero, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, plus_zero, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, plus_zero, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, plus_zero, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, plus_zero, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, (FLOAT) 1, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, (FLOAT) 1, plus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, (FLOAT) 1, (FLOAT) 1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_i (iseqsig, (FLOAT) 1, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, (FLOAT) 1, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, (FLOAT) 1, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, (FLOAT) 1, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, minus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, minus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, plus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, plus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, minus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, minus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, plus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, plus_zero, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, (FLOAT) 1, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, -qnan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, qnan_value, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -qnan_value, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, snan_value, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + TEST_ff_i (iseqsig, -snan_value, -snan_value, 0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM), + }; + +static void +iseqsig_test (void) +{ + ALL_RM_TEST (iseqsig, 1, iseqsig_test_data, RUN_TEST_LOOP_ff_i_tg, END); +} static const struct test_f_i_data isfinite_test_data[] = { TEST_f_b (isfinite, 0, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -12834,6 +12892,7 @@ main (int argc, char **argv) fma_test (); /* Comparison macros: */ + iseqsig_test (); isgreater_test (); isgreaterequal_test (); isless_test (); diff --git a/math/math.h b/math/math.h index 8cd641688d..394cefae02 100644 --- a/math/math.h +++ b/math/math.h @@ -531,6 +531,24 @@ extern int matherr (struct exception *__exc); #endif +#if __GLIBC_USE (IEC_60559_BFP_EXT) +/* Return X == Y but raising "invalid" and setting errno if X or Y is + a NaN. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define iseqsig(x, y) \ + (sizeof ((x) + (y)) == sizeof (float) \ + ? __iseqsigf ((x), (y)) \ + : __iseqsig ((x), (y))) +# else +# define iseqsig(x, y) \ + (sizeof ((x) + (y)) == sizeof (float) \ + ? __iseqsigf ((x), (y)) \ + : sizeof ((x) + (y)) == sizeof (double) \ + ? __iseqsig ((x), (y)) \ + : __iseqsigl ((x), (y))) +# endif +#endif + __END_DECLS diff --git a/math/s_iseqsig_template.c b/math/s_iseqsig_template.c new file mode 100644 index 0000000000..ebdae6493c --- /dev/null +++ b/math/s_iseqsig_template.c @@ -0,0 +1,42 @@ +/* Test whether X == Y. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <fenv.h> +#include <math.h> +#include <stdbool.h> +#include <fix-fp-int-compare-invalid.h> + +int +M_DECL_FUNC (__iseqsig) (FLOAT x, FLOAT y) +{ + /* Comparing <= and >= is sufficient to determine both whether X and + Y are equal, and whether they are unordered, while raising the + "invalid" exception if they are unordered. */ + bool cmp1 = x <= y; + bool cmp2 = x >= y; + if (cmp1 && cmp2) + return 1; + else if (!cmp1 && !cmp2) + { + if (FIX_COMPARE_INVALID) + feraiseexcept (FE_INVALID); + __set_errno (EDOM); + } + return 0; +} |