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();
}