Module Name:    src
Committed By:   dsl
Date:           Sat Mar  1 21:08:39 UTC 2014

Modified Files:
        src/tests/lib/libm: t_acos.c

Log Message:
Some of the acos() tests seem to fail on some systems.
Sorting out why isn't helped by the tests not reporting the erronous value.
Change the 'boilerplate' pattern used so that all the values are output.
Reduce the amount of faffy red tape as well.
Some of these reductions could be shared with other libm tests, but for
  the moment they are defined in this file.
All these tests pass on my amd64 system, and when I run amd64 qemu.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/tests/lib/libm/t_acos.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/lib/libm/t_acos.c
diff -u src/tests/lib/libm/t_acos.c:1.4 src/tests/lib/libm/t_acos.c:1.5
--- src/tests/lib/libm/t_acos.c:1.4	Tue Apr  9 12:11:04 2013
+++ src/tests/lib/libm/t_acos.c	Sat Mar  1 21:08:39 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: t_acos.c,v 1.4 2013/04/09 12:11:04 isaki Exp $ */
+/* $NetBSD: t_acos.c,v 1.5 2014/03/01 21:08:39 dsl Exp $ */
 
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -32,188 +32,100 @@
 #include <atf-c.h>
 #include <math.h>
 
-static const struct {
-	double x;
-	double y;
-} values[] = {
-	{ -1,    M_PI,              },
-	{ -0.99, 3.000053180265366, },
-	{ -0.5,  2.094395102393195, },
-	{ -0.1,  1.670963747956456, },
-	{  0,    M_PI / 2,          },
-	{  0.1,  1.470628905633337, },
-	{  0.5,  1.047197551196598, },
-	{  0.99, 0.141539473324427, },
-};
-
 /*
- * acos(3)
+ * Check result of fn(arg) is correct within the bounds.
+ * Should be ok to do the checks using 'double' for 'float' functions.
  */
-ATF_TC(acos_nan);
-ATF_TC_HEAD(acos_nan, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(NaN) == NaN");
-}
-
-ATF_TC_BODY(acos_nan, tc)
-{
-#ifndef __vax__
-	const double x = 0.0L / 0.0L;
-
-	if (isnan(acos(x)) == 0)
-		atf_tc_fail_nonfatal("acos(NaN) != NaN");
-#endif
-}
-
-ATF_TC(acos_inf_neg);
-ATF_TC_HEAD(acos_inf_neg, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(-Inf) == NaN");
-}
-
-ATF_TC_BODY(acos_inf_neg, tc)
-{
-#ifndef __vax__
-	const double x = -1.0L / 0.0L;
-
-	if (isnan(acos(x)) == 0)
-		atf_tc_fail_nonfatal("acos(-Inf) != NaN");
-#endif
-}
-
-ATF_TC(acos_inf_pos);
-ATF_TC_HEAD(acos_inf_pos, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(+Inf) == NaN");
-}
+#define T_LIBM_CHECK(fn, arg, expect, epsilon) do { \
+	double r = fn(arg); \
+	double e = fabs(r - expect); \
+	if (e > epsilon) \
+		atf_tc_fail_nonfatal(#fn "(%g) is %g not %g (error %g > %g)", \
+			arg, r, expect, e, epsilon); \
+    } while (0)
+
+/* Check that the result of fn(arg) is NaN */
+#ifndef __vax__
+#define T_LIBM_CHECK_NAN(fn, arg) do { \
+	double r = fn(arg); \
+	if (!isnan(r)) \
+		atf_tc_fail_nonfatal(#fn "(%g) is %g not NaN", arg, r); \
+    } while (0)
+#else
+/* vax doesn't support NaN */
+#define T_LIBM_CHECK_NAN(fn, arg) (void)(arg)
+#endif
+
+#define AFT_LIBM_TEST(name, description) \
+ATF_TC(name); \
+ATF_TC_HEAD(name, tc) { atf_tc_set_md_var(tc, "descr", description); } \
+ATF_TC_BODY(name, tc)
 
