]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - math/libm-test-driver.c
math: Improve fmodf
[thirdparty/glibc.git] / math / libm-test-driver.c
index b7c0343062816764f27d286e24b78ce0eb56279e..db8c0198cb1ba9a69c8c24c79b58ea498ac672ac 100644 (file)
@@ -1,5 +1,5 @@
 /* Support code for testing libm functions (driver).
-   Copyright (C) 1997-2018 Free Software Foundation, Inc.
+   Copyright (C) 1997-2023 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
@@ -14,7 +14,7 @@
 
    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/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
 #include "libm-test-support.h"
 
 /* Flags set by the including file.  */
 const int flag_test_errno = TEST_ERRNO;
 const int flag_test_exceptions = TEST_EXCEPTIONS;
-const int flag_test_finite = TEST_FINITE;
-const int flag_test_inline = TEST_INLINE;
 const int flag_test_mathvec = TEST_MATHVEC;
 
+#if TEST_NARROW
+const int snan_tests_arg = SNAN_TESTS (ARG_FLOAT);
+#else
+const int snan_tests_arg = SNAN_TESTS (FLOAT);
+#endif
+
 #define STRX(x) #x
 #define STR(x) STRX (x)
 #define STR_FLOAT STR (FLOAT)
+#define STR_ARG_FLOAT STR (ARG_FLOAT)
 #define STR_VEC_LEN STR (VEC_LEN)
 
 /* Informal description of the functions being tested.  */
 #if TEST_MATHVEC
 # define TEST_MSG "testing " STR_FLOAT " (vector length " STR_VEC_LEN ")\n"
-#elif TEST_INLINE
-# define TEST_MSG "testing " STR_FLOAT " (inline functions)\n"
-#elif TEST_FINITE
-# define TEST_MSG "testing " STR_FLOAT " (finite-math-only)\n"
+#elif TEST_NARROW
+# define TEST_MSG "testing " STR_FLOAT " (argument " STR_ARG_FLOAT ")\n"
 #else
 # define TEST_MSG "testing " STR_FLOAT " (without inline functions)\n"
 #endif
@@ -64,11 +67,7 @@ const char test_msg[] = TEST_MSG;
                                         ? TEST_NAN_PAYLOAD             \
                                         : 0)
 
-#if TEST_INLINE
-const char qtype_str[] = "i" TYPE_STR;
-#else
 const char qtype_str[] = TYPE_STR;
-#endif
 
 /* Various constants derived from pi.  We must supply them precalculated for
    accuracy.  They are written as a series of postfix operations to keep
@@ -108,9 +107,31 @@ const char qtype_str[] = TYPE_STR;
 #define min_value      TYPE_MIN
 #define min_subnorm_value TYPE_TRUE_MIN
 
+#define arg_plus_zero  ARG_LIT (0.0)
+#define arg_minus_zero ARG_LIT (-0.0)
+#define arg_plus_infty ARG_FUNC (__builtin_inf) ()
+#define arg_minus_infty        -(ARG_FUNC (__builtin_inf) ())
+#define arg_qnan_value_pl(S)   ARG_FUNC (__builtin_nan) (S)
+#define arg_qnan_value arg_qnan_value_pl ("")
+#define arg_snan_value_pl(S)   ARG_FUNC (__builtin_nans) (S)
+#define arg_snan_value arg_snan_value_pl ("")
+#define arg_max_value  ARG_TYPE_MAX
+#define arg_min_value  ARG_TYPE_MIN
+#define arg_min_subnorm_value ARG_TYPE_TRUE_MIN
+
 /* For nexttoward tests.  */
 #define snan_value_ld  __builtin_nansl ("")
 
+/* For pseudo-normal number tests.  */
+#if TEST_COND_intel96
+# include <math_ldbl.h>
+#define pseudo_inf { .parts = { 0x00000000, 0x00000000, 0x7fff }}
+#define pseudo_zero { .parts = { 0x00000000, 0x00000000, 0x0100 }}
+#define pseudo_qnan { .parts = { 0x00000001, 0x00000000, 0x7fff }}
+#define pseudo_snan { .parts = { 0x00000001, 0x40000000, 0x7fff }}
+#define pseudo_unnormal { .parts = { 0x00000001, 0x40000000, 0x0100 }}
+#endif
+
 /* Structures for each kind of test.  */
 /* Used for both RUN_TEST_LOOP_f_f and RUN_TEST_LOOP_fp_f.  */
 struct test_f_f_data
