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