-ATF_TC_BODY(acos_inf_pos, tc)
-{
-#ifndef __vax__
-	const double x = 1.0L / 0.0L;
-
-	if (isnan(acos(x)) == 0)
-		atf_tc_fail_nonfatal("acos(+Inf) != NaN");
-#endif
-}
-
-ATF_TC(acos_one_pos);
-ATF_TC_HEAD(acos_one_pos, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(1.0) == +0.0");
-}
-
-ATF_TC_BODY(acos_one_pos, tc)
-{
-#ifndef __vax__
-	const double y = acos(1.0);
-
-	if (fabs(y) > 0.0 || signbit(y) != 0)
-		atf_tc_fail_nonfatal("acos(1.0) != +0.0");
-#endif
-}
-
-ATF_TC(acos_range);
-ATF_TC_HEAD(acos_range, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(x) == NaN, x < -1, x > 1");
-}
+/*
+ * acos(3) and acosf(3)
+ */
 
-ATF_TC_BODY(acos_range, tc)
+AFT_LIBM_TEST(acos_nan, "Test acos/acosf(x) == NaN, x = NaN, +/-Inf, ![-1..1]")
 {
-#ifndef __vax__
-	const double x[] = { -1.1, -1.000000001, 1.1, 1.000000001 };
+	static const double x[] = {
+	    -1.000000001, 1.000000001,
+	    -1.0000001, 1.0000001,
+	    -1.1, 1.1,
+	    0.0L / 0.0L,  /* NAN */
+	    -1.0L / 0.0L, /* -Inf */
+	    +1.0L / 0.0L, /* +Inf */
+	};
 	size_t i;
 
 	for (i = 0; i < __arraycount(x); i++) {
-
-		if (isnan(acos(x[i])) == 0)
-			atf_tc_fail_nonfatal("acos(%f) != NaN", x[i]);
+		T_LIBM_CHECK_NAN(acos, x[i]);
+		if (i < 2)
+			/* Values are too small for float */
+			continue;
+		T_LIBM_CHECK_NAN(acosf, x[i]);
 	}
-#endif
-}
-
-ATF_TC(acos_inrange);
-ATF_TC_HEAD(acos_inrange, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acos(x) for some values");
 }
 
-ATF_TC_BODY(acos_inrange, tc)
+AFT_LIBM_TEST(acos_inrange, "Test acos/acosf(x) for some valid values")
 {
-#ifndef __vax__
-	const double eps = 1.0e-15;
-	double x;
-	double y;
+	static const struct {
+		double x;
+		double y;
+	} values[] = {
+		{ -1,    M_PI,              },
+		{ -0.99, 3.000053180265366, },
+		{ -0.5,  2.094395102393195, },
+		{ -0.1,  1.670963747956456, },
+		{  0,    M_PI / 2,          },
+		{  0.1,  1.470628905633337, },
+		{  0.5,  1.047197551196598, },
+		{  0.99, 0.141539473324427, },
+	};
 	size_t i;
 
+	/*
+	 * Note that acos(x) might be calcualted as atan((1-x*x)/x).
+	 * This means that acos(-1) is atan(-0.0), if the sign is lost
+	 * the value will be 0 (atan(+0)) not M_PI.
+	 */
+
 	for (i = 0; i < __arraycount(values); i++) {
-		x = values[i].x;
-		y = values[i].y;
-		if (fabs(acos(x) - y) > eps)
-			atf_tc_fail_nonfatal("acos(%g) != %g", x, y);
+		T_LIBM_CHECK(acos, values[i].x, values[i].y, 1.0e-15);
+		T_LIBM_CHECK(acosf, values[i].x, values[i].y, 1.0e-5);
 	}
-#endif
 }
 
