diff options
author | David Schultz <das@FreeBSD.org> | 2013-06-03 09:15:15 +0000 |
---|---|---|
committer | David Schultz <das@FreeBSD.org> | 2013-06-03 09:15:15 +0000 |
commit | 8ffb5b838e1870799da85c9f6c1aba0ed6076b3e (patch) | |
tree | 12a658408790cab2e56f2d87ac2a1ebd066d2a7c /tools/regression/lib/msun/test-logarithm.c | |
parent | 25a4d6bfda29119996f6bd93c02914ba646634fa (diff) | |
download | src-8ffb5b838e1870799da85c9f6c1aba0ed6076b3e.tar.gz src-8ffb5b838e1870799da85c9f6c1aba0ed6076b3e.zip |
Notes
Diffstat (limited to 'tools/regression/lib/msun/test-logarithm.c')
-rw-r--r-- | tools/regression/lib/msun/test-logarithm.c | 115 |
1 files changed, 114 insertions, 1 deletions
diff --git a/tools/regression/lib/msun/test-logarithm.c b/tools/regression/lib/msun/test-logarithm.c index c5f23b8705bb..18b9ebe5caca 100644 --- a/tools/regression/lib/msun/test-logarithm.c +++ b/tools/regression/lib/msun/test-logarithm.c @@ -65,20 +65,37 @@ __FBSDID("$FreeBSD$"); assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) +#define test(func, x, result, exceptmask, excepts) do { \ + volatile long double _d = x; \ + assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ + assert(fpequal((func)(_d), (result))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ +} while (0) + +#define test_tol(func, z, result, tol) do { \ + volatile long double _d = z; \ + debug(" testing %6s(%15La) ~= % .36Le\n", #func, _d, result); \ + assert(fpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ +} while (0) + /* Test all the functions that compute log(x). */ #define testall0(x, result, exceptmask, excepts) do { \ test(log, x, result, exceptmask, excepts); \ test(logf, x, result, exceptmask, excepts); \ + test(logl, x, result, exceptmask, excepts); \ test(log2, x, result, exceptmask, excepts); \ test(log2f, x, result, exceptmask, excepts); \ + test(log2l, x, result, exceptmask, excepts); \ test(log10, x, result, exceptmask, excepts); \ test(log10f, x, result, exceptmask, excepts); \ + test(log10l, x, result, exceptmask, excepts); \ } while (0) /* Test all the functions that compute log(1+x). */ #define testall1(x, result, exceptmask, excepts) do { \ test(log1p, x, result, exceptmask, excepts); \ test(log1pf, x, result, exceptmask, excepts); \ + test(log1pl, x, result, exceptmask, excepts); \ } while (0) void @@ -128,6 +145,13 @@ run_log2_tests(void) assert(log2(ldexp(1.0, i)) == i); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } + for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { + assert(log2l(ldexpl(1.0, i)) == i); +#if 0 + /* XXX This test does not pass yet. */ + assert(fetestexcept(ALL_STD_EXCEPT) == 0); +#endif + } } void @@ -139,7 +163,17 @@ run_roundingmode_tests(void) */ fesetround(FE_DOWNWARD); /* These are still positive per IEEE 754R */ +#if 0 testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); +#else + /* logl, log2l, and log10l don't pass yet. */ + test(log, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(logf, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log2, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log2f, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log10, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log10f, 1.0, 0.0, ALL_STD_EXCEPT, 0); +#endif testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); fesetround(FE_TOWARDZERO); testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); @@ -154,11 +188,84 @@ run_roundingmode_tests(void) fesetround(FE_TONEAREST); } +void +run_accuracy_tests(void) +{ + static const struct { + float x; + long double log2x; + long double logex; + long double log10x; + } tests[] = { + { 0x1p-120 + 0x1p-140, + -1.19999998624139449158861798943319717e2L, + -8.31776607135195754708796206665656732e1L, + -3.61235990655024477716980559136055915e1L, + }, + { 1.0 - 0x1p-20, + -1.37586186296463416424364914705656460e-6L, + -9.53674771153890007250243736279163253e-7L, + -4.14175690642480911859354110516159131e-7L, }, + { 1.0 + 0x1p-20, + 1.37586055084113820105668028340371476e-6L, + 9.53673861659188233908415514963336144e-7L, + 4.14175295653950611453333571759200697e-7L }, + { 19.75, + 4.30378074817710292442728634194115348e0L, + 2.98315349134713087533848129856505779e0L, + 1.29556709996247903756734359702926363e0L }, + { 19.75 * 0x1p100, + 1.043037807481771029244272863419411534e2L, + 7.229787154734166181706169344438271459e1L, + 3.139856666636059855894123306947856631e1L }, + }; + int i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + test_tol(log2, tests[i].x, tests[i].log2x, DBL_ULP()); + test_tol(log2f, tests[i].x, tests[i].log2x, FLT_ULP()); + test_tol(log2l, tests[i].x, tests[i].log2x, LDBL_ULP()); + test_tol(log, tests[i].x, tests[i].logex, DBL_ULP()); + test_tol(logf, tests[i].x, tests[i].logex, FLT_ULP()); + test_tol(logl, tests[i].x, tests[i].logex, LDBL_ULP()); + test_tol(log10, tests[i].x, tests[i].log10x, DBL_ULP()); + test_tol(log10f, tests[i].x, tests[i].log10x, FLT_ULP()); + test_tol(log10l, tests[i].x, tests[i].log10x, LDBL_ULP()); + if (tests[i].x >= 0.5) { + test_tol(log1p, tests[i].x - 1, tests[i].logex, + DBL_ULP()); + test_tol(log1pf, tests[i].x - 1, tests[i].logex, + FLT_ULP()); + test_tol(log1pl, tests[i].x - 1, tests[i].logex, + LDBL_ULP()); + } + } +} + +void +run_log1p_accuracy_tests(void) +{ + + test_tol(log1pf, 0x0.333333p0F, + 1.82321546859847114303367992804596800640e-1L, FLT_ULP()); + test_tol(log1p, 0x0.3333333333333p0, + 1.82321556793954589204283870982629267635e-1L, DBL_ULP()); + test_tol(log1pl, 0x0.33333333333333332p0L, + 1.82321556793954626202683007050468762914e-1L, LDBL_ULP()); + + test_tol(log1pf, -0x0.333333p0F, + -2.23143536413048672940940199918017467652e-1L, FLT_ULP()); + test_tol(log1p, -0x0.3333333333333p0, + -2.23143551314209700255143859052009022937e-1L, DBL_ULP()); + test_tol(log1pl, -0x0.33333333333333332p0L, + -2.23143551314209755752742563153765697950e-1L, LDBL_ULP()); +} + int main(int argc, char *argv[]) { - printf("1..3\n"); + printf("1..5\n"); run_generic_tests(); printf("ok 1 - logarithm\n"); @@ -169,5 +276,11 @@ main(int argc, char *argv[]) run_roundingmode_tests(); printf("ok 3 - logarithm\n"); + run_accuracy_tests(); + printf("ok 4 - logarithm\n"); + + run_log1p_accuracy_tests(); + printf("ok 5 - logarithm\n"); + return (0); } |