@@ -184,31 +184,77 @@ struct ulp_data
#define IGNORE_RESULT 0x20000
#define NON_FINITE 0x40000
+#define MANT_DIG (TYPE_MANT_DIG - 1)
+#define MIN_EXP (TYPE_MIN_EXP - 1)
+#define MAX_EXP (TYPE_MAX_EXP - 1)
+
+/* Maximum character buffer to store a stringitized FLOAT value. */
+# define FSTR_MAX (128)
+
+#if TEST_INLINE
+# define TYPESTR "i" TYPE_STR
+#else
+# define TYPESTR TYPE_STR
+#endif
+
+/* Format specific test macros. */
+#define TEST_COND_binary32 (TYPE_MANT_DIG == 24 \
+ && TYPE_MIN_EXP == -125 \
+ && TYPE_MAX_EXP == 128)
+
+#define TEST_COND_binary64 (TYPE_MANT_DIG == 53 \
+ && TYPE_MIN_EXP == -1021 \
+ && TYPE_MAX_EXP == 1024)
+
+#define TEST_COND_binary128 (TYPE_MANT_DIG == 113 \
+ && TYPE_MIN_EXP == -16381 \
+ && TYPE_MAX_EXP == 16384)
+
+#define TEST_COND_ibm128 (TYPE_MANT_DIG == 106)
+
+#define TEST_COND_intel96 (TYPE_MANT_DIG == 64 \
+ && TYPE_MIN_EXP == -16381 \
+ && TYPE_MAX_EXP == 16384)
+
+#define TEST_COND_m68k96 (TYPE_MANT_DIG == 64 \
+ && TYPE_MIN_EXP == -16382 \
+ && TYPE_MAX_EXP == 16384)
+
+/* This is a standin replacement for the usage of TEST_LDOUBLE
+ to enable certain tests for the format/type. Instead, we
+ enable them if some trait of the format is more expressive
+ than the binary64 format. */
+#define TEST_COND_gt_binary64 (TYPE_MANT_DIG > 53 \
+ || TYPE_MIN_EXP < -1021 \
+ || TYPE_MAX_EXP > 1024 )
+
/* Values underflowing only for float. */
-#ifdef TEST_FLOAT
+#if TEST_COND_binary32
# define UNDERFLOW_EXCEPTION_FLOAT UNDERFLOW_EXCEPTION
# define UNDERFLOW_EXCEPTION_OK_FLOAT UNDERFLOW_EXCEPTION_OK
#else
# define UNDERFLOW_EXCEPTION_FLOAT 0
# define UNDERFLOW_EXCEPTION_OK_FLOAT 0
#endif
+
/* Values underflowing only for double or types with a larger least
positive normal value. */
-#if defined TEST_FLOAT || defined TEST_DOUBLE \
- || (defined TEST_LDOUBLE && LDBL_MIN_EXP >= DBL_MIN_EXP)
+#if TEST_COND_binary32 || TEST_COND_binary64 || TEST_COND_ibm128
# define UNDERFLOW_EXCEPTION_DOUBLE UNDERFLOW_EXCEPTION
# define UNDERFLOW_EXCEPTION_OK_DOUBLE UNDERFLOW_EXCEPTION_OK
#else
# define UNDERFLOW_EXCEPTION_DOUBLE 0
# define UNDERFLOW_EXCEPTION_OK_DOUBLE 0
#endif
+
/* Values underflowing only for IBM long double or types with a larger least
positive normal value. */
-#if defined TEST_FLOAT || (defined TEST_LDOUBLE && LDBL_MIN_EXP > DBL_MIN_EXP)
+#if TEST_COND_binary32 || TEST_COND_ibm128
# define UNDERFLOW_EXCEPTION_LDOUBLE_IBM UNDERFLOW_EXCEPTION
#else
# define UNDERFLOW_EXCEPTION_LDOUBLE_IBM 0
#endif
+
/* Values underflowing on architectures detecting tininess before
rounding, but not on those detecting tininess after rounding. */
#define UNDERFLOW_EXCEPTION_BEFORE_ROUNDING (TININESS_AFTER_ROUNDING \
@@ -228,36 +274,13 @@ struct ulp_data
#endif
/* Conditions used by tests generated by gen-auto-libm-tests.c. */
-#ifdef TEST_FLOAT
-# define TEST_COND_flt_32 1
-#else
-# define TEST_COND_flt_32 0
-#endif
-#if defined TEST_DOUBLE || (defined TEST_LDOUBLE && LDBL_MANT_DIG == 53)
-# define TEST_COND_dbl_64 1
-#else
-# define TEST_COND_dbl_64 0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 64 && LDBL_MIN_EXP == -16381
-# define TEST_COND_ldbl_96_intel 1
-#else
-# define TEST_COND_ldbl_96_intel 0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 64 && LDBL_MIN_EXP == -16382
-# define TEST_COND_ldbl_96_m68k 1
-#else
-# define TEST_COND_ldbl_96_m68k 0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 113
-# define TEST_COND_ldbl_128 1
-#else
-# define TEST_COND_ldbl_128 0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 106
-# define TEST_COND_ldbl_128ibm 1
-#else
-# define TEST_COND_ldbl_128ibm 0
-#endif
+#define TEST_COND_flt_32 TEST_COND_binary32
+#define TEST_COND_dbl_64 TEST_COND_binary64
+#define TEST_COND_ldbl_96_intel TEST_COND_intel96
+#define TEST_COND_ldbl_96_m68k TEST_COND_m68k96
+#define TEST_COND_ldbl_128 TEST_COND_binary128
+#define TEST_COND_ldbl_128ibm TEST_COND_ibm128
+
#if LONG_MAX == 0x7fffffff
# define TEST_COND_long32 1
# define TEST_COND_long64 0
@@ -281,12 +304,12 @@ struct ulp_data
#endif
/* Various constants (we must supply them precalculated for accuracy). */
-#define M_PI_6l .52359877559829887307710723054658383L
-#define M_PI_34l 2.356194490192344928846982537459627163L /* 3*pi/4 */
-#define M_PI_34_LOG10El 1.023282265381381010614337719073516828L
-#define M_PI2_LOG10El 0.682188176920920673742891812715677885L
-#define M_PI4_LOG10El 0.341094088460460336871445906357838943L
-#define M_PI_LOG10El 1.364376353841841347485783625431355770L
+#define M_PI_6l LIT (.52359877559829887307710723054658383)
+#define M_PI_34l LIT (2.356194490192344928846982537459627163) /* 3*pi/4 */
+#define M_PI_34_LOG10El LIT (1.023282265381381010614337719073516828)
+#define M_PI2_LOG10El LIT (0.682188176920920673742891812715677885)
+#define M_PI4_LOG10El LIT (0.341094088460460336871445906357838943)
+#define M_PI_LOG10El LIT (1.364376353841841347485783625431355770)
#define ulps_file_name "ULPs" /* Name of the ULPs file. */
static FILE *ulps_file; /* File to document difference. */
@@ -303,25 +326,14 @@ static int output_max_error; /* Should the maximal errors printed? */
static int output_points; /* Should the single function results printed? */
static int ignore_max_ulp; /* Should we ignore max_ulp? */
-#define plus_zero CHOOSE (0.0L, 0.0, 0.0f, \
- 0.0L, 0.0, 0.0f)
-#define minus_zero CHOOSE (-0.0L, -0.0, -0.0f, \
- -0.0L, -0.0, -0.0f)
-#define plus_infty CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF, \
- HUGE_VALL, HUGE_VAL, HUGE_VALF)
-#define minus_infty CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF, \
- -HUGE_VALL, -HUGE_VAL, -HUGE_VALF)
+#define plus_zero LIT (0.0)
+#define minus_zero LIT (-0.0)
+#define plus_infty (TYPE_INF)
+#define minus_infty (-TYPE_INF)
#define qnan_value FUNC (__builtin_nan) ("")
-#define max_value CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX, \
- LDBL_MAX, DBL_MAX, FLT_MAX)
-#define min_value CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN, \
- LDBL_MIN, DBL_MIN, FLT_MIN)
-#define min_subnorm_value CHOOSE (LDBL_TRUE_MIN, \
- DBL_TRUE_MIN, \
- FLT_TRUE_MIN, \
- LDBL_TRUE_MIN, \
- DBL_TRUE_MIN, \
- FLT_TRUE_MIN)
+#define max_value TYPE_MAX
+#define min_value TYPE_MIN
+#define min_subnorm_value TYPE_TRUE_MIN
static FLOAT max_error, real_max_error, imag_max_error;
@@ -329,23 +341,11 @@ static FLOAT prev_max_error, prev_real_max_error, prev_imag_max_error;
static FLOAT max_valid_error;
-#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \
- (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
-#define MIN_EXP CHOOSE ((LDBL_MIN_EXP-1), (DBL_MIN_EXP-1), (FLT_MIN_EXP-1), \
- (LDBL_MIN_EXP-1), (DBL_MIN_EXP-1), (FLT_MIN_EXP-1))
-#define MAX_EXP CHOOSE (LDBL_MAX_EXP, DBL_MAX_EXP, FLT_MAX_EXP, \
- LDBL_MAX_EXP, DBL_MAX_EXP, FLT_MAX_EXP)
/* Sufficient numbers of digits to represent any floating-point value
unambiguously (for any choice of the number of bits in the first
hex digit, in the case of TYPE_HEX_DIG). When used with printf
formats where the precision counts only digits after the point, 1
is subtracted from these values. */
-#define TYPE_DECIMAL_DIG CHOOSE (LDBL_DECIMAL_DIG, \
- DBL_DECIMAL_DIG, \
- FLT_DECIMAL_DIG, \
- LDBL_DECIMAL_DIG, \
- DBL_DECIMAL_DIG, \
- FLT_DECIMAL_DIG)
#define TYPE_HEX_DIG ((MANT_DIG + 7) / 4)
/* Compare KEY (a string, with the name of a function) with ULP (a
@@ -428,8 +428,12 @@ print_float (FLOAT f)
else if (isnan (f))
printf ("qNaN\n");
else
- printf ("% .*" PRINTF_EXPR " % .*" PRINTF_XEXPR "\n",
- TYPE_DECIMAL_DIG - 1, f, TYPE_HEX_DIG - 1, f);
+ {
+ char fstrn[FSTR_MAX], fstrx[FSTR_MAX];
+ FTOSTR (fstrn, FSTR_MAX, "% .*" PRINTF_EXPR, TYPE_DECIMAL_DIG - 1, f);
+ FTOSTR (fstrx, FSTR_MAX, "% .*" PRINTF_XEXPR, TYPE_HEX_DIG - 1, f);
+ printf ("%s %s\n", fstrn, fstrx);
+ }
}
/* Should the message print to screen? This depends on the verbose flag,
@@ -471,11 +475,10 @@ print_function_ulps (const char *function_name, FLOAT ulp)
{
if (output_ulps)
{
+ char ustrn[FSTR_MAX];
+ FTOSTR (ustrn, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (ulp));
fprintf (ulps_file, "Function: \"%s\":\n", function_name);
- fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
- CHOOSE("ldouble", "double", "float",
- "ildouble", "idouble", "ifloat"),
- FUNC(ceil) (ulp));
+ fprintf (ulps_file, TYPESTR ": %s\n", ustrn);
}
}
@@ -486,21 +489,20 @@ print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
{
if (output_ulps)
{
+ char fstrn[FSTR_MAX];
if (real_ulp != 0.0)
{
+ FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (real_ulp));
fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
- fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
- CHOOSE("ldouble", "double", "float",
- "ildouble", "idouble", "ifloat"),
- FUNC(ceil) (real_ulp));
+ fprintf (ulps_file, TYPESTR ": %s\n", fstrn);
}
if (imag_ulp != 0.0)
{
+ FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (imag_ulp));
fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
- fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
- CHOOSE("ldouble", "double", "float",
- "ildouble", "idouble", "ifloat"),
- FUNC(ceil) (imag_ulp));
+ fprintf (ulps_file, TYPESTR ": %s\n", fstrn);
}
@@ -548,10 +550,12 @@ print_max_error (const char *func_name)
if (print_screen_max_error (ok))
{
+ char mestr[FSTR_MAX], pmestr[FSTR_MAX];
+ FTOSTR (mestr, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (max_error));
+ FTOSTR (pmestr, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (prev_max_error));
printf ("Maximal error of `%s'\n", func_name);
- printf (" is : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (max_error));
- printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
- FUNC(ceil) (prev_max_error));
+ printf (" is : %s ulp\n", mestr);
+ printf (" accepted: %s ulp\n", pmestr);
}
update_stats (ok);
@@ -584,16 +588,22 @@ print_complex_max_error (const char *func_name)
if (print_screen_max_error (ok))
{
+ char rmestr[FSTR_MAX], prmestr[FSTR_MAX];
+ char imestr[FSTR_MAX], pimestr[FSTR_MAX];
+ FTOSTR (rmestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (real_max_error));
+ FTOSTR (prmestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (prev_real_max_error));
+ FTOSTR (imestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (imag_max_error));
+ FTOSTR (pimestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+ FUNC (ceil) (prev_imag_max_error));
printf ("Maximal error of real part of: %s\n", func_name);
- printf (" is : %.0" PRINTF_NEXPR " ulp\n",
- FUNC(ceil) (real_max_error));
- printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
- FUNC(ceil) (prev_real_max_error));
+ printf (" is : %s ulp\n", rmestr);
+ printf (" accepted: %s ulp\n", prmestr);
printf ("Maximal error of imaginary part of: %s\n", func_name);
- printf (" is : %.0" PRINTF_NEXPR " ulp\n",
- FUNC(ceil) (imag_max_error));
- printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
- FUNC(ceil) (prev_imag_max_error));
+ printf (" is : %s ulp\n", imestr);
+ printf (" accepted: %s ulp\n", pimestr);
}
update_stats (ok);
@@ -749,7 +759,7 @@ ulp (FLOAT value)
2^(-MANT_DIG) which is too large a value to be useful. Note that we
can't use ilogb(0), since that isn't a valid thing to do. As a point
of comparison Java's ulp returns the next normal value e.g.
- 2^(1 - MAX_EXP) for ulp(0), but that is not what we want for
+ 2^(1 - TYPE_MAX_EXP) for ulp(0), but that is not what we want for
glibc. */
/* Fall through... */
case FP_SUBNORMAL:
@@ -851,10 +861,17 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
print_float (expected);
if (print_diff)
{
- printf (" difference: % .*" PRINTF_EXPR " % .*" PRINTF_XEXPR
- "\n", TYPE_DECIMAL_DIG - 1, diff, TYPE_HEX_DIG - 1, diff);
- printf (" ulp : % .4" PRINTF_NEXPR "\n", ulps);
- printf (" max.ulp : % .4" PRINTF_NEXPR "\n", max_ulp);
+ char dstrn[FSTR_MAX], dstrx[FSTR_MAX];
+ char ustrn[FSTR_MAX], mustrn[FSTR_MAX];
+ FTOSTR (dstrn, FSTR_MAX, "% .*" PRINTF_EXPR,
+ TYPE_DECIMAL_DIG - 1, diff);
+ FTOSTR (dstrx, FSTR_MAX, "% .*" PRINTF_XEXPR,
+ TYPE_HEX_DIG - 1, diff);
+ FTOSTR (ustrn, FSTR_MAX, "% .4" PRINTF_NEXPR, ulps);
+ FTOSTR (mustrn, FSTR_MAX, "% .4" PRINTF_NEXPR, max_ulp);
+ printf (" difference: %s %s\n", dstrn, dstrx);
+ printf (" ulp : %s\n", ustrn);
+ printf (" max.ulp : %s\n", mustrn);
}
}
update_stats (ok);
@@ -7897,8 +7914,8 @@ static const struct test_f_i_data ilogb_test_data[] =
TEST_f_i (ilogb, -min_subnorm_value, MIN_EXP-MANT_DIG, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
TEST_f_i (ilogb, min_value, MIN_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
TEST_f_i (ilogb, -min_value, MIN_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
- TEST_f_i (ilogb, max_value, MAX_EXP-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
- TEST_f_i (ilogb, -max_value, MAX_EXP-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
+ TEST_f_i (ilogb, max_value, MAX_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
+ TEST_f_i (ilogb, -max_value, MAX_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
/* ilogb (0.0) == FP_ILOGB0 plus invalid exception */
TEST_f_i (ilogb, 0.0, FP_ILOGB0, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM),
@@ -9030,8 +9047,8 @@ static const struct test_f_f_data logb_test_data[] =
TEST_f_f (logb, -min_subnorm_value, MIN_EXP-MANT_DIG, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
TEST_f_f (logb, min_value, MIN_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
TEST_f_f (logb, -min_value, MIN_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
- TEST_f_f (logb, max_value, MAX_EXP-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
- TEST_f_f (logb, -max_value, MAX_EXP-1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
+ TEST_f_f (logb, max_value, MAX_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
+ TEST_f_f (logb, -max_value, MAX_EXP, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED);
TEST_f_f (logb, 0x0.1p-127, -131, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_f (logb, 0x0.01p-127, -135, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@@ -16,6 +16,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <float.h>
+
#define FUNC(function) function
#define FLOAT double
#define PRINTF_EXPR "e"
@@ -23,3 +25,15 @@
#define PRINTF_NEXPR "f"
#define TEST_DOUBLE 1
#define BUILD_COMPLEX(real, imag) (CMPLX ((real), (imag)))
+
+#define LIT(x) (x)
+#define FTOSTR snprintf
+#define TYPE_STR "double"
+#define TYPE_DECIMAL_DIG DBL_DECIMAL_DIG
+#define TYPE_MIN DBL_MIN
+#define TYPE_TRUE_MIN DBL_TRUE_MIN
+#define TYPE_MAX DBL_MAX
+#define TYPE_MIN_EXP DBL_MIN_EXP
+#define TYPE_MAX_EXP DBL_MAX_EXP
+#define TYPE_MANT_DIG DBL_MANT_DIG
+#define TYPE_INF HUGE_VAL
@@ -16,6 +16,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <float.h>
+
#define FUNC(function) function ## f
#define FLOAT float
#define PRINTF_EXPR "e"
@@ -23,3 +25,15 @@
#define PRINTF_NEXPR "f"
#define TEST_FLOAT 1
#define BUILD_COMPLEX(real, imag) (CMPLXF ((real), (imag)))
+
+#define LIT(x) (x ## f)
+#define FTOSTR snprintf
+#define TYPE_STR "float"
+#define TYPE_INF HUGE_VALF
+#define TYPE_DECIMAL_DIG FLT_DECIMAL_DIG
+#define TYPE_MANT_DIG FLT_MANT_DIG
+#define TYPE_MAX FLT_MAX
+#define TYPE_MAX_EXP FLT_MAX_EXP
+#define TYPE_MIN FLT_MIN
+#define TYPE_MIN_EXP FLT_MIN_EXP
+#define TYPE_TRUE_MIN FLT_TRUE_MIN
@@ -16,6 +16,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <float.h>
+
#define FUNC(function) function##l
#define FLOAT long double
#define PRINTF_EXPR "Le"
@@ -23,3 +25,15 @@
#define PRINTF_NEXPR "Lf"
#define TEST_LDOUBLE 1
#define BUILD_COMPLEX(real, imag) (CMPLXL ((real), (imag)))
+
+#define LIT(x) (x ## L)
+#define FTOSTR snprintf
+#define TYPE_STR "ldouble"
+#define TYPE_DECIMAL_DIG LDBL_DECIMAL_DIG
+#define TYPE_MIN LDBL_MIN
+#define TYPE_TRUE_MIN LDBL_TRUE_MIN
+#define TYPE_MAX LDBL_MAX
+#define TYPE_MIN_EXP LDBL_MIN_EXP
+#define TYPE_MAX_EXP LDBL_MAX_EXP
+#define TYPE_MANT_DIG LDBL_MANT_DIG
+#define TYPE_INF HUGE_VALL