Module Name:    src
Committed By:   riastradh
Date:           Mon May  6 00:54:02 UTC 2024

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

Log Message:
tests/lib/libm/t_modf.c: Expand modf/modff/modfl tests.

1. Exercise more edge cases around the largest exponent that can
   represent non-integers.

2. - Verify modf can handle all cases modff can.
   - Veriy modf can handle some cases modff can't.
   - Verify modfl can handle all cases modf or modff can.
   - If long double isn't just double, verify modfl can handle some
     cases modf and modff can't.

3. Check infinities and NaN.

4. Verify oddness, i.e., modf(-x) = -modf(x).

5. Display more useful diagnostics in case any of this goes wrong.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libm/t_modf.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_modf.c
diff -u src/tests/lib/libm/t_modf.c:1.1 src/tests/lib/libm/t_modf.c:1.2
--- src/tests/lib/libm/t_modf.c:1.1	Mon Jun 16 12:54:43 2014
+++ src/tests/lib/libm/t_modf.c	Mon May  6 00:54:02 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: t_modf.c,v 1.1 2014/06/16 12:54:43 joerg Exp $ */
+/*	$NetBSD: t_modf.c,v 1.2 2024/05/06 00:54:02 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -29,40 +29,417 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_modf.c,v 1.2 2024/05/06 00:54:02 riastradh Exp $");
+
 #include <atf-c.h>
 #include <float.h>
 #include <math.h>
 
+__CTASSERT(FLT_RADIX == 2);
+
+static const struct {
+	float x, i, f;
+} casesf[] = {
+	{ 0, 0, 0 },
+	{ FLT_MIN, 0, FLT_MIN },
+	{ 0.5, 0, 0.5 },
+	{ 1 - FLT_EPSILON/2, 0, 1 - FLT_EPSILON/2 },
+	{ 1, 1, 0 },
+	{ 1 + FLT_EPSILON, 1, FLT_EPSILON },
+	{ 0.5/FLT_EPSILON - 0.5, 0.5/FLT_EPSILON - 1, 0.5 },
+	{ 0.5/FLT_EPSILON, 0.5/FLT_EPSILON, 0 },
+	{ 0.5/FLT_EPSILON + 0.5, 0.5/FLT_EPSILON, 0.5 },
+	{ 1/FLT_EPSILON, 1/FLT_EPSILON, 0 },
+};
+
+static const struct {
+	double x, i, f;
+} cases[] = {
+	{ 0, 0, 0 },
+	{ DBL_MIN, 0, DBL_MIN },
+	{ 0.5, 0, 0.5 },
+	{ 1 - DBL_EPSILON/2, 0, 1 - DBL_EPSILON/2 },
+	{ 1, 1, 0 },
+	{ 1 + DBL_EPSILON, 1, DBL_EPSILON },
+	{ 1/FLT_EPSILON + 0.5, 1/FLT_EPSILON, 0.5 },
+	{ 0.5/DBL_EPSILON - 0.5, 0.5/DBL_EPSILON - 1, 0.5 },
+	{ 0.5/DBL_EPSILON, 0.5/DBL_EPSILON, 0 },
+	{ 0.5/DBL_EPSILON + 0.5, 0.5/DBL_EPSILON, 0.5 },
+	{ 1/DBL_EPSILON, 1/DBL_EPSILON, 0 },
+};
+
+#ifdef __HAVE_LONG_DOUBLE
+static const struct {
+	long double x, i, f;
+} casesl[] = {
+	{ 0, 0, 0 },
+	{ LDBL_MIN, 0, LDBL_MIN },
+	{ 0.5, 0, 0.5 },
+	{ 1 - LDBL_EPSILON/2, 0, 1 - LDBL_EPSILON/2 },
+	{ 1, 1, 0 },
+	{ 1 + LDBL_EPSILON, 1, LDBL_EPSILON },
+	{ 1.0L/DBL_EPSILON + 0.5L, 1.0L/DBL_EPSILON, 0.5 },
+	{ 0.5/LDBL_EPSILON - 0.5L, 0.5/LDBL_EPSILON - 1, 0.5 },
+	{ 0.5/LDBL_EPSILON, 0.5/LDBL_EPSILON, 0 },
+	{ 0.5/LDBL_EPSILON + 0.5L, 0.5/LDBL_EPSILON, 0.5 },
+	{ 1/LDBL_EPSILON, 1/LDBL_EPSILON, 0 },
+};
+#endif	/* __HAVE_LONG_DOUBLE */
+
+ATF_TC(modff);
+ATF_TC_HEAD(modff, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "modff(3)");
+}
+ATF_TC_BODY(modff, tc)
+{
+	unsigned n;
+
+	for (n = 0; n < __arraycount(casesf); n++) {
+		float x, i, f;
+
+		x = casesf[n].x;
+		f = modff(x, &i);
+		ATF_CHECK_EQ_MSG(i, casesf[n].i,
+		    "casesf[%u]: modff %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, casesf[n].f,
+		    "casesf[%u]: modff %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+
+		f = modff(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -casesf[n].i,
+		    "casesf[%u]: modff %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, -casesf[n].f,
+		    "casesf[%u]: modff %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+	}
+
+#ifdef INFINITY
+	{
+		float x, i, f;
+
+		x = INFINITY;
+		f = modff(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modff +inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modff +inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+
+		x = -INFINITY;
+		f = modff(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modff -inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modff -inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+	}
+#endif	/* INFINITY */
+
+#ifdef NAN
+	{
+		float x, i, f;
+
+		x = NAN;
+		f = modff(x, &i);
+		ATF_CHECK_MSG(isnan(f),
+		    "modff NaN returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isnan(i),
+		    "modff NaN returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+	}
+#endif	/* NAN */
+}
+
 ATF_TC(modf);
 ATF_TC_HEAD(modf, tc)
 {
-	atf_tc_set_md_var(tc, "descr","Check modf family");
+	atf_tc_set_md_var(tc, "descr", "modf(3)");
 }
-
 ATF_TC_BODY(modf, tc)
 {
-	float basef;
-	double base;
-	long double basel;
-	ATF_CHECK(modff(1.0, &basef) == 0.0);
-	ATF_CHECK(basef == 1.0);
-	ATF_CHECK(modf(1.0, &base) == 0.0);
-	ATF_CHECK(base == 1.0);
-	ATF_CHECK(modfl(1.0, &basel) == 0.0);
-	ATF_CHECK(basel == 1.0);
-
-	ATF_CHECK(modff(-1 - FLT_EPSILON, &basef) == -FLT_EPSILON);
-	ATF_CHECK(basef == -1.0);
-	ATF_CHECK(modf(-1 - DBL_EPSILON, &base) == -DBL_EPSILON);
-	ATF_CHECK(base == -1.0);
-	ATF_CHECK(modfl(-1 - LDBL_EPSILON, &basel) == -LDBL_EPSILON);
-	ATF_CHECK(basel == -1.0);
+	unsigned n;
+
+	for (n = 0; n < __arraycount(casesf); n++) {
+		double x, i, f;
+
+		x = casesf[n].x;
+		f = modf(x, &i);
+		ATF_CHECK_EQ_MSG(i, casesf[n].i,
+		    "casesf[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, casesf[n].f,
+		    "casesf[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+
+		f = modf(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -casesf[n].i,
+		    "casesf[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, -casesf[n].f,
+		    "casesf[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+	}
+
+	for (n = 0; n < __arraycount(cases); n++) {
+		double x, i, f;
+
+		x = cases[n].x;
+		f = modf(x, &i);
+		ATF_CHECK_EQ_MSG(i, cases[n].i,
+		    "cases[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+		ATF_CHECK_EQ_MSG(f, cases[n].f,
+		    "cases[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+
+		f = modf(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -cases[n].i,
+		    "cases[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+		ATF_CHECK_EQ_MSG(f, -cases[n].f,
+		    "cases[%u]: modf %g=%a"
+		    " returned integer %g=%a, frac %g=%a;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+	}
+
+#ifdef INFINITY
+	{
+		double x, i, f;
+
+		x = INFINITY;
+		f = modf(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modf +inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modf +inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+
+		x = -INFINITY;
+		f = modf(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modf -inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modf -inf returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+	}
+#endif	/* INFINITY */
+
+#ifdef NAN
+	{
+		double x, i, f;
+
+		x = NAN;
+		f = modf(x, &i);
+		ATF_CHECK_MSG(isnan(f),
+		    "modf NaN returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isnan(i),
+		    "modf NaN returned integer %g=%a, frac %g=%a",
+		    i, i, f, f);
+	}
+#endif	/* NAN */
+}
+
+ATF_TC(modfl);
+ATF_TC_HEAD(modfl, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "modfl(3)");
+}
+ATF_TC_BODY(modfl, tc)
+{
+	unsigned n;
+
+	for (n = 0; n < __arraycount(casesf); n++) {
+		long double x, i, f;
+
+		x = casesf[n].x;
+		f = modfl(x, &i);
+		ATF_CHECK_EQ_MSG(i, casesf[n].i,
+		    "casesf[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, casesf[n].f,
+		    "casesf[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+
+		f = modfl(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -casesf[n].i,
+		    "casesf[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+		ATF_CHECK_EQ_MSG(f, -casesf[n].f,
+		    "casesf[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f);
+	}
+
+	for (n = 0; n < __arraycount(cases); n++) {
+		long double x, i, f;
+
+		x = cases[n].x;
+		f = modfl(x, &i);
+		ATF_CHECK_EQ_MSG(i, cases[n].i,
+		    "cases[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+		ATF_CHECK_EQ_MSG(f, cases[n].f,
+		    "cases[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+
+		f = modfl(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -cases[n].i,
+		    "cases[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+		ATF_CHECK_EQ_MSG(f, -cases[n].f,
+		    "cases[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %g=%a, frac %g=%a",
+		    n, x, x, i, i, f, f,
+		    cases[n].i, cases[n].i, cases[n].f, cases[n].f);
+	}
+
+#ifdef __HAVE_LONG_DOUBLE
+	for (n = 0; n < __arraycount(casesl); n++) {
+		long double x, i, f;
+
+		x = casesl[n].x;
+		f = modfl(x, &i);
+		ATF_CHECK_EQ_MSG(i, casesl[n].i,
+		    "casesl[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %Lg=%La, frac %Lg=%La",
+		    n, x, x, i, i, f, f,
+		    casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f);
+		ATF_CHECK_EQ_MSG(f, casesl[n].f,
+		    "casesl[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %Lg=%La, frac %Lg=%La",
+		    n, x, x, i, i, f, f,
+		    casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f);
+
+		f = modfl(-x, &i);
+		ATF_CHECK_EQ_MSG(i, -casesl[n].i,
+		    "casesl[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %Lg=%La, frac %Lg=%La",
+		    n, x, x, i, i, f, f,
+		    casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f);
+		ATF_CHECK_EQ_MSG(f, -casesl[n].f,
+		    "casesl[%u]: modfl %Lg=%La"
+		    " returned integer %Lg=%La, frac %Lg=%La;"
+		    " expected integer %Lg=%La, frac %Lg=%La",
+		    n, x, x, i, i, f, f,
+		    casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f);
+	}
+#endif	/* __HAVE_LONG_DOUBLE */
+
+#ifdef INFINITY
+	{
+		long double x, i, f;
+
+		x = INFINITY;
+		f = modfl(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modfl +inf returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modfl +inf returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+
+		x = -INFINITY;
+		f = modfl(x, &i);
+		ATF_CHECK_MSG(f == 0,
+		    "modfl -inf returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isinf(i),
+		    "modfl -inf returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+	}
+#endif
+
+#ifdef NAN
+	{
+		long double x, i, f;
+
+		x = NAN;
+		f = modfl(x, &i);
+		ATF_CHECK_MSG(isnan(f),
+		    "modfl NaN returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+		ATF_CHECK_MSG(isnan(i),
+		    "modfl NaN returned integer %Lg=%La, frac %Lg=%La",
+		    i, i, f, f);
+	}
+#endif
 }
 
 ATF_TP_ADD_TCS(tp)
 {
 
+	ATF_TP_ADD_TC(tp, modff);
 	ATF_TP_ADD_TC(tp, modf);
+	ATF_TP_ADD_TC(tp, modfl);
 
 	return atf_no_error();
 }

Reply via email to