| README for libm-test math test suite |
| ==================================== |
| |
| The libm-test math test suite tests a number of function points of |
| math functions in the GNU C library. The following sections contain a |
| brief overview. Please note that the test drivers and the Perl script |
| "gen-libm-test.pl" have some options. A full list of options is |
| available with --help (for the test drivers) and -h for |
| "gen-libm-test.pl". |
| |
| |
| What is tested? |
| =============== |
| The tests just evaluate the functions at specified points and compare |
| the results with precomputed values and the requirements of the ISO |
| C99 standard. |
| |
| Besides testing the special values mandated by IEEE 754 (infinities, |
| NaNs and minus zero), some more or less random values are tested. |
| |
| Files that are part of libm-test |
| ================================ |
| |
| The main file is "libm-test.inc". It is independent of the target |
| platform and the specific real floating type and format and contains |
| placeholder test "templates" for math functions defined in libm. |
| The file, along with a generated file named "auto-libm-test-out", |
| is preprocessed by the Perl script "gen-libm-test.pl" to expand |
| the templates and produce a set of test cases for each math function |
| that are specific to the target platform but still independent of |
| the real floating type. The results of the processing are |
| "libm-test.c" and a file "libm-test-ulps.h" with platform specific |
| deltas by which the actual math function results may deviate from |
| the expected results and still be considered correct. |
| |
| The test drivers "test-double.c", "test-float.c", and "test-ldouble.c" |
| test the normal double, float and long double implementation of libm. |
| The test drivers with an 'i' in their name ("test-idouble.c", |
| "test-ifloat.c", and "test-ildoubl.c") test the corresponding inline |
| functions (where available - otherwise they also test the real |
| functions in libm). Each driver selects the desired real floating |
| type to exercise the math functions to test with (float, double, or |
| long double) by defining a small set of macros just before including |
| the generic "libm-test.c" file. Each driver also either defines or |
| undefines the __NO_MATH_INLINES macro just before including |
| "libm-test.c" to select either the real or inline functions, |
| respectively. Each driver is compiled into a single executable test |
| program with the corresponding name. |
| |
| As mentioned above, the "gen-libm-test.pl" script looks for a file |
| named "libm-test-ulps" in the platform specific sysdep directory (or |
| its fpu or nofpu subdirectory) and for each variant (real floating |
| type and rounding mode) of every tested function reads from it the |
| maximum difference expressed as Units of Least Precision (ULP) the |
| actual result of the function may deviate from the expected result |
| before it's considered incorrect. |
| |
| The "auto-libm-test-out" file contains sets of test cases to exercise, |
| the conditions under which to exercise each, and the expected results. |
| The file is generated by the "gen-auto-libm-tests" program from the |
| "auto-libm-test-in" file. See the comments in gen-auto-libm-tests.c |
| for details about the content and format of the -in and -out files. |
| |
| How can I generate "libm-test-ulps"? |
| ==================================== |
| |
| To automatically generate a new "libm-test-ulps" run "make regen-ulps". |
| This generates the file "math/NewUlps" in the build directory. The file |
| contains the sorted results of all the tests. You can use the "NewUlps" |
| file as the machine's updated "libm-test-ulps" file. Copy "NewUlps" to |
| "libm-test-ulps" in the appropriate machine sysdep directory. Verify |
| the changes, post your patch, and check it in after review. |
| |
| To manually generate a new "libm-test-ulps" file, first remove "ULPs" |
| file in the current directory, then you can execute for example: |
| ./testrun.sh math/test-double -u --ignore-max-ulp=yes |
| This generates a file "ULPs" with all double ULPs in it, ignoring any |
| previously calculated ULPs, and running with the newly built dynamic |
| loader and math library (assumes you didn't install your build). Now |
| generate the ULPs for all other formats, the tests will be appending the |
| data to the "ULPs" file. As final step run "gen-libm-test.pl" with the |
| file as input and ask to generate a pretty printed output in the file |
| "NewUlps": |
| gen-libm-test.pl -u ULPs -n |
| Copy "NewUlps" to "libm-test-ulps" in the appropriate machine sysdep |
| directory. |
| |
| Note that the test drivers have an option "-u" to output an unsorted |
| list of all epsilons that the functions have. The output can be read |
| in directly but it's better to pretty print it first. |
| "gen-libm-test.pl" has an option to generate a pretty-printed and |
| 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 maximal errors of single functions, like: |
| |
| Function "yn": |
| idouble: 6 |
| |
| The keywords are float, ifloat, double, idouble, ldouble and ildouble |
| (the prefix i stands for inline). |
| |
| Adding tests to libm-test.inc |
| ============================= |
| |
| The tests are evaluated by a set of special test macros. The macros |
| start with "TEST_" followed by a specification the input values, an |
| underscore and a specification of the output values. As an example, |
| the test macro for a function with input of type FLOAT (FLOAT is |
| either float, double, long double) and output of type FLOAT is |
| "TEST_f_f". The macro's parameter are the name of the function, the |
| input parameter, output parameter and optionally one exception |
| parameter. |
| |
| The accepted parameter types are: |
| - "f" for FLOAT |
| - "b" for boolean - just tests if the output parameter evaluates to 0 |
| or 1 (only for output). |
| - "c" for complex. This parameter needs two values, first the real, |
| then the imaginary part. |
| - "i" for int. |
| - "l" for long int. |
| - "L" for long long int. |
| - "F" for the address of a FLOAT (only as input parameter) |
| - "I" for the address of an int (only as input parameter) |
| |
| How to read the test output |
| =========================== |
| |
| Running each test on its own at the default level of verbosity will |
| print on stdout a line describing the implementation of math functions |
| exercised by the test (float, double, or long double), along with |
| whether the inline set has been selected, regardless of whether or |
| not any inline functions actually exist. This is then followed by |
| the details of test failures (if any). The output concludes by |
| a summary listing the number of test cases exercised and the number |
| of test failures uncovered. |
| |
| For each test failure (and for each test case at higher levels of |
| verbosity), the output contains the name of the function under test |
| and its arguments or conditions that triggered the failure. Note |
| that the name of the function in the output need not correspond |
| exactly to the name of the math function actually invoked. For example, |
| the output will refer to the "acos" function even if the actual function |
| under test is acosf (for the float version) or acosl (for the long |
| double version). Also note that the function arguments may be shown |
| in either the decimal or the hexadecimal floating point format which |
| may or may not correspond to the format used in the auto-libm-test-in |
| file. Besides the name of the function, for each test failure the |
| output contains the actual and expected results and the difference |
| between the two, printed in both the decimal and hexadecimal |
| floating point format, and the ULP and maximum ULP for the test |
| case. |