@@ -133,7 +154,7 @@ struct test_ff_f_data
     int exceptions;
   } rd, rn, rz, ru;
 };
-/* Strictly speaking, a j type argument is one gen-libm-test.pl will not
+/* Strictly speaking, a j type argument is one gen-libm-test.py will not
    attempt to muck with.  For now, it is only used to prevent it from
    mucking up an explicitly long double argument.  */
 struct test_fj_f_data
@@ -147,6 +168,38 @@ struct test_fj_f_data
     int exceptions;
   } rd, rn, rz, ru;
 };
+#ifdef ARG_FLOAT
+struct test_a_f_data
+{
+  const char *arg_str;
+  ARG_FLOAT arg;
+  struct
+  {
+    FLOAT expected;
+    int exceptions;
+  } rd, rn, rz, ru;
+};
+struct test_aa_f_data
+{
+  const char *arg_str;
+  ARG_FLOAT arg1, arg2;
+  struct
+  {
+    FLOAT expected;
+    int exceptions;
+  } rd, rn, rz, ru;
+};
+struct test_aaa_f_data
+{
+  const char *arg_str;
+  ARG_FLOAT arg1, arg2, arg3;
+  struct
+  {
+    FLOAT expected;
+    int exceptions;
+  } rd, rn, rz, ru;
+};
+#endif
 struct test_fi_f_data
 {
   const char *arg_str;
@@ -293,7 +346,21 @@ struct test_f_i_data
     int exceptions;
   } rd, rn, rz, ru;
 };
-/* Used for both RUN_TEST_LOOP_ff_b and RUN_TEST_LOOP_ff_i_tg.  */
+/* Used for RUN_TEST_LOOP_f_i_tg_u and RUN_TEST_LOOP_f_b_tg_u.  */
+#if TEST_COND_intel96
+struct test_j_i_data_u
+{
+  const char *arg_str;
+  ieee_long_double_shape_type arg;
+  struct
+  {
+    int expected;
+    int exceptions;
+  } rd, rn, rz, ru;
+};
+#endif
+/* Used for RUN_TEST_LOOP_ff_b, RUN_TEST_LOOP_fpfp_b and
+   RUN_TEST_LOOP_ff_i_tg.  */
 struct test_ff_i_data
 {
   const char *arg_str;
@@ -356,6 +423,7 @@ struct test_Ff_b1_data
 #define IF_ROUND_INIT_FE_DOWNWARD              \
   int save_round_mode = fegetround ();         \
   if (ROUNDING_TESTS (FLOAT, FE_DOWNWARD)      \
+      && !TEST_MATHVEC                         \
       && fesetround (FE_DOWNWARD) == 0)
 #define IF_ROUND_INIT_FE_TONEAREST             \
   int save_round_mode = fegetround ();         \
@@ -364,10 +432,12 @@ struct test_Ff_b1_data
 #define IF_ROUND_INIT_FE_TOWARDZERO            \
   int save_round_mode = fegetround ();         \
   if (ROUNDING_TESTS (FLOAT, FE_TOWARDZERO)    \
+      && !TEST_MATHVEC                         \
       && fesetround (FE_TOWARDZERO) == 0)
 #define IF_ROUND_INIT_FE_UPWARD                        \
   int save_round_mode = fegetround ();         \
   if (ROUNDING_TESTS (FLOAT, FE_UPWARD)                \
+      && !TEST_MATHVEC                         \
       && fesetround (FE_UPWARD) == 0)
 #define ROUND_RESTORE_ /* Empty.  */
 #define ROUND_RESTORE_FE_DOWNWARD              \
@@ -409,7 +479,7 @@ struct test_Ff_b1_data
 
 /* Run an individual test, including any required setup and checking
    of results, or loop over all tests in an array.  */
-#define RUN_TEST_f_f(ARG_STR, FUNC_NAME, ARG, EXPECTED,                        \
+#define RUN_TEST_1_f(ARG_STR, FUNC_NAME, ARG, EXPECTED,                        \
                     EXCEPTIONS)                                        \
   do                                                                   \
     if (enable_test (EXCEPTIONS))                                      \
@@ -420,13 +490,15 @@ struct test_Ff_b1_data
        COMMON_TEST_CLEANUP;                                            \
       }                                                                        \
   while (0)
