diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2013-12-20 09:29:29 +0100 |
---|---|---|
committer | Thomas Schwinge <thomas@codesourcery.com> | 2013-12-20 09:29:29 +0100 |
commit | a65dd355fb80a05215e15ae97649de52aec885e3 (patch) | |
tree | 81701bb0c6b648630f2bf1729a85d7f5eb49e67b /math/gen-libm-test.pl | |
parent | 296a5732f94abe4d5699dc981e4ccfb950b48cee (diff) | |
parent | b4578bab30f72cddd2cf38abfb39f9c8dc892249 (diff) |
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Diffstat (limited to 'math/gen-libm-test.pl')
-rwxr-xr-x | math/gen-libm-test.pl | 243 |
1 files changed, 216 insertions, 27 deletions
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl index c2d10d35e8..29522a3a25 100755 --- a/math/gen-libm-test.pl +++ b/math/gen-libm-test.pl @@ -39,10 +39,11 @@ use Getopt::Std; use strict; -use vars qw ($input $output); +use vars qw ($input $output $auto_input); use vars qw (%results); use vars qw (%beautify @all_floats); use vars qw ($output_dir $ulps_file); +use vars qw (%auto_tests); # all_floats is sorted and contains all recognised float types @all_floats = ('double', 'float', 'idouble', @@ -51,26 +52,15 @@ use vars qw ($output_dir $ulps_file); %beautify = ( "minus_zero" => "-0", "plus_zero" => "+0", + "-0x0p+0f" => "-0", + "-0x0p+0" => "-0", + "-0x0p+0L" => "-0", + "0x0p+0f" => "+0", + "0x0p+0" => "+0", + "0x0p+0L" => "+0", "minus_infty" => "-inf", "plus_infty" => "inf", "qnan_value" => "qNaN", - "M_El" => "e", - "M_E2l" => "e^2", - "M_E3l" => "e^3", - "M_LOG10El", "log10(e)", - "M_PIl" => "pi", - "M_PI_34l" => "3/4 pi", - "M_PI_2l" => "pi/2", - "M_PI_4l" => "pi/4", - "M_PI_6l" => "pi/6", - "M_PI_34_LOG10El" => "3/4 pi*log10(e)", - "M_PI_LOG10El" => "pi*log10(e)", - "M_PI2_LOG10El" => "pi/2*log10(e)", - "M_PI4_LOG10El" => "pi/4*log10(e)", - "M_LOG_SQRT_PIl" => "log(sqrt(pi))", - "M_LOG_2_SQRT_PIl" => "log(2*sqrt(pi))", - "M_2_SQRT_PIl" => "2 sqrt (pi)", - "M_SQRT_PIl" => "sqrt (pi)", ); @@ -99,9 +89,11 @@ $ulps_file = $opt_u if ($opt_u); $output_dir = $opt_o if ($opt_o); $input = "libm-test.inc"; +$auto_input = "auto-libm-test-out"; $output = "${output_dir}libm-test.c"; &parse_ulps ($ulps_file); +&parse_auto_input ($auto_input); &generate_testfile ($input, $output) unless ($opt_n); &output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n); &print_ulps_file ("${output_dir}NewUlps") if ($opt_n); @@ -121,6 +113,9 @@ sub beautify { return '-' . $beautify{$tmp}; } } + if ($arg =~ /^-?0x[0-9a-f.]*p[-+][0-9]+f$/) { + $arg =~ s/f$//; + } if ($arg =~ /[0-9]L$/) { $arg =~ s/L$//; } @@ -147,11 +142,12 @@ sub build_complex_beautify { # Return the text to put in an initializer for a test's exception # information. sub show_exceptions { - my ($exception) = @_; + my ($ignore_result, $exception) = @_; + $ignore_result = ($ignore_result ? "IGNORE_RESULT|" : ""); if (defined $exception) { - return ", $exception"; + return ", ${ignore_result}$exception"; } else { - return ', 0'; + return ", ${ignore_result}0"; } } @@ -162,6 +158,7 @@ sub parse_args { my ($current_arg, $cline, $i); my (@special); my ($call_args); + my ($ignore_result_any, $ignore_result_all); ($descr_args, $descr_res) = split /_/,$descr, 2; @@ -216,7 +213,7 @@ sub parse_args { # consistency check if ($current_arg == $#args) { die ("wrong number of arguments") - unless ($args[$current_arg] =~ /EXCEPTION|ERRNO|IGNORE_ZERO_INF_SIGN/); + unless ($args[$current_arg] =~ /EXCEPTION|ERRNO|IGNORE_ZERO_INF_SIGN|TEST_NAN_SIGN|NO_TEST_INLINE|XFAIL_TEST/); } elsif ($current_arg < $#args) { die ("wrong number of arguments"); } elsif ($current_arg > ($#args+1)) { @@ -249,20 +246,47 @@ sub parse_args { } @descr = split //,$descr_res; + $ignore_result_any = 0; + $ignore_result_all = 1; foreach (@descr) { if ($_ =~ /b|f|i|l|L/ ) { - $cline .= ", $args[$current_arg]"; + my ($result) = $args[$current_arg]; + if ($result eq "IGNORE") { + $ignore_result_any = 1; + $result = "0"; + } else { + $ignore_result_all = 0; + } + $cline .= ", $result"; $current_arg++; } elsif ($_ eq 'c') { - $cline .= ", $args[$current_arg], $args[$current_arg+1]"; + my ($result1) = $args[$current_arg]; + if ($result1 eq "IGNORE") { + $ignore_result_any = 1; + $result1 = "0"; + } else { + $ignore_result_all = 0; + } + my ($result2) = $args[$current_arg + 1]; + if ($result2 eq "IGNORE") { + $ignore_result_any = 1; + $result2 = "0"; + } else { + $ignore_result_all = 0; + } + $cline .= ", $result1, $result2"; $current_arg += 2; } elsif ($_ eq '1') { push @special, $args[$current_arg]; ++$current_arg; } } + if ($ignore_result_any && !$ignore_result_all) { + die ("some but not all function results ignored\n"); + } # Add exceptions. - $cline .= show_exceptions (($current_arg <= $#args) + $cline .= show_exceptions ($ignore_result_any, + ($current_arg <= $#args) ? $args[$current_arg] : undef); @@ -280,17 +304,165 @@ sub parse_args { print $file " $cline },\n"; } +# Convert a condition from auto-libm-test-out to C form. +sub convert_condition { + my ($cond) = @_; + my (@conds, $ret); + @conds = split /:/, $cond; + foreach (@conds) { + s/-/_/g; + s/^/TEST_COND_/; + } + $ret = join " && ", @conds; + return "($ret)"; +} + +# Return text to OR a value into an accumulated flags string. +sub or_value { + my ($cond) = @_; + if ($cond eq "0") { + return ""; + } else { + return " | $cond"; + } +} + +# Return text to OR a conditional expression between two values into +# an accumulated flags string. +sub or_cond_value { + my ($cond, $if, $else) = @_; + if ($cond eq "1") { + return or_value ($if); + } elsif ($cond eq "0") { + return or_value ($else); + } else { + return or_value ("($cond ? $if : $else)"); + } +} + # Generate libm-test.c sub generate_testfile { my ($input, $output) = @_; - my ($lasttext); - my (@args, $i); open INPUT, $input or die ("Can't open $input: $!"); open OUTPUT, ">$output" or die ("Can't open $output: $!"); # Replace the special macros while (<INPUT>) { + # AUTO_TESTS (function, mode), + if (/^\s*AUTO_TESTS_/) { + my ($descr, $func, $mode, $auto_test, $num_auto_tests); + ($descr, $func, $mode) = ($_ =~ /AUTO_TESTS_(\w+)\s*\((\w+),\s*(\w+)\)/); + $num_auto_tests = 0; + foreach $auto_test (sort keys %{$auto_tests{$func}{$mode}}) { + my ($finputs, $format, $inputs, $outputs, $flags); + my ($format_conv, $flags_conv, @flags, %flag_cond); + $num_auto_tests++; + ($finputs, $outputs, $flags) = split / : */, $auto_test; + ($format, $inputs) = split / /, $finputs, 2; + $inputs =~ s/ /, /g; + $outputs =~ s/ /, /g; + $format_conv = convert_condition ($format); + print OUTPUT "#if $format_conv\n"; + @flags = split / /, $flags; + foreach (@flags) { + if (/^([^:]*):(.*)$/) { + my ($flag, $cond); + $flag = $1; + $cond = convert_condition ($2); + if (defined ($flag_cond{$flag})) { + if ($flag_cond{$flag} ne "1") { + $flag_cond{$flag} .= " || $cond"; + } + } else { + $flag_cond{$flag} = $cond; + } + } else { + $flag_cond{$_} = "1"; + } + } + $flags_conv = ""; + if (defined ($flag_cond{"no-test-inline"})) { + $flags_conv .= or_cond_value ($flag_cond{"no-test-inline"}, + "NO_TEST_INLINE", "0"); + } + if (defined ($flag_cond{"xfail"})) { + $flags_conv .= or_cond_value ($flag_cond{"xfail"}, + "XFAIL_TEST", "0"); + } + my (@exc_list) = qw(divbyzero inexact invalid overflow underflow); + my ($exc); + foreach $exc (@exc_list) { + my ($exc_expected, $exc_ok, $no_exc); + $exc_expected = "\U$exc\E_EXCEPTION"; + $exc_ok = "\U$exc\E_EXCEPTION_OK"; + $no_exc = "0"; + if ($exc eq "inexact") { + $exc_ok = "0"; + $no_exc = "NO_INEXACT_EXCEPTION"; + } + if (defined ($flag_cond{$exc})) { + if ($flag_cond{$exc} ne "1") { + die ("unexpected condition for $exc\n"); + } + if (defined ($flag_cond{"$exc-ok"})) { + $flags_conv .= or_cond_value ($flag_cond{"$exc-ok"}, + $exc_ok, $exc_expected); + } else { + $flags_conv .= or_value ($exc_expected); + } + } else { + if (defined ($flag_cond{"$exc-ok"})) { + $flags_conv .= or_cond_value ($flag_cond{"$exc-ok"}, + $exc_ok, $no_exc); + } else { + $flags_conv .= or_value ($no_exc); + } + } + } + my ($errno_expected, $errno_unknown_cond); + if (defined ($flag_cond{"errno-edom"})) { + if ($flag_cond{"errno-edom"} ne "1") { + die ("unexpected condition for errno-edom"); + } + if (defined ($flag_cond{"errno-erange"})) { + die ("multiple errno values expected"); + } + $errno_expected = "ERRNO_EDOM"; + } elsif (defined ($flag_cond{"errno-erange"})) { + if ($flag_cond{"errno-erange"} ne "1") { + die ("unexpected condition for errno-erange"); + } + $errno_expected = "ERRNO_ERANGE"; + } else { + $errno_expected = "ERRNO_UNCHANGED"; + } + if (defined ($flag_cond{"errno-edom-ok"})) { + if (defined ($flag_cond{"errno-erange-ok"}) + && $flag_cond{"errno-erange-ok"} ne $flag_cond{"errno-edom-ok"}) { + $errno_unknown_cond = "($flag_cond{\"errno-edom-ok\"} || $flag_cond{\"errno-erange-ok\"})"; + } else { + $errno_unknown_cond = $flag_cond{"errno-edom-ok"}; + } + } elsif (defined ($flag_cond{"errno-erange-ok"})) { + $errno_unknown_cond = $flag_cond{"errno-erange-ok"}; + } else { + $errno_unknown_cond = "0"; + } + $flags_conv .= or_cond_value ($errno_unknown_cond, + "0", $errno_expected); + if ($flags_conv ne "") { + $flags_conv =~ s/^ \|/,/; + } + &parse_args (\*OUTPUT, $descr, + "$func, $inputs, $outputs$flags_conv"); + print OUTPUT "#endif\n"; + } + if ($num_auto_tests == 0) { + die ("no automatic tests for $func, $mode\n"); + } + next; + } # TEST_... if (/^\s*TEST_/) { @@ -544,3 +716,20 @@ sub output_ulps { print ULP " };\n"; close ULP; } + +# Parse auto-libm-test-out. +sub parse_auto_input { + my ($file) = @_; + open AUTO, $file or die ("Can't open $file: $!"); + while (<AUTO>) { + chop; + next if !/^= /; + s/^= //; + if (/^(\S+) (\S+) (.*)$/) { + $auto_tests{$1}{$2}{$3} = 1; + } else { + die ("bad automatic test line: $_\n"); + } + } + close AUTO; +} |