From a8a8e5f56ad4190e6012a1f1840e6e147c479a7a Mon Sep 17 00:00:00 2001 From: riastradh Date: Wed, 7 Nov 2018 03:59:36 +0000 Subject: [PATCH] Fix up libm tests. - Fix up last few digits of a lot of known-answer tests. Confirmed with GNU mpfr to 200 bits of precision and cross-checked with whatever libm Ubuntu ships with. - Test relative error, not absolute error. - Set bounds in terms of *_EPSILON, not magic numbers. *_EPSILON is twice the largest relative error of a correctly rounded operation, and equal to the largest relative error of an operation with up to 1ulp error. Most of the operations we're testing are not correctly rounded, but they ought to be no more than 1ulp away. For the few cases where that's not a priori clear (like comparing cbrt and pow(x, 1/3)), use twice *_EPSILON to allow some leeway. - Write the success condition positively as error <= eps. This comes out false if the result is a NaN, meaning failure. In contrast, if we write error > eps for the _failure_ condition, then if the result is a NaN, it will also come out false, but meaning success, which is not what we want. - Fix the trigonometric test cases near bad spots. sin(pi - d) for nonzero d is not zero; it is d + O(d^3). pi is not a floating-point number, so these results should be approximately the nonzero error of our approximation to pi. Likewise with cos(pi/2 - d) and tan(pi + d). (Yes, I know the sin _function_ is ill-conditioned near pi so you shouldn't pass approximate inputs near there, but that's separate from whether a sin _implementation_ gives an answer that is wrong by quintillions of ulps.) Since on x86 (i386 and amd64 alike) we currently use x87 hardware trigonometric instructions, which are bad, these are marked xfail on x86 for now until we switch to software implementations (coming soon to a repository near you). - Use %.8g, %.17g, %.35g to print float, double, long double in failures. This should be enough to identify the problematic outputs and/or reproduce the computation, even if long double is binary128 with 115 bits of precision. If there are any new libm test failures after this, tell me what architecture you're on and send me the atf output and I'll try to figure it out. --- tests/lib/libm/t_acos.c | 4 +- tests/lib/libm/t_asin.c | 33 ++++++++----- tests/lib/libm/t_cbrt.c | 73 ++++++++++++++++++++--------- tests/lib/libm/t_cos.c | 80 ++++++++++++++++++++----------- tests/lib/libm/t_cosh.c | 58 +++++++++++------------ tests/lib/libm/t_exp.c | 52 ++++++++++---------- tests/lib/libm/t_ldexp.c | 37 +++++++-------- tests/lib/libm/t_libm.h | 6 +-- tests/lib/libm/t_log.c | 18 +++---- tests/lib/libm/t_scalbn.c | 31 +++++++----- tests/lib/libm/t_sin.c | 99 ++++++++++++++++++++++++++++----------- tests/lib/libm/t_sinh.c | 56 +++++++++++----------- tests/lib/libm/t_sqrt.c | 72 +++++++++++++++++----------- tests/lib/libm/t_tan.c | 94 +++++++++++++++++++++++++++---------- 14 files changed, 442 insertions(+), 271 deletions(-) diff --git a/tests/lib/libm/t_acos.c b/tests/lib/libm/t_acos.c index f051fb64df42..973f0245cdab 100644 --- a/tests/lib/libm/t_acos.c +++ b/tests/lib/libm/t_acos.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_acos.c,v 1.10 2014/03/05 20:14:46 dsl Exp $ */ +/* $NetBSD: t_acos.c,v 1.11 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ ATF_LIBM_TEST(acos_inrange, "Test acos/acosf(x) for some valid values") { 0, M_PI / 2, }, { 0.1, 1.470628905633337, }, { 0.5, 1.047197551196598, }, - { 0.99, 0.141539473324427, }, + { 0.99, 0.1415394733244273, }, }; unsigned int i; diff --git a/tests/lib/libm/t_asin.c b/tests/lib/libm/t_asin.c index 06de85216429..9b7a5922584f 100644 --- a/tests/lib/libm/t_asin.c +++ b/tests/lib/libm/t_asin.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_asin.c,v 1.3 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_asin.c,v 1.4 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -30,6 +30,7 @@ */ #include +#include #include static const struct { @@ -117,13 +118,14 @@ ATF_TC_HEAD(asin_inrange, tc) ATF_TC_BODY(asin_inrange, tc) { - const double eps = 1.0e-15; - double y; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - y = asin(values[i].x); - if (fabs(y - values[i].y) > eps) + double x = values[i].x; + double y = values[i].y; + + if (!(fabs((asin(x) - y)/y) <= eps)) atf_tc_fail_nonfatal("asin(%g) != %g", values[i].x, values[i].y); } @@ -230,16 +232,23 @@ ATF_TC_HEAD(asinf_inrange, tc) ATF_TC_BODY(asinf_inrange, tc) { - const float eps = 1.0e-6; - float x; - float y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - x = values[i].x; - y = values[i].y; - if (fabs(asinf(x) - y) > eps) - atf_tc_fail_nonfatal("asinf(%g) != %g", x, y); + float x = values[i].x; + float y = values[i].y; + + if (fabs(x) == 0.5) + atf_tc_expect_fail("asinf is busted," + " gives ~2ulp error"); + if (!(fabsf((asinf(x) - y)/y) <= eps)) { + atf_tc_fail_nonfatal("asinf(%.8g) = %.8g != %.8g," + " error=~%.1fulp", + x, asinf(x), y, fabsf(((asinf(x) - y)/y)/eps)); + } + if (fabs(x) == 0.5) + atf_tc_expect_pass(); } } diff --git a/tests/lib/libm/t_cbrt.c b/tests/lib/libm/t_cbrt.c index a7de9f629815..56a6940418d0 100644 --- a/tests/lib/libm/t_cbrt.c +++ b/tests/lib/libm/t_cbrt.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_cbrt.c,v 1.3 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_cbrt.c,v 1.4 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,9 +29,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_cbrt.c,v 1.3 2014/03/03 10:39:08 martin Exp $"); +__RCSID("$NetBSD: t_cbrt.c,v 1.4 2018/11/07 03:59:36 riastradh Exp $"); #include +#include #include #include @@ -61,18 +62,26 @@ ATF_TC_HEAD(cbrt_pow, tc) ATF_TC_BODY(cbrt_pow, tc) { const double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; - const double eps = 1.0e-14; - double y, z; + /* Neither cbrt nor pow is required to be correctly rounded. */ + const double eps = 2*DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(x); i++) { + double x_cbrt = cbrt(x[i]); + double x_pow13 = pow(x[i], 1.0 / 3.0); + bool ok; - y = cbrt(x[i]); - z = pow(x[i], 1.0 / 3.0); + if (x[i] == 0) { + ok = (x_cbrt == x_pow13); + } else { + ok = (fabs((x_cbrt - x_pow13)/x_cbrt) <= eps); + } - if (fabs(y - z) > eps) - atf_tc_fail_nonfatal("cbrt(%0.03f) != " - "pow(%0.03f, 1/3)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("cbrt(%.17g) = %.17g != " + "pow(%.17g, 1/3) = %.17g\n", + x[i], x_cbrt, x[i], x_pow13); + } } } @@ -162,18 +171,27 @@ ATF_TC_HEAD(cbrtf_powf, tc) ATF_TC_BODY(cbrtf_powf, tc) { const float x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; - const float eps = 1.0e-5; - float y, z; + /* Neither cbrt nor pow is required to be correctly rounded. */ + const float eps = 2*FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(x); i++) { + float x_cbrt = cbrtf(x[i]); + float x_pow13 = powf(x[i], 1.0 / 3.0); + bool ok; - y = cbrtf(x[i]); - z = powf(x[i], 1.0 / 3.0); + if (x[i] == 0) { + ok = (x_cbrt == x_pow13); + } else { + ok = (fabsf((x_cbrt - x_pow13)/x_cbrt) <= eps); + } - if (fabsf(y - z) > eps) - atf_tc_fail_nonfatal("cbrtf(%0.03f) != " - "powf(%0.03f, 1/3)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("cbrtf(%.9g) = %.9g. != " + "powf(%.9g, 1/3) = %.9g\n", + (double)x[i], (double)x_cbrt, + (double)x[i], (double)x_pow13); + } } } @@ -263,18 +281,27 @@ ATF_TC_HEAD(cbrtl_powl, tc) ATF_TC_BODY(cbrtl_powl, tc) { const long double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; - const long double eps = 1.0e-15; - long double y, z; + /* Neither cbrt nor pow is required to be correctly rounded. */ + const long double eps = 2*LDBL_EPSILON; size_t i; + atf_tc_expect_fail("powl not yet implemented with full precision"); for (i = 0; i < __arraycount(x); i++) { + long double x_cbrt = cbrtl(x[i]); + long double x_pow13 = powl(x[i], 1.0 / 3.0); + bool ok; - y = cbrtl(x[i]); - z = powl(x[i], 1.0 / 3.0); + if (x[i] == 0) { + ok = (x_cbrt == x_pow13); + } else { + ok = (fabsl((x_cbrt - x_pow13)/x_cbrt) <= eps); + } - if (fabsl(y - z) > eps * fabsl(1 + x[i])) - atf_tc_fail_nonfatal("cbrtl(%0.03Lf) != " - "powl(%0.03Lf, 1/3)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("cbrtl(%.35Lg) = %.35Lg != " + "powl(%.35Lg, 1/3) = %.35Lg\n", + x[i], x_cbrt, x[i], x_pow13); + } } } diff --git a/tests/lib/libm/t_cos.c b/tests/lib/libm/t_cos.c index d99d60810eeb..52be45050408 100644 --- a/tests/lib/libm/t_cos.c +++ b/tests/lib/libm/t_cos.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_cos.c,v 1.4 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_cos.c,v 1.5 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,29 +29,41 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include +#include #include +#if defined(__i386__) || defined(__x86_64__) +const int TRIG_BUSTED = 1; +#else +const int TRIG_BUSTED = 0; +#endif + static const struct { int angle; double x; double y; + float fy; } angles[] = { - { -180, -3.141592653589793, -1.0000000000000000 }, - { -135, -2.356194490192345, -0.7071067811865476 }, - { -90, -1.570796326794897, 0.0000000000000000 }, - { -45, -0.785398163397448, 0.7071067811865476 }, - { 0, 0.000000000000000, 1.0000000000000000 }, - { 30, 0.523598775598299, 0.8660254037844386 }, - { 45, 0.785398163397448, 0.7071067811865476 }, - { 60, 1.047197551196598, 0.5000000000000000 }, - { 90, 1.570796326794897, 0.0000000000000000 }, - { 120, 2.094395102393195, -0.5000000000000000 }, - { 135, 2.356194490192345, -0.7071067811865476 }, - { 150, 2.617993877991494, -0.8660254037844386 }, - { 180, 3.141592653589793, -1.0000000000000000 }, - { 270, 4.712388980384690, 0.0000000000000000 }, - { 360, 6.283185307179586, 1.0000000000000000 } + { -180, -3.141592653589793, -1.0000000000000000, 999 }, + { -135, -2.356194490192345, -0.7071067811865476, 999 }, + { -90, -1.5707963267948966, 6.123233995736766e-17, -4.3711388e-08 }, + { -90, -1.5707963267948968, -1.6081226496766366e-16, -4.3711388e-08 }, + { -45, -0.785398163397448, 0.7071067811865478, 999 }, + { 0, 0.000000000000000, 1.0000000000000000, 999 }, + { 30, 0.523598775598299, 0.8660254037844386, 999 }, + { 45, 0.785398163397448, 0.7071067811865478, 999 }, + { 60, 1.0471975511965976, 0.5000000000000001, 999 }, + { 60, 1.0471975511965979, 0.4999999999999999, 999 }, + { 90, 1.570796326794897, -3.8285686989269494e-16, -4.3711388e-08 }, + { 120, 2.0943951023931953, -0.4999999999999998, 999 }, + { 120, 2.0943951023931957, -0.5000000000000002, 999 }, + { 135, 2.356194490192345, -0.7071067811865476, 999 }, + { 150, 2.617993877991494, -0.8660254037844386, 999 }, + { 180, 3.141592653589793, -1.0000000000000000, 999 }, + { 270, 4.712388980384690, -1.8369701987210297e-16, 1.1924881e-08 }, + { 360, 6.283185307179586, 1.0000000000000000, 999 }, }; /* @@ -65,14 +77,24 @@ ATF_TC_HEAD(cos_angles, tc) ATF_TC_BODY(cos_angles, tc) { - const double eps = 1.0e-15; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + double theta = angles[i].x; + double cos_theta = angles[i].y; - if (fabs(cos(angles[i].x) - angles[i].y) > eps) - atf_tc_fail_nonfatal("cos(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + assert(cos_theta != 0); + if (TRIG_BUSTED && fabs(cos_theta) < 2*DBL_EPSILON) + atf_tc_expect_fail("cos near +/-pi/2 is busted"); + if (!(fabs((cos(theta) - cos_theta)/cos_theta) <= eps)) { + atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g" + " != %.17g", + deg, theta, cos(theta), cos_theta); + } + if (TRIG_BUSTED && fabs(cos_theta) < 2*DBL_EPSILON) + atf_tc_expect_pass(); } } @@ -154,18 +176,22 @@ ATF_TC_HEAD(cosf_angles, tc) ATF_TC_BODY(cosf_angles, tc) { - const float eps = 1.0e-7; - float x, y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + float theta = angles[i].x; + float cos_theta = angles[i].fy; - x = angles[i].x; - y = angles[i].y; + if (cos_theta == 999) + cos_theta = angles[i].y; - if (fabsf(cosf(x) - y) > eps) - atf_tc_fail_nonfatal("cosf(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + assert(cos_theta != 0); + if (!(fabsf((cosf(theta) - cos_theta)/cos_theta) <= eps)) { + atf_tc_fail_nonfatal("cosf(%d deg) = %.8g != %.8g", + deg, cos(theta), cos_theta); + } } } diff --git a/tests/lib/libm/t_cosh.c b/tests/lib/libm/t_cosh.c index 3f998de761bb..aac3a39b0236 100644 --- a/tests/lib/libm/t_cosh.c +++ b/tests/lib/libm/t_cosh.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_cosh.c,v 1.6 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_cosh.c,v 1.7 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,28 +29,28 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_cosh.c,v 1.6 2014/03/03 10:39:08 martin Exp $"); +__RCSID("$NetBSD: t_cosh.c,v 1.7 2018/11/07 03:59:36 riastradh Exp $"); #include +#include #include #include static const struct { double x; double y; - double e; } values[] = { - { -10, 11013.23292010332, 1e4, }, - { -2, 3.762195691083631, 1, }, - { -1, 1.543080634815244, 1, }, - { -0.05, 1.001250260438369, 1, }, - { -0.001, 1.000000500000042, 1, }, - { 0, 1, 1, }, - { 0.001, 1.000000500000042, 1, }, - { 0.05, 1.001250260438369, 1, }, - { 1, 1.543080634815244, 1, }, - { 2, 3.762195691083631, 1, }, - { 10, 11013.23292010332, 1e4, }, + { -10, 11013.232920103323, }, + { -2, 3.762195691083631, }, + { -1, 1.543080634815244, }, + { -0.05, 1.001250260438369, }, + { -0.001, 1.0000005000000418, }, + { 0, 1, }, + { 0.001, 1.0000005000000418, }, + { 0.05, 1.001250260438369, }, + { 1, 1.543080634815244, }, + { 2, 3.762195691083631, }, + { 10, 11013.232920103323, }, }; /* @@ -64,18 +64,17 @@ ATF_TC_HEAD(cosh_inrange, tc) ATF_TC_BODY(cosh_inrange, tc) { - double eps; - double x; - double y; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - x = values[i].x; - y = values[i].y; - eps = 1e-15 * values[i].e; + double x = values[i].x; + double cosh_x = values[i].y; - if (fabs(cosh(x) - y) > eps) - atf_tc_fail_nonfatal("cosh(%g) != %g\n", x, y); + if (!(fabs((cosh(x) - cosh_x)/cosh_x) <= eps)) { + atf_tc_fail_nonfatal("cosh(%.17g) = %.17g != %.17g\n", + x, cosh(x), cosh_x); + } } } @@ -162,18 +161,17 @@ ATF_TC_HEAD(coshf_inrange, tc) ATF_TC_BODY(coshf_inrange, tc) { - float eps; - float x; - float y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - x = values[i].x; - y = values[i].y; - eps = 1e-6 * values[i].e; + float x = values[i].x; + float cosh_x = values[i].y; - if (fabsf(coshf(x) - y) > eps) - atf_tc_fail_nonfatal("coshf(%g) != %g\n", x, y); + if (!(fabsf((coshf(x) - cosh_x)/cosh_x) <= eps)) { + atf_tc_fail_nonfatal("coshf(%.17g) = %.17g != %.17g\n", + x, coshf(x), cosh_x); + } } } diff --git a/tests/lib/libm/t_exp.c b/tests/lib/libm/t_exp.c index 73ae87b01509..e506cdc6d719 100644 --- a/tests/lib/libm/t_exp.c +++ b/tests/lib/libm/t_exp.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_exp.c,v 1.8 2014/10/07 16:53:44 gson Exp $ */ +/* $NetBSD: t_exp.c,v 1.9 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -30,6 +30,7 @@ */ #include +#include #include #include "t_libm.h" @@ -37,17 +38,16 @@ static const struct { double x; double y; - double e; } exp_values[] = { - { -10, 0.4539992976248485e-4, 1e-4, }, - { -5, 0.6737946999085467e-2, 1e-2, }, - { -1, 0.3678794411714423, 1e-1, }, - { -0.1, 0.9048374180359595, 1e-1, }, - { 0, 1.0000000000000000, 1, }, - { 0.1, 1.1051709180756477, 1, }, - { 1, 2.7182818284590452, 1, }, - { 5, 148.41315910257660, 1e2, }, - { 10, 22026.465794806718, 1e4, }, + { -10, 0.4539992976248485e-4, }, + { -5, 0.6737946999085467e-2, }, + { -1, 0.3678794411714423, }, + { -0.1, 0.9048374180359595, }, + { 0, 1.0000000000000000, }, + { 0.1, 1.1051709180756477, }, + { 1, 2.7182818284590452, }, + { 5, 148.41315910257660, }, + { 10, 22026.465794806718, }, }; /* @@ -234,18 +234,17 @@ ATF_TC_HEAD(exp_product, tc) ATF_TC_BODY(exp_product, tc) { - double eps; - double x; - double y; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(exp_values); i++) { - x = exp_values[i].x; - y = exp_values[i].y; - eps = 1e-15 * exp_values[i].e; + double x = exp_values[i].x; + double e_x = exp_values[i].y; - if (fabs(exp(x) - y) > eps) - atf_tc_fail_nonfatal("exp(%0.01f) != %18.18e", x, y); + if (!(fabs((exp(x) - e_x)/e_x) <= eps)) { + atf_tc_fail_nonfatal("exp(%.17g) = %.17g != %.17g", + x, exp(x), e_x); + } } } @@ -332,18 +331,17 @@ ATF_TC_HEAD(expf_product, tc) ATF_TC_BODY(expf_product, tc) { - float eps; - float x; - float y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(exp_values); i++) { - x = exp_values[i].x; - y = exp_values[i].y; - eps = 1e-6 * exp_values[i].e; + float x = exp_values[i].x; + float e_x = exp_values[i].y; - if (fabsf(expf(x) - y) > eps) - atf_tc_fail_nonfatal("expf(%0.01f) != %18.18e", x, y); + if (!(fabsf((expf(x) - e_x)/e_x) <= eps)) { + atf_tc_fail_nonfatal("expf(%.8g) = %.8g != %.8g", + x, exp(x), e_x); + } } } diff --git a/tests/lib/libm/t_ldexp.c b/tests/lib/libm/t_ldexp.c index 251f2aeba5fb..977b2219873b 100644 --- a/tests/lib/libm/t_ldexp.c +++ b/tests/lib/libm/t_ldexp.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_ldexp.c,v 1.16 2016/08/25 00:32:31 maya Exp $ */ +/* $NetBSD: t_ldexp.c,v 1.17 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,14 +29,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_ldexp.c,v 1.16 2016/08/25 00:32:31 maya Exp $"); +__RCSID("$NetBSD: t_ldexp.c,v 1.17 2018/11/07 03:59:36 riastradh Exp $"); #include #include -#include +#include #include +#include #include #include @@ -195,22 +196,17 @@ ATF_TC_HEAD(ldexp_exp2, tc) ATF_TC_BODY(ldexp_exp2, tc) { const double n[] = { 1, 2, 3, 10, 50, 100 }; -#if __DBL_MIN_10_EXP__ <= -40 - const double eps = 1.0e-40; -#else - const double eps = __DBL_MIN__*4.0; -#endif + const double eps = DBL_EPSILON; const double x = 12.0; - double y; size_t i; for (i = 0; i < __arraycount(n); i++) { + double y = ldexp(x, n[i]); - y = ldexp(x, n[i]); - - if (fabs(y - (x * exp2(n[i]))) > eps) { - atf_tc_fail_nonfatal("ldexp(%0.01f, %0.01f) " - "!= %0.01f * exp2(%0.01f)", x, n[i], x, n[i]); + if (!(fabs((y - (x * exp2(n[i])))/y) <= eps)) { + atf_tc_fail_nonfatal("ldexp(%.17g, %.17g) = %.17g " + "!= %.17g * exp2(%.17g) = %.17g", + x, n[i], y, x, n[i], (x * exp2(n[i]))); } } } @@ -320,18 +316,17 @@ ATF_TC_HEAD(ldexpf_exp2f, tc) ATF_TC_BODY(ldexpf_exp2f, tc) { const float n[] = { 1, 2, 3, 10, 50, 100 }; - const float eps = 1.0e-9; + const float eps = FLT_EPSILON; const float x = 12.0; - float y; size_t i; for (i = 0; i < __arraycount(n); i++) { + float y = ldexpf(x, n[i]); - y = ldexpf(x, n[i]); - - if (fabsf(y - (x * exp2f(n[i]))) > eps) { - atf_tc_fail_nonfatal("ldexpf(%0.01f, %0.01f) " - "!= %0.01f * exp2f(%0.01f)", x, n[i], x, n[i]); + if (!(fabsf((y - (x * exp2f(n[i])))/y) <= eps)) { + atf_tc_fail_nonfatal("ldexpf(%.17g, %.17g) = %.17g " + "!= %.17g * exp2f(%.17g) = %.17g", + x, n[i], y, x, n[i], (x * exp2f(n[i]))); } } } diff --git a/tests/lib/libm/t_libm.h b/tests/lib/libm/t_libm.h index 34e3cb28abf5..0831f22d468d 100644 --- a/tests/lib/libm/t_libm.h +++ b/tests/lib/libm/t_libm.h @@ -1,4 +1,4 @@ -/* $NetBSD: t_libm.h,v 1.6 2014/03/25 17:30:14 joerg Exp $ */ +/* $NetBSD: t_libm.h,v 1.7 2018/11/07 03:59:36 riastradh Exp $ */ /* * Check result of fn(arg) is correct within the bounds. @@ -11,8 +11,8 @@ long double epsilon = epsilon_; \ long double expect = expect_; \ long double r = fn(arg); \ - long double e = fabsl(r - expect); \ - if (r != expect && e > epsilon) \ + long double e = fabsl((r - expect)/expect); \ + if (!(r == expect || e <= epsilon)) \ atf_tc_fail_nonfatal( \ "subtest %u: " #fn "(%g) is %Lg (%.14La) " \ "not %Lg (%.13La), error %Lg (%.6La) > %Lg", \ diff --git a/tests/lib/libm/t_log.c b/tests/lib/libm/t_log.c index 756efcf39769..41aae4c7c967 100644 --- a/tests/lib/libm/t_log.c +++ b/tests/lib/libm/t_log.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_log.c,v 1.13 2015/02/09 19:39:48 martin Exp $ */ +/* $NetBSD: t_log.c,v 1.14 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,10 +29,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_log.c,v 1.13 2015/02/09 19:39:48 martin Exp $"); +__RCSID("$NetBSD: t_log.c,v 1.14 2018/11/07 03:59:36 riastradh Exp $"); #include +#include #include #include #include @@ -614,10 +615,10 @@ ATF_TC_HEAD(log_base, tc) ATF_TC_BODY(log_base, tc) { - const double eps = 1.0e-38; + const double eps = DBL_EPSILON; - if (fabs(log(M_E) - 1.0) > eps) - atf_tc_fail_nonfatal("log(e) != 1"); + if (!(fabs(log(M_E) - 1.0) <= eps)) + atf_tc_fail_nonfatal("log(e) = %.17g != 1", log(M_E)); } ATF_TC(log_nan); @@ -714,10 +715,11 @@ ATF_TC_HEAD(logf_base, tc) ATF_TC_BODY(logf_base, tc) { - const float eps = 1.0e-7; + const float eps = FLT_EPSILON; - if (fabsf(logf(M_E) - 1.0f) > eps) - atf_tc_fail_nonfatal("logf(e) != 1"); + if (!(fabsf(logf(M_E) - 1.0f) <= eps)) + atf_tc_fail_nonfatal("logf(e) = %.17g != 1", + (double)logf(M_E)); } ATF_TC(logf_nan); diff --git a/tests/lib/libm/t_scalbn.c b/tests/lib/libm/t_scalbn.c index 57970e16dbe4..2a0b51ae372e 100644 --- a/tests/lib/libm/t_scalbn.c +++ b/tests/lib/libm/t_scalbn.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_scalbn.c,v 1.15 2018/06/03 08:39:00 maya Exp $ */ +/* $NetBSD: t_scalbn.c,v 1.16 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_scalbn.c,v 1.15 2018/06/03 08:39:00 maya Exp $"); +__RCSID("$NetBSD: t_scalbn.c,v 1.16 2018/11/07 03:59:36 riastradh Exp $"); #include #include @@ -97,9 +97,12 @@ ATF_TC_BODY(scalbn_val, tc) fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW), tests[i].except); #endif - ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON, - "test %zu: return value %g instead of %g (difference %g)", - i, rv, tests[i].result, tests[i].result-rv); + /* scalbn is always exact except for underflow or overflow. */ + ATF_CHECK_MSG(rv == tests[i].result, + "test %zu: return value %.17g instead of %.17g" + " (error %.17g)", + i, rv, tests[i].result, + fabs((tests[i].result - rv)/tests[i].result)); } } @@ -239,9 +242,12 @@ ATF_TC_BODY(scalbnf_val, tc) ATF_CHECK_EQ_MSG(errno, tests[i].error, "test %zu: errno %d instead of %d", i, errno, tests[i].error); - ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON, - "test %zu: return value %g instead of %g (difference %g)", - i, rv, tests[i].result, tests[i].result-rv); + /* scalbn is always exact except for underflow or overflow. */ + ATF_CHECK_MSG(rv == (float)tests[i].result, + "test %zu: return value %.8g instead of %.8g" + " (error %.8g)", + i, rv, tests[i].result, + fabsf((tests[i].result - rv)/tests[i].result)); } } @@ -384,9 +390,12 @@ ATF_TC_BODY(scalbnl_val, tc) ATF_CHECK_EQ_MSG(errno, tests[i].error, "test %zu: errno %d instead of %d", i, errno, tests[i].error); - ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON, - "test %zu: return value %Lg instead of %Lg (difference %Lg)", - i, rv, (long double)tests[i].result, (long double)tests[i].result-rv); + /* scalbn is always exact except for underflow or overflow. */ + ATF_CHECK_MSG(rv == (long double)tests[i].result, + "test %zu: return value %.35Lg instead of %.35Lg" + " (error %.35Lg)", + i, rv, (long double)tests[i].result, + fabsl(((long double)tests[i].result - rv)/tests[i].result)); } #endif } diff --git a/tests/lib/libm/t_sin.c b/tests/lib/libm/t_sin.c index a82f49dc65d6..321fbbb9ebc5 100644 --- a/tests/lib/libm/t_sin.c +++ b/tests/lib/libm/t_sin.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_sin.c,v 1.4 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_sin.c,v 1.5 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,29 +29,39 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include +#include #include +#if defined(__i386__) || defined(__x86_64__) +const int TRIG_BUSTED = 1; +#else +const int TRIG_BUSTED = 0; +#endif + static const struct { int angle; double x; double y; + float fy; } angles[] = { - { -180, -3.141592653589793, 0.0000000000000000 }, - { -135, -2.356194490192345, -0.7071067811865476 }, - { -90, -1.570796326794897, -1.0000000000000000 }, - { -45, -0.785398163397448, -0.7071067811865476 }, - { 0, 0.000000000000000, 0.0000000000000000 }, - { 30, 0.523598775598299, 0.5000000000000000 }, - { 45, 0.785398163397448, 0.7071067811865476 }, - { 60, 1.047197551196598, 0.8660254037844386 }, - { 90, 1.570796326794897, 1.0000000000000000 }, - { 120, 2.094395102393195, 0.8660254037844386 }, - { 135, 2.356194490192345, 0.7071067811865476 }, - { 150, 2.617993877991494, 0.5000000000000000 }, - { 180, 3.141592653589793, 0.0000000000000000 }, - { 270, 4.712388980384690, -1.0000000000000000 }, - { 360, 6.283185307179586, 0.0000000000000000 } + { -360, -6.283185307179586, 2.4492935982947064e-16, -1.7484555e-07 }, + { -180, -3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 }, + { -135, -2.356194490192345, -0.7071067811865476, 999 }, + { -90, -1.570796326794897, -1.0000000000000000, 999 }, + { -45, -0.785398163397448, -0.7071067811865472, 999 }, + { 0, 0.000000000000000, 0.0000000000000000, 999 }, + { 30, 0.5235987755982989, 0.5000000000000000, 999 }, + { 45, 0.785398163397448, 0.7071067811865472, 999 }, + { 60, 1.047197551196598, 0.8660254037844388, 999 }, + { 90, 1.570796326794897, 1.0000000000000000, 999 }, + { 120, 2.094395102393195, 0.8660254037844389, 999 }, + { 135, 2.356194490192345, 0.7071067811865476, 999 }, + { 150, 2.617993877991494, 0.5000000000000003, 999 }, + { 180, 3.141592653589793, 1.2246467991473532e-16, -8.7422777e-08 }, + { 270, 4.712388980384690, -1.0000000000000000, 999 }, + { 360, 6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 }, }; /* @@ -65,14 +75,37 @@ ATF_TC_HEAD(sin_angles, tc) ATF_TC_BODY(sin_angles, tc) { - const double eps = 1.0e-15; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + double theta = angles[i].x; + double sin_theta = angles[i].y; + bool ok; - if (fabs(sin(angles[i].x) - angles[i].y) > eps) - atf_tc_fail_nonfatal("sin(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + if (sin_theta == 0) { + /* Should be computed exactly. */ + assert(sin_theta == 0); + ok = (sin(theta) == 0); + } else { + assert(sin_theta != 0); + ok = (fabs((sin(theta) - sin_theta)/sin_theta) <= eps); + } + + if (TRIG_BUSTED && + sin_theta != 0 && + fabs(sin_theta) < 2*DBL_EPSILON) + atf_tc_expect_fail("sin near +/- pi is busted"); + if (!ok) { + atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g" + " != %.17g", + deg, theta, sin(theta), sin_theta); + } + if (TRIG_BUSTED && + sin_theta != 0 && + fabs(sin_theta) < 2*DBL_EPSILON) + atf_tc_expect_pass(); } } @@ -154,18 +187,30 @@ ATF_TC_HEAD(sinf_angles, tc) ATF_TC_BODY(sinf_angles, tc) { - const float eps = 1.0e-6; - float x, y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + float theta = angles[i].x; + float sin_theta = angles[i].fy; + bool ok; - x = angles[i].x; - y = angles[i].y; + if (sin_theta == 999) + sin_theta = angles[i].y; - if (fabsf(sinf(x) - y) > eps) - atf_tc_fail_nonfatal("sinf(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + if (sin_theta == 0) { + /* Should be computed exactly. */ + ok = (sinf(theta) == 0); + } else { + ok = (fabsf((sinf(theta) - sin_theta)/sin_theta) + <= eps); + } + + if (!ok) { + atf_tc_fail_nonfatal("sinf(%d deg) = %.17g != %.17g", + deg, (double)sin(theta), (double)sin_theta); + } } } diff --git a/tests/lib/libm/t_sinh.c b/tests/lib/libm/t_sinh.c index d935f0ea7ffb..d5f764fea573 100644 --- a/tests/lib/libm/t_sinh.c +++ b/tests/lib/libm/t_sinh.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_sinh.c,v 1.6 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_sinh.c,v 1.7 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,27 +29,27 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_sinh.c,v 1.6 2014/03/03 10:39:08 martin Exp $"); +__RCSID("$NetBSD: t_sinh.c,v 1.7 2018/11/07 03:59:36 riastradh Exp $"); #include +#include #include #include static const struct { double x; double y; - double e; } values[] = { - { -10, -11013.23287470339, 1e4, }, - { -2, -3.626860407847019, 1, }, - { -1, -1.175201193643801, 1, }, - { -0.05, -0.050020835937655, 1, }, - { -0.001,-0.001000000166667, 1, }, - { 0.001, 0.001000000166667, 1, }, - { 0.05, 0.050020835937655, 1, }, - { 1, 1.175201193643801, 1, }, - { 2, 3.626860407847019, 1, }, - { 10, 11013.23287470339, 1e4, }, + { -10, -11013.232874703393, }, + { -2, -3.626860407847019, }, + { -1, -1.1752011936438014, }, + { -0.05, -0.050020835937655016, }, + { -0.001,-0.0010000001666666751, }, + { 0.001, 0.0010000001666666751, }, + { 0.05, 0.050020835937655016, }, + { 1, 1.1752011936438014, }, + { 2, 3.626860407847019, }, + { 10, 11013.232874703393, }, }; /* @@ -63,18 +63,17 @@ ATF_TC_HEAD(sinh_inrange, tc) ATF_TC_BODY(sinh_inrange, tc) { - double eps; - double x; - double y; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - x = values[i].x; - y = values[i].y; - eps = 1e-15 * values[i].e; + double x = values[i].x; + double sinh_x = values[i].y; - if (fabs(sinh(x) - y) > eps) - atf_tc_fail_nonfatal("sinh(%g) != %g\n", x, y); + if (!(fabs((sinh(x) - sinh_x)/sinh_x) <= eps)) { + atf_tc_fail_nonfatal("sinh(%.17g) = %.17g != %.17g\n", + x, sinh(x), sinh_x); + } } } @@ -163,18 +162,17 @@ ATF_TC_HEAD(sinhf_inrange, tc) ATF_TC_BODY(sinhf_inrange, tc) { - float eps; - float x; - float y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(values); i++) { - x = values[i].x; - y = values[i].y; - eps = 1e-6 * values[i].e; + float x = values[i].x; + float sinh_x = values[i].y; - if (fabsf(sinhf(x) - y) > eps) - atf_tc_fail_nonfatal("sinhf(%g) != %g\n", x, y); + if (!(fabsf((sinhf(x) - sinh_x)/sinh_x) <= eps)) { + atf_tc_fail_nonfatal("sinhf(%.8g) = %.8g != %.8g\n", + (double)x, (double)sinhf(x), (double)sinh_x); + } } } diff --git a/tests/lib/libm/t_sqrt.c b/tests/lib/libm/t_sqrt.c index 1d551ec3101d..080aff1c40e8 100644 --- a/tests/lib/libm/t_sqrt.c +++ b/tests/lib/libm/t_sqrt.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_sqrt.c,v 1.7 2014/03/12 21:40:07 martin Exp $ */ +/* $NetBSD: t_sqrt.c,v 1.8 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_sqrt.c,v 1.7 2014/03/12 21:40:07 martin Exp $"); +__RCSID("$NetBSD: t_sqrt.c,v 1.8 2018/11/07 03:59:36 riastradh Exp $"); #include #include @@ -62,22 +62,25 @@ ATF_TC_HEAD(sqrt_pow, tc) ATF_TC_BODY(sqrt_pow, tc) { const double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; -#if __DBL_MIN_10_EXP__ <= -40 - const double eps = 1.0e-40; -#else - const double eps = __DBL_MIN__*4.0; -#endif - double y, z; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(x); i++) { + double x_sqrt = sqrt(x[i]); + double x_pow12 = pow(x[i], 1.0 / 2.0); + bool ok; - y = sqrt(x[i]); - z = pow(x[i], 1.0 / 2.0); + if (x[i] == 0) { + ok = (x_sqrt == x_pow12); + } else { + ok = (fabs((x_sqrt - x_pow12)/x_sqrt) <= eps); + } - if (fabs(y - z) > eps) - atf_tc_fail_nonfatal("sqrt(%0.03f) != " - "pow(%0.03f, 1/2)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("sqrt(%.17g) = %.17g != " + "pow(%.17g, 1/2) = %.17g\n", + x[i], x_sqrt, x[i], x_pow12); + } } } @@ -166,18 +169,26 @@ ATF_TC_HEAD(sqrtf_powf, tc) ATF_TC_BODY(sqrtf_powf, tc) { const float x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; - const float eps = 1.0e-30; - volatile float y, z; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(x); i++) { + float x_sqrt = sqrtf(x[i]); + float x_pow12 = powf(x[i], 1.0 / 2.0); + bool ok; - y = sqrtf(x[i]); - z = powf(x[i], 1.0 / 2.0); + if (x[i] == 0) { + ok = (x_sqrt == x_pow12); + } else { + ok = (fabsf((x_sqrt - x_pow12)/x_sqrt) <= eps); + } - if (fabsf(y - z) > eps) - atf_tc_fail_nonfatal("sqrtf(%0.03f) != " - "powf(%0.03f, 1/2)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("sqrtf(%.8g) = %.8g != " + "powf(%.8g, 1/2) = %.8g\n", + (double)x[i], (double)x_sqrt, + (double)x[i], (double)x_pow12); + } } } @@ -266,18 +277,25 @@ ATF_TC_HEAD(sqrtl_powl, tc) ATF_TC_BODY(sqrtl_powl, tc) { const long double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; - const long double eps = 5.0*DBL_EPSILON; /* XXX powl == pow for now */ - volatile long double y, z; + const long double eps = DBL_EPSILON; /* XXX powl == pow for now */ size_t i; for (i = 0; i < __arraycount(x); i++) { + long double x_sqrt = sqrtl(x[i]); + long double x_pow12 = powl(x[i], 1.0 / 2.0); + bool ok; - y = sqrtl(x[i]); - z = powl(x[i], 1.0 / 2.0); + if (x[i] == 0) { + ok = (x_sqrt == x_pow12); + } else { + ok = (fabsl((x_sqrt - x_pow12)/x_sqrt) <= eps); + } - if (fabsl(y - z) > eps) - atf_tc_fail_nonfatal("sqrtl(%0.03Lf) != " - "powl(%0.03Lf, 1/2)\n", x[i], x[i]); + if (!ok) { + atf_tc_fail_nonfatal("sqrtl(%.35Lg) = %.35Lg != " + "powl(%.35Lg, 1/2) = %.35Lg\n", + x[i], x_sqrt, x[i], x_pow12); + } } } diff --git a/tests/lib/libm/t_tan.c b/tests/lib/libm/t_tan.c index 807e3d1f3364..e2e7085af60a 100644 --- a/tests/lib/libm/t_tan.c +++ b/tests/lib/libm/t_tan.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_tan.c,v 1.5 2014/03/03 10:39:08 martin Exp $ */ +/* $NetBSD: t_tan.c,v 1.6 2018/11/07 03:59:36 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -29,26 +29,35 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include +#include #include +#if defined(__i386__) || defined(__x86_64__) +const int TRIG_BUSTED = 1; +#else +const int TRIG_BUSTED = 0; +#endif + static const struct { int angle; double x; double y; + float fy; } angles[] = { - { -180, -3.141592653589793, 0.0000000000000000 }, - { -135, -2.356194490192345, 1.0000000000000000 }, - { -45, -0.785398163397448, -1.0000000000000000 }, - { 0, 0.000000000000000, 0.0000000000000000 }, - { 30, 0.523598775598299, 0.5773502691896258 }, - { 45, 0.785398163397448, 1.0000000000000000 }, - { 60, 1.047197551196598, 1.7320508075688773 }, - { 120, 2.094395102393195, -1.7320508075688773 }, - { 135, 2.356194490192345, -1.0000000000000000 }, - { 150, 2.617993877991494, -0.5773502691896258 }, - { 180, 3.141592653589793, 0.0000000000000000 }, - { 360, 6.283185307179586, 0.0000000000000000 } + { -180, -3.141592653589793, 1.2246467991473532e-16, -8.7422777e-08 }, + { -135, -2.356194490192345, 1.0000000000000002, 999 }, + { -45, -0.785398163397448, -0.9999999999999992, 999 }, + { 0, 0.000000000000000, 0.0000000000000000, 999 }, + { 30, 0.5235987755982988, 0.57735026918962573, 999 }, + { 45, 0.785398163397448, 0.9999999999999992, 999 }, + { 60, 1.047197551196598, 1.7320508075688785, 999 }, + { 120, 2.094395102393195, -1.7320508075688801, -1.7320505 }, + { 135, 2.356194490192345, -1.0000000000000002, 999 }, + { 150, 2.617993877991494, -0.57735026918962629, -0.57735032 }, + { 180, 3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 }, + { 360, 6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 }, }; /* @@ -62,14 +71,37 @@ ATF_TC_HEAD(tan_angles, tc) ATF_TC_BODY(tan_angles, tc) { - const double eps = 1.0e-14; + const double eps = DBL_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + double theta = angles[i].x; + double tan_theta = angles[i].y; + bool ok; - if (fabs(tan(angles[i].x) - angles[i].y) > eps) - atf_tc_fail_nonfatal("tan(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + if (theta == 0) { + /* Should be computed exactly. */ + assert(tan_theta == 0); + ok = (tan(theta) == 0); + } else { + assert(tan_theta != 0); + ok = (fabs((tan(theta) - tan_theta)/tan_theta) <= eps); + } + + if (TRIG_BUSTED && + tan_theta != 0 && + fabs(tan_theta) < 2*DBL_EPSILON) + atf_tc_expect_fail("tan near +/- pi is busted"); + if (!ok) { + atf_tc_fail_nonfatal("tan(%d deg = %.17g) = %.17g" + " != %.17g", + deg, theta, tan(theta), tan_theta); + } + if (TRIG_BUSTED && + tan_theta != 0 && + fabs(tan_theta) < 2*DBL_EPSILON) + atf_tc_expect_pass(); } } @@ -151,18 +183,32 @@ ATF_TC_HEAD(tanf_angles, tc) ATF_TC_BODY(tanf_angles, tc) { - const float eps = 1.0e-6; - float x, y; + const float eps = FLT_EPSILON; size_t i; for (i = 0; i < __arraycount(angles); i++) { + int deg = angles[i].angle; + float theta = angles[i].x; + float tan_theta = angles[i].fy; + bool ok; - x = angles[i].x; - y = angles[i].y; + if (tan_theta == 999) + tan_theta = angles[i].y; - if (fabsf(tanf(x) - y) > eps) - atf_tc_fail_nonfatal("tanf(%d deg) != %0.01f", - angles[i].angle, angles[i].y); + if (theta == 0) { + /* Should be computed exactly. */ + assert(tan_theta == 0); + ok = (tan(theta) == 0); + } else { + assert(tan_theta != 0); + ok = (fabsf((tanf(theta) - tan_theta)/tan_theta) + <= eps); + } + + if (!ok) { + atf_tc_fail_nonfatal("tanf(%d deg) = %.8g != %.8g", + deg, tanf(theta), tan_theta); + } } }