-/*
- * acosf(3)
- */
-ATF_TC(acosf_nan);
-ATF_TC_HEAD(acosf_nan, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(NaN) == NaN");
-}
-
-ATF_TC_BODY(acosf_nan, tc)
-{
-#ifndef __vax__
-	const float x = 0.0L / 0.0L;
-
-	if (isnan(acosf(x)) == 0)
-		atf_tc_fail_nonfatal("acosf(NaN) != NaN");
-#endif
-}
-
-ATF_TC(acosf_inf_neg);
-ATF_TC_HEAD(acosf_inf_neg, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(-Inf) == NaN");
-}
-
-ATF_TC_BODY(acosf_inf_neg, tc)
+AFT_LIBM_TEST(acos_one_pos, "Test acos(1.0) == +0.0")
 {
 #ifndef __vax__
-	const float x = -1.0L / 0.0L;
-
-	if (isnan(acosf(x)) == 0)
-		atf_tc_fail_nonfatal("acosf(-Inf) != NaN");
-#endif
-}
-
-ATF_TC(acosf_inf_pos);
-ATF_TC_HEAD(acosf_inf_pos, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(+Inf) == NaN");
-}
-
-ATF_TC_BODY(acosf_inf_pos, tc)
-{
-#ifndef __vax__
-	const float x = 1.0L / 0.0L;
+	const double y = acos(1.0);
 
-	if (isnan(acosf(x)) == 0)
-		atf_tc_fail_nonfatal("acosf(+Inf) != NaN");
+	if (fabs(y) > 0.0 || signbit(y) != 0)
+		atf_tc_fail_nonfatal("acos(1.0) != +0.0");
 #endif
 }
 
-ATF_TC(acosf_one_pos);
-ATF_TC_HEAD(acosf_one_pos, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(1.0) == +0.0");
-}
-
-ATF_TC_BODY(acosf_one_pos, tc)
+AFT_LIBM_TEST(acosf_one_pos, "Test acosf(1.0) == +0.0")
 {
 #ifndef __vax__
 	const float y = acosf(1.0);
@@ -223,65 +135,13 @@ ATF_TC_BODY(acosf_one_pos, tc)
 #endif
 }
 
-ATF_TC(acosf_range);
-ATF_TC_HEAD(acosf_range, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(x) == NaN, x < -1, x > 1");
-}
-
-ATF_TC_BODY(acosf_range, tc)
-{
-#ifndef __vax__
-	const float x[] = { -1.1, -1.0000001, 1.1, 1.0000001 };
-	size_t i;
-
-	for (i = 0; i < __arraycount(x); i++) {
-
-		if (isnan(acosf(x[i])) == 0)
-			atf_tc_fail_nonfatal("acosf(%f) != NaN", x[i]);
-	}
-#endif
-}
-
-ATF_TC(acosf_inrange);
-ATF_TC_HEAD(acosf_inrange, tc)
-{
-	atf_tc_set_md_var(tc, "descr", "Test acosf(x) for some values");
-}
-
-ATF_TC_BODY(acosf_inrange, tc)
-{
-#ifndef __vax__
-	const float eps = 1.0e-5;
-	float x;
-	float y;
-	size_t i;
-
-	for (i = 0; i < __arraycount(values); i++) {
-		x = values[i].x;
-		y = values[i].y;
-		if (fabsf(acosf(x) - y) > eps)
-			atf_tc_fail_nonfatal("acosf(%g) != %g", x, y);
-	}
-#endif
-}
-
 ATF_TP_ADD_TCS(tp)
 {
 
 	ATF_TP_ADD_TC(tp, acos_nan);
-	ATF_TP_ADD_TC(tp, acos_inf_neg);
-	ATF_TP_ADD_TC(tp, acos_inf_pos);
-	ATF_TP_ADD_TC(tp, acos_one_pos);
-	ATF_TP_ADD_TC(tp, acos_range);
 	ATF_TP_ADD_TC(tp, acos_inrange);
-
-	ATF_TP_ADD_TC(tp, acosf_nan);
-	ATF_TP_ADD_TC(tp, acosf_inf_neg);
-	ATF_TP_ADD_TC(tp, acosf_inf_pos);
+	ATF_TP_ADD_TC(tp, acos_one_pos);
 	ATF_TP_ADD_TC(tp, acosf_one_pos);
-	ATF_TP_ADD_TC(tp, acosf_range);
-	ATF_TP_ADD_TC(tp, acosf_inrange);
 
 	return atf_no_error();
 }

Reply via email to