diff options
Diffstat (limited to 'math')
-rw-r--r-- | math/README.libm-test | 10 | ||||
-rwxr-xr-x | math/gen-libm-test.pl | 79 | ||||
-rw-r--r-- | math/libm-test.inc | 102 |
3 files changed, 40 insertions, 151 deletions
diff --git a/math/README.libm-test b/math/README.libm-test index a083a6d..b8353b1 100644 --- a/math/README.libm-test +++ b/math/README.libm-test @@ -68,14 +68,12 @@ sorted new ULPs file from the output of the test drivers. Contents of libm-test-ulps ========================== -Since libm-test-ulps can be generated automatically, just a few -notes. The file contains lines for single tests, like: -Test "cos (pi/2) == 0": -float: 1 -and lines for maximal errors of single functions, like: +Since libm-test-ulps can be generated automatically, just a few notes. +The file contains lines for maximal errors of single functions, like: + Function "yn": -idouble: 6.0000 +idouble: 6 The keywords are float, ifloat, double, idouble, ldouble and ildouble (the prefix i stands for inline). diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl index a1c528d..919f0f2 100755 --- a/math/gen-libm-test.pl +++ b/math/gen-libm-test.pl @@ -21,8 +21,6 @@ # Note that functions and tests share the same namespace. # Information about tests are stored in: %results -# $results{$test}{"kind"} is either "fct" or "test" and flags whether this -# is a maximal error of a function or a single test. # $results{$test}{"type"} is the result type, e.g. normal or complex. # $results{$test}{"has_ulps"} is set if deltas exist. # In the following description $type and $float are: @@ -484,7 +482,7 @@ sub generate_testfile { # Parse ulps file sub parse_ulps { my ($file) = @_; - my ($test, $type, $float, $eps, $kind); + my ($test, $type, $float, $eps); # $type has the following values: # "normal": No complex variable @@ -496,21 +494,6 @@ sub parse_ulps { # ignore comments and empty lines next if /^#/; next if /^\s*$/; - if (/^Test/) { - if (/Real part of:/) { - s/Real part of: //; - $type = 'real'; - } elsif (/Imaginary part of:/) { - s/Imaginary part of: //; - $type = 'imag'; - } else { - $type = 'normal'; - } - s/^.+\"(.*)\".*$/$1/; - $test = $_; - $kind = 'test'; - next; - } if (/^Function: /) { if (/Real part of/) { s/Real part of //; @@ -522,7 +505,6 @@ sub parse_ulps { $type = 'normal'; } ($test) = ($_ =~ /^Function:\s*\"([a-zA-Z0-9_]+)\"/); - $kind = 'fct'; next; } if (/^i?(float|double|ldouble):/) { @@ -540,7 +522,6 @@ sub parse_ulps { } elsif ($type eq 'normal') { $results{$test}{'type'} = 'normal'; } - $results{$test}{'kind'} = $kind; next; } print "Skipping unknown entry: `$_'\n"; @@ -569,39 +550,9 @@ sub print_ulps_file { $last_fct = ''; open NEWULP, ">$file" or die ("Can't open $file: $!"); print NEWULP "# Begin of automatic generation\n"; - # first the function calls - foreach $test (sort keys %results) { - next if ($results{$test}{'kind'} ne 'test'); - foreach $type ('real', 'imag', 'normal') { - if (exists $results{$test}{$type}) { - if (defined $results{$test}) { - ($fct) = ($test =~ /^(\w+)\s/); - if ($fct ne $last_fct) { - $last_fct = $fct; - print NEWULP "\n# $fct\n"; - } - } - if ($type eq 'normal') { - print NEWULP "Test \"$test\":\n"; - } elsif ($type eq 'real') { - print NEWULP "Test \"Real part of: $test\":\n"; - } elsif ($type eq 'imag') { - print NEWULP "Test \"Imaginary part of: $test\":\n"; - } - foreach $float (@all_floats) { - if (exists $results{$test}{$type}{'ulp'}{$float}) { - print NEWULP "$float: ", - &clean_up_number ($results{$test}{$type}{'ulp'}{$float}), - "\n"; - } - } - } - } - } print NEWULP "\n# Maximal error of functions:\n"; foreach $fct (sort keys %results) { - next if ($results{$fct}{'kind'} ne 'fct'); foreach $type ('real', 'imag', 'normal') { if (exists $results{$fct}{$type}) { if ($type eq 'normal') { @@ -656,7 +607,7 @@ sub get_all_ulps_for_test { sub output_ulps { my ($file, $ulps_filename) = @_; my ($i, $fct, $type, $ulp, $ulp_real, $ulp_imag); - my (%test_ulps, %func_ulps, %func_real_ulps, %func_imag_ulps); + my (%func_ulps, %func_real_ulps, %func_imag_ulps); open ULP, ">$file" or die ("Can't open $file: $!"); @@ -674,22 +625,11 @@ sub output_ulps { } else { die "unknown results ($fct) type $type\n"; } - if ($results{$fct}{'kind'} eq 'fct') { - if ($type eq 'normal') { - $func_ulps{$fct} = $ulp; - } else { - $func_real_ulps{$fct} = $ulp_real; - $func_imag_ulps{$fct} = $ulp_imag; - } - } elsif ($results{$fct}{'kind'} eq 'test') { - if ($type eq 'normal') { - $test_ulps{$fct} = $ulp; - } else { - $test_ulps{"Real part of: $fct"} = $ulp_real; - $test_ulps{"Imaginary part of: $fct"} = $ulp_imag; - } + if ($type eq 'normal') { + $func_ulps{$fct} = $ulp; } else { - die "unknown results ($fct) kind $results{$fct}{'kind'}\n"; + $func_real_ulps{$fct} = $ulp_real; + $func_imag_ulps{$fct} = $ulp_imag; } } print ULP "\n/* Maximal error of functions. */\n"; @@ -708,13 +648,6 @@ sub output_ulps { print ULP " { \"$fct\", $func_imag_ulps{$fct} },\n"; } print ULP " };\n"; - - print ULP "\n/* Error of single function calls. */\n"; - print ULP "static const struct ulp_data test_ulps[] =\n {\n"; - foreach $fct (sort keys %test_ulps) { - print ULP " { \"$fct\", $test_ulps{$fct} },\n"; - } - print ULP " };\n"; close ULP; } diff --git a/math/libm-test.inc b/math/libm-test.inc index 4cb239f..f8cd947 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -127,16 +127,16 @@ #include <tininess.h> #include <math-tests.h> -/* Structure for ulp data for a test, a function, or the real or - imaginary part of a function. */ +/* Structure for ulp data for a function, or the real or imaginary + part of a function. */ struct ulp_data { const char *name; FLOAT max_ulp; }; -/* This header defines test_ulps, func_ulps, func_real_ulps and - func_imag_ulps arrays. */ +/* This header defines func_ulps, func_real_ulps and func_imag_ulps + arrays. */ #include "libm-test-ulps.h" /* Allow platforms without all rounding modes to test properly, @@ -324,6 +324,7 @@ static int ignore_max_ulp; /* Should we ignore max_ulp? */ static FLOAT max_error, real_max_error, imag_max_error; +static FLOAT prev_max_error, prev_real_max_error, prev_imag_max_error; #define BUILD_COMPLEX(real, imag) \ ({ __complex__ FLOAT __retval; \ @@ -336,9 +337,9 @@ static FLOAT max_error, real_max_error, imag_max_error; #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)) -/* Compare KEY (a string, with the name of a test or a function) with - ULP (a pointer to a struct ulp_data structure), returning a value - less than, equal to or greater than zero for use in bsearch. */ +/* Compare KEY (a string, with the name of a function) with ULP (a + pointer to a struct ulp_data structure), returning a value less + than, equal to or greater than zero for use in bsearch. */ static int compare_ulp_data (const void *key, const void *ulp) @@ -362,44 +363,20 @@ find_ulps (const char *name, const struct ulp_data *data, size_t nmemb) return entry->max_ulp; } -/* Return the ulps for test NAME. */ - -static FLOAT -find_test_ulps (const char *name) -{ - return find_ulps (name, test_ulps, - sizeof (test_ulps) / sizeof (test_ulps[0])); -} - -/* Return the ulps for real function NAME. */ - -static FLOAT -find_function_ulps (const char *name) -{ - return find_ulps (name, func_ulps, - sizeof (func_ulps) / sizeof (func_ulps[0])); -} - -/* Return the ulps for complex function NAME. */ - -static __complex__ FLOAT -find_complex_function_ulps (const char *name) -{ - FLOAT ulp_real = find_ulps (name, func_real_ulps, - (sizeof (func_real_ulps) - / sizeof (func_real_ulps[0]))); - FLOAT ulp_imag = find_ulps (name, func_imag_ulps, - (sizeof (func_imag_ulps) - / sizeof (func_imag_ulps[0]))); - return BUILD_COMPLEX (ulp_real, ulp_imag); -} - static void -init_max_error (void) +init_max_error (const char *name) { max_error = 0; real_max_error = 0; imag_max_error = 0; + prev_max_error = find_ulps (name, func_ulps, + sizeof (func_ulps) / sizeof (func_ulps[0])); + prev_real_max_error = find_ulps (name, func_real_ulps, + (sizeof (func_real_ulps) + / sizeof (func_real_ulps[0]))); + prev_imag_max_error = find_ulps (name, func_imag_ulps, + (sizeof (func_imag_ulps) + / sizeof (func_imag_ulps[0]))); feclearexcept (FE_ALL_EXCEPT); errno = 0; } @@ -460,19 +437,6 @@ update_stats (int ok) } static void -print_ulps (const char *test_name, FLOAT ulp) -{ - if (output_ulps) - { - fprintf (ulps_file, "Test \"%s\":\n", test_name); - fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", - CHOOSE("ldouble", "double", "float", - "ildouble", "idouble", "ifloat"), - FUNC(ceil) (ulp)); - } -} - -static void print_function_ulps (const char *function_name, FLOAT ulp) { if (output_ulps) @@ -541,10 +505,9 @@ fpstack_test (const char *test_name) static void print_max_error (const char *func_name) { - FLOAT allowed = find_function_ulps (func_name); int ok = 0; - if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp)) + if (max_error == 0.0 || (max_error <= prev_max_error && !ignore_max_ulp)) { ok = 1; } @@ -557,7 +520,8 @@ print_max_error (const char *func_name) { 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) (allowed)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (prev_max_error)); } update_stats (ok); @@ -567,17 +531,16 @@ print_max_error (const char *func_name) static void print_complex_max_error (const char *func_name) { - __complex__ FLOAT allowed = find_complex_function_ulps (func_name); int real_ok = 0, imag_ok = 0, ok; if (real_max_error == 0 - || (real_max_error <= __real__ allowed && !ignore_max_ulp)) + || (real_max_error <= prev_real_max_error && !ignore_max_ulp)) { real_ok = 1; } if (imag_max_error == 0 - || (imag_max_error <= __imag__ allowed && !ignore_max_ulp)) + || (imag_max_error <= prev_imag_max_error && !ignore_max_ulp)) { imag_ok = 1; } @@ -595,12 +558,12 @@ print_complex_max_error (const char *func_name) printf (" is : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (real_max_error)); printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", - FUNC(ceil) (__real__ allowed)); + FUNC(ceil) (prev_real_max_error)); 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) (__imag__ allowed)); + FUNC(ceil) (prev_imag_max_error)); } update_stats (ok); @@ -773,7 +736,7 @@ ulp (FLOAT value) static void check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, int exceptions, - FLOAT *curr_max_error) + FLOAT *curr_max_error, FLOAT max_ulp) { int ok = 0; int print_diff = 0; @@ -785,7 +748,6 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, test_errno (test_name, errno_value, exceptions); if (exceptions & IGNORE_RESULT) goto out; - FLOAT max_ulp = find_test_ulps (test_name); if (issignaling (computed) && issignaling (expected)) { if ((exceptions & TEST_NAN_SIGN) != 0 @@ -839,11 +801,7 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, else if (ulps <= 0.5 || (ulps <= max_ulp && !ignore_max_ulp)) ok = 1; else - { - ok = 0; - print_ulps (test_name, ulps); - } - + ok = 0; } if (print_screen (ok)) { @@ -876,7 +834,7 @@ check_float (const char *test_name, FLOAT computed, FLOAT expected, int exceptions) { check_float_internal (test_name, computed, expected, - exceptions, &max_error); + exceptions, &max_error, prev_max_error); } @@ -895,7 +853,7 @@ check_complex (const char *test_name, __complex__ FLOAT computed, part_exp = __real__ expected; check_float_internal (str, part_comp, part_exp, - exception, &real_max_error); + exception, &real_max_error, prev_real_max_error); free (str); if (asprintf (&str, "Imaginary part of: %s", test_name) == -1) @@ -910,7 +868,7 @@ check_complex (const char *test_name, __complex__ FLOAT computed, exception & (IGNORE_ZERO_INF_SIGN | TEST_NAN_SIGN | IGNORE_RESULT), - &imag_max_error); + &imag_max_error, prev_imag_max_error); free (str); } @@ -1629,7 +1587,7 @@ struct test_fFF_11_data /* Start and end the tests for a given function. */ #define START(FUNC) \ const char *this_func = #FUNC; \ - init_max_error () + init_max_error (this_func) #define END \ print_max_error (this_func) #define END_COMPLEX \ |