-#define RUN_TEST_LOOP_f_f(FUNC_NAME, ARRAY, ROUNDING_MODE)             \
+#define RUN_TEST_LOOP_1_f(FUNC_NAME, ARRAY, ROUNDING_MODE)             \
   IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
     for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)    \
-      RUN_TEST_f_f ((ARRAY)[i].arg_str, FUNC_NAME, (ARRAY)[i].arg,     \
+      RUN_TEST_1_f ((ARRAY)[i].arg_str, FUNC_NAME, (ARRAY)[i].arg,     \
                    (ARRAY)[i].RM_##ROUNDING_MODE.expected,             \
                    (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);          \
   ROUND_RESTORE_ ## ROUNDING_MODE
+#define RUN_TEST_LOOP_f_f RUN_TEST_LOOP_1_f
+#define RUN_TEST_LOOP_a_f RUN_TEST_LOOP_1_f
 #define RUN_TEST_fp_f(ARG_STR, FUNC_NAME, ARG, EXPECTED,               \
                     EXCEPTIONS)                                        \
   do                                                                   \
@@ -467,14 +539,15 @@ struct test_Ff_b1_data
 #define RUN_TEST_ff_f RUN_TEST_2_f
 #define RUN_TEST_LOOP_ff_f RUN_TEST_LOOP_2_f
 #define RUN_TEST_LOOP_fj_f RUN_TEST_LOOP_2_f
+#define RUN_TEST_LOOP_aa_f RUN_TEST_LOOP_2_f
 #define RUN_TEST_fi_f RUN_TEST_2_f
 #define RUN_TEST_LOOP_fi_f RUN_TEST_LOOP_2_f
 #define RUN_TEST_fl_f RUN_TEST_2_f
 #define RUN_TEST_LOOP_fl_f RUN_TEST_LOOP_2_f
 #define RUN_TEST_if_f RUN_TEST_2_f
 #define RUN_TEST_LOOP_if_f RUN_TEST_LOOP_2_f
-#define RUN_TEST_fff_f(ARG_STR, FUNC_NAME, ARG1, ARG2, ARG3,           \
-                      EXPECTED, EXCEPTIONS)                            \
+#define RUN_TEST_3_f(ARG_STR, FUNC_NAME, ARG1, ARG2, ARG3,             \
+                    EXPECTED, EXCEPTIONS)                              \
   do                                                                   \
     if (enable_test (EXCEPTIONS))                                      \
       {                                                                        \
@@ -484,14 +557,16 @@ struct test_Ff_b1_data
        COMMON_TEST_CLEANUP;                                            \
       }                                                                        \
   while (0)
-#define RUN_TEST_LOOP_fff_f(FUNC_NAME, ARRAY, ROUNDING_MODE)           \
+#define RUN_TEST_LOOP_3_f(FUNC_NAME, ARRAY, ROUNDING_MODE)             \
   IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
     for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)    \
-      RUN_TEST_fff_f ((ARRAY)[i].arg_str, FUNC_NAME, (ARRAY)[i].arg1,  \
-                     (ARRAY)[i].arg2, (ARRAY)[i].arg3,                 \
-                     (ARRAY)[i].RM_##ROUNDING_MODE.expected,           \
-                     (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);        \
+      RUN_TEST_3_f ((ARRAY)[i].arg_str, FUNC_NAME, (ARRAY)[i].arg1,    \
+                   (ARRAY)[i].arg2, (ARRAY)[i].arg3,                   \
+                   (ARRAY)[i].RM_##ROUNDING_MODE.expected,             \
+                   (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);          \
   ROUND_RESTORE_ ## ROUNDING_MODE
+#define RUN_TEST_LOOP_fff_f RUN_TEST_LOOP_3_f
+#define RUN_TEST_LOOP_aaa_f RUN_TEST_LOOP_3_f
 #define RUN_TEST_fiu_M(ARG_STR, FUNC_NAME, ARG1, ARG2, ARG3,           \
                       EXPECTED, EXCEPTIONS)                            \
   do                                                                   \
@@ -804,6 +879,22 @@ struct test_Ff_b1_data
                       (ARRAY)[i].RM_##ROUNDING_MODE.expected,          \
                       (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);       \
   ROUND_RESTORE_ ## ROUNDING_MODE
+#define RUN_TEST_LOOP_j_b_tg_u(FUNC_NAME, ARRAY, ROUNDING_MODE)                \
+  IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
+  for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)      \
+  RUN_TEST_f_b_tg ((ARRAY)[i].arg_str, FUNC_NAME,                      \
+                  (FLOAT)(ARRAY)[i].arg.value,                         \
+                  (ARRAY)[i].RM_##ROUNDING_MODE.expected,              \
+                  (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);           \
+  ROUND_RESTORE_ ## ROUNDING_MODE
+#define RUN_TEST_LOOP_j_i_tg_u(FUNC_NAME, ARRAY, ROUNDING_MODE)                \
+  IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
+  for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)      \
+  RUN_TEST_f_i_tg ((ARRAY)[i].arg_str, FUNC_NAME,                      \
+                  (FLOAT)(ARRAY)[i].arg.value,                         \
+                  (ARRAY)[i].RM_##ROUNDING_MODE.expected,              \
+                  (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);           \
+  ROUND_RESTORE_ ## ROUNDING_MODE
 #define RUN_TEST_ff_b(ARG_STR, FUNC_NAME, ARG1, ARG2, EXPECTED,                \
                      EXCEPTIONS)                                       \
   do                                                                   \
@@ -823,6 +914,26 @@ struct test_Ff_b1_data
                     (ARRAY)[i].RM_##ROUNDING_MODE.expected,            \
                     (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);         \
   ROUND_RESTORE_ ## ROUNDING_MODE
+#define RUN_TEST_fpfp_b(ARG_STR, FUNC_NAME, ARG1, ARG2, EXPECTED,      \
+                       EXCEPTIONS)                                     \
+  do                                                                   \
+    if (enable_test (EXCEPTIONS))                                      \
+      {                                                                        \
+       COMMON_TEST_SETUP (ARG_STR);                                    \
+       check_bool (test_name,                                          \
+                   FUNC_TEST (FUNC_NAME) (&(ARG1), &(ARG2)),           \
+                   EXPECTED, EXCEPTIONS);                              \
+       COMMON_TEST_CLEANUP;                                            \
+      }                                                                        \
+  while (0)
+#define RUN_TEST_LOOP_fpfp_b(FUNC_NAME, ARRAY, ROUNDING_MODE)          \
+  IF_ROUND_INIT_ ## ROUNDING_MODE                                      \
+    for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++)    \
+      RUN_TEST_fpfp_b ((ARRAY)[i].arg_str, FUNC_NAME,                  \
+                      (ARRAY)[i].arg1, (ARRAY)[i].arg2,                \
+                      (ARRAY)[i].RM_##ROUNDING_MODE.expected,          \
+                      (ARRAY)[i].RM_##ROUNDING_MODE.exceptions);       \
+  ROUND_RESTORE_ ## ROUNDING_MODE
 #define RUN_TEST_ff_i_tg(ARG_STR, FUNC_NAME, ARG1, ARG2, EXPECTED,     \
                         EXCEPTIONS)                                    \
   do                                                                   \
@@ -945,18 +1056,32 @@ struct test_Ff_b1_data
                       (ARRAY)[i].RM_##ROUNDING_MODE.extra2_expected);  \
   ROUND_RESTORE_ ## ROUNDING_MODE
 
-#if !TEST_MATHVEC
-# define VEC_SUFF
+#if TEST_MATHVEC
+# define TEST_SUFF VEC_SUFF
+# define TEST_SUFF_STR
+#elif TEST_NARROW
+# define TEST_SUFF
+# define TEST_SUFF_STR "_" ARG_TYPE_STR
+#else
+# define TEST_SUFF
+# define TEST_SUFF_STR
 #endif
 
 #define STR_CONCAT(a, b, c) __STRING (a##b##c)
 #define STR_CON3(a, b, c) STR_CONCAT (a, b, c)
 
+#if TEST_NARROW
+# define TEST_COND_any_ibm128 (TEST_COND_ibm128 || TEST_COND_arg_ibm128)
+#else
+# define TEST_COND_any_ibm128 TEST_COND_ibm128
+#endif
+
 /* Start and end the tests for a given function.  */
 #define START(FUN, SUFF, EXACT)                                        \
   CHECK_ARCH_EXT;                                              \
-  const char *this_func = STR_CON3 (FUN, SUFF, VEC_SUFF);      \
-  init_max_error (this_func, EXACT)
+  const char *this_func                                                \
+    = STR_CON3 (FUN, SUFF, TEST_SUFF) TEST_SUFF_STR;           \
+  init_max_error (this_func, EXACT, TEST_COND_any_ibm128)
 #define END                                    \
   print_max_error (this_func)
 #define END_COMPLEX                            \