xref: /netbsd-src/tests/lib/libc/gen/t_fpclassify.c (revision 9bda4630351909a1a74baa7c5b3e2fbb1553b941)
1*9bda4630Sriastradh /* $NetBSD: t_fpclassify.c,v 1.6 2024/05/09 14:44:39 riastradh Exp $ */
24a45a29aSjruoho 
34a45a29aSjruoho /*-
44a45a29aSjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
54a45a29aSjruoho  * All rights reserved.
64a45a29aSjruoho  *
74a45a29aSjruoho  * Redistribution and use in source and binary forms, with or without
84a45a29aSjruoho  * modification, are permitted provided that the following conditions
94a45a29aSjruoho  * are met:
104a45a29aSjruoho  * 1. Redistributions of source code must retain the above copyright
114a45a29aSjruoho  *    notice, this list of conditions and the following disclaimer.
124a45a29aSjruoho  * 2. Redistributions in binary form must reproduce the above copyright
134a45a29aSjruoho  *    notice, this list of conditions and the following disclaimer in the
144a45a29aSjruoho  *    documentation and/or other materials provided with the distribution.
154a45a29aSjruoho  *
164a45a29aSjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
174a45a29aSjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
184a45a29aSjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
194a45a29aSjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
204a45a29aSjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
214a45a29aSjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
224a45a29aSjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
234a45a29aSjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
244a45a29aSjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
254a45a29aSjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
264a45a29aSjruoho  * POSSIBILITY OF SUCH DAMAGE.
274a45a29aSjruoho  */
284a45a29aSjruoho 
294a45a29aSjruoho #include <atf-c.h>
304a45a29aSjruoho 
314a45a29aSjruoho #include <float.h>
324a45a29aSjruoho #include <math.h>
334a45a29aSjruoho #include <stdio.h>
344a45a29aSjruoho #include <string.h>
354a45a29aSjruoho 
364a45a29aSjruoho ATF_TC(fpclassify_float);
ATF_TC_HEAD(fpclassify_float,tc)374a45a29aSjruoho ATF_TC_HEAD(fpclassify_float, tc)
384a45a29aSjruoho {
394a45a29aSjruoho 
404a45a29aSjruoho 	atf_tc_set_md_var(tc, "descr", "Test float operations");
414a45a29aSjruoho }
424a45a29aSjruoho 
ATF_TC_BODY(fpclassify_float,tc)434a45a29aSjruoho ATF_TC_BODY(fpclassify_float, tc)
444a45a29aSjruoho {
454a45a29aSjruoho 	float d0, d1, d2, f, ip;
464a45a29aSjruoho 	int e, i;
474a45a29aSjruoho 
484a45a29aSjruoho 	d0 = FLT_MIN;
4922479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL,
5022479c33Sriastradh 	    "fpclassify(%a)=%d FP_NORMAL=%d",
5122479c33Sriastradh 	    d0, fpclassify(d0), FP_NORMAL);
524a45a29aSjruoho 	f = frexpf(d0, &e);
5322479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, FLT_MIN_EXP,
5422479c33Sriastradh 	    "frexpf(%a) returned normalized %a, exponent %d;"
5522479c33Sriastradh 	    " expected normalized %a, exponent %d",
5622479c33Sriastradh 	    d0, f, e, 0.5, FLT_MIN_EXP);
5722479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0.5,
5822479c33Sriastradh 	    "frexpf(%a) returned normalized %a, exponent %d;"
5922479c33Sriastradh 	    " expected normalized %a, exponent %d",
6022479c33Sriastradh 	    d0, f, e, 0.5, FLT_MIN_EXP);
614a45a29aSjruoho 	d1 = d0;
624a45a29aSjruoho 
63*9bda4630Sriastradh #ifdef __FLT_HAS_DENORM__
644a45a29aSjruoho 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
654a45a29aSjruoho 	for (i = 1; i < FLT_MANT_DIG; i++) {
664a45a29aSjruoho 		d1 /= 2;
6722479c33Sriastradh 		ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL,
6822479c33Sriastradh 		    "[%d] fpclassify(%a)=%d FP_SUBNORMAL=%d",
6922479c33Sriastradh 		    i, d1, fpclassify(d1), FP_SUBNORMAL);
7022479c33Sriastradh 		ATF_CHECK_MSG(d1 > 0 && d1 < d0,
7122479c33Sriastradh 		    "[%d] d1=%a d0=%a", i, d1, d0);
724a45a29aSjruoho 
734a45a29aSjruoho 		d2 = ldexpf(d0, -i);
7422479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexpf(%a, -%d)=%a != %a",
7522479c33Sriastradh 		    i, d0, i, d2, d1);
764a45a29aSjruoho 
774a45a29aSjruoho 		d2 = modff(d1, &ip);
7822479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1,
7922479c33Sriastradh 		    "[%d] modff(%a) returned int %a, frac %a;"
8022479c33Sriastradh 		    " expected int %a, frac %a",
8122479c33Sriastradh 		    i, d1, ip, d2, 0., d1);
8222479c33Sriastradh 		ATF_CHECK_EQ_MSG(ip, 0,
8322479c33Sriastradh 		    "[%d] modff(%a) returned int %a, frac %a;"
8422479c33Sriastradh 		    " expected int %a, frac %a",
8522479c33Sriastradh 		    i, d1, ip, d2, 0., d1);
864a45a29aSjruoho 
874a45a29aSjruoho 		f = frexpf(d1, &e);
8822479c33Sriastradh 		ATF_CHECK_EQ_MSG(e, FLT_MIN_EXP - i,
8922479c33Sriastradh 		    "[%d] frexpf(%a) returned normalized %a, exponent %d;"
9022479c33Sriastradh 		    " expected normalized %a, exponent %d",
9122479c33Sriastradh 		    i, d1, f, e, 0.5, FLT_MIN_EXP - i);
9222479c33Sriastradh 		ATF_CHECK_EQ_MSG(f, 0.5,
9322479c33Sriastradh 		    "[%d] frexpf(%a) returned normalized %a, exponent %d;"
9422479c33Sriastradh 		    " expected normalized %a, exponent %d",
9522479c33Sriastradh 		    i, d1, f, e, 0.5, FLT_MIN_EXP - i);
964a45a29aSjruoho 	}
97*9bda4630Sriastradh #endif
984a45a29aSjruoho 
994a45a29aSjruoho 	d1 /= 2;
10022479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO,
10122479c33Sriastradh 	    "fpclassify(%a)=%d FP_ZERO=%d",
10222479c33Sriastradh 	    d1, fpclassify(d1), FP_ZERO);
1034a45a29aSjruoho 	f = frexpf(d1, &e);
10422479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, 0,
10522479c33Sriastradh 	    "frexpf(%a) returned normalized %a, exponent %d;"
10622479c33Sriastradh 	    " expected normalized %a, exponent %d",
10722479c33Sriastradh 	    d1, f, e, 0., 0);
10822479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0,
10922479c33Sriastradh 	    "frexpf(%a) returned normalized %a, exponent %d;"
11022479c33Sriastradh 	    " expected normalized %a, exponent %d",
11122479c33Sriastradh 	    d1, f, e, 0., 0);
1124a45a29aSjruoho }
1134a45a29aSjruoho 
1144a45a29aSjruoho ATF_TC(fpclassify_double);
ATF_TC_HEAD(fpclassify_double,tc)1154a45a29aSjruoho ATF_TC_HEAD(fpclassify_double, tc)
1164a45a29aSjruoho {
1174a45a29aSjruoho 
1184a45a29aSjruoho 	atf_tc_set_md_var(tc, "descr", "Test double operations");
1194a45a29aSjruoho }
1204a45a29aSjruoho 
ATF_TC_BODY(fpclassify_double,tc)1214a45a29aSjruoho ATF_TC_BODY(fpclassify_double, tc)
1224a45a29aSjruoho {
1234a45a29aSjruoho 	double d0, d1, d2, f, ip;
1244a45a29aSjruoho 	int e, i;
1254a45a29aSjruoho 
1264a45a29aSjruoho 	d0 = DBL_MIN;
12722479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL,
12822479c33Sriastradh 	    "fpclassify(%a)=%d FP_NORMAL=%d",
12922479c33Sriastradh 	    d0, fpclassify(d0), FP_NORMAL);
1304a45a29aSjruoho 	f = frexp(d0, &e);
13122479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, DBL_MIN_EXP,
13222479c33Sriastradh 	    "frexp(%a) returned normalized %a, exponent %d;"
13322479c33Sriastradh 	    " expected normalized %a, exponent %d",
13422479c33Sriastradh 	    d0, f, e, 0.5, DBL_MIN_EXP);
13522479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0.5,
13622479c33Sriastradh 	    "frexp(%a) returned normalized %a, exponent %d;"
13722479c33Sriastradh 	    " expected normalized %a, exponent %d",
13822479c33Sriastradh 	    d0, f, e, 0.5, DBL_MIN_EXP);
1394a45a29aSjruoho 	d1 = d0;
1404a45a29aSjruoho 
141*9bda4630Sriastradh #ifdef __DBL_HAS_DENORM__
1424a45a29aSjruoho 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
1434a45a29aSjruoho 	for (i = 1; i < DBL_MANT_DIG; i++) {
1444a45a29aSjruoho 		d1 /= 2;
14522479c33Sriastradh 		ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL,
14622479c33Sriastradh 		    "[%d] fpclassify(%a)=%d FP_SUBNORMAL=%d",
14722479c33Sriastradh 		    i, d1, fpclassify(d1), FP_SUBNORMAL);
14822479c33Sriastradh 		ATF_CHECK_MSG(d1 > 0 && d1 < d0,
14922479c33Sriastradh 		    "[%d] d1=%a d0=%a", i, d1, d0);
1504a45a29aSjruoho 
1514a45a29aSjruoho 		d2 = ldexp(d0, -i);
15222479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexp(%a, -%d)=%a != %a",
15322479c33Sriastradh 		    i, d0, i, d2, d1);
1544a45a29aSjruoho 
1554a45a29aSjruoho 		d2 = modf(d1, &ip);
15622479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1,
15722479c33Sriastradh 		    "[%d] modf(%a) returned int %a, frac %a;"
15822479c33Sriastradh 		    " expected int %a, frac %a",
15922479c33Sriastradh 		    i, d1, ip, d2, 0., d1);
16022479c33Sriastradh 		ATF_CHECK_EQ_MSG(ip, 0,
16122479c33Sriastradh 		    "[%d] modf(%a) returned int %a, frac %a;"
16222479c33Sriastradh 		    " expected int %a, frac %a",
16322479c33Sriastradh 		    i, d1, ip, d2, 0., d1);
1644a45a29aSjruoho 
1654a45a29aSjruoho 		f = frexp(d1, &e);
16622479c33Sriastradh 		ATF_CHECK_EQ_MSG(e, DBL_MIN_EXP - i,
16722479c33Sriastradh 		    "[%d] frexp(%a) returned normalized %a, exponent %d;"
16822479c33Sriastradh 		    " expected normalized %a, exponent %d",
16922479c33Sriastradh 		    i, d1, f, e, 0.5, DBL_MIN_EXP - i);
17022479c33Sriastradh 		ATF_CHECK_EQ_MSG(f, 0.5,
17122479c33Sriastradh 		    "[%d] frexp(%a) returned normalized %a, exponent %d;"
17222479c33Sriastradh 		    " expected normalized %a, exponent %d",
17322479c33Sriastradh 		    i, d1, f, e, 0.5, DBL_MIN_EXP - i);
1744a45a29aSjruoho 	}
175*9bda4630Sriastradh #endif
1764a45a29aSjruoho 
1774a45a29aSjruoho 	d1 /= 2;
17822479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO,
17922479c33Sriastradh 	    "fpclassify(%a)=%d FP_ZERO=%d",
18022479c33Sriastradh 	    d1, fpclassify(d1), FP_ZERO);
1814a45a29aSjruoho 	f = frexp(d1, &e);
18222479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, 0,
18322479c33Sriastradh 	    "frexp(%a) returned normalized %a, exponent %d;"
18422479c33Sriastradh 	    " expected normalized %a, exponent %d",
18522479c33Sriastradh 	    d1, f, e, 0., 0);
18622479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0,
18722479c33Sriastradh 	    "frexp(%a) returned normalized %a, exponent %d;"
18822479c33Sriastradh 	    " expected normalized %a, exponent %d",
18922479c33Sriastradh 	    d1, f, e, 0., 0);
1904a45a29aSjruoho }
1914a45a29aSjruoho 
1924a45a29aSjruoho ATF_TC(fpclassify_long_double);
ATF_TC_HEAD(fpclassify_long_double,tc)1934a45a29aSjruoho ATF_TC_HEAD(fpclassify_long_double, tc)
1944a45a29aSjruoho {
1954a45a29aSjruoho 
1964a45a29aSjruoho 	atf_tc_set_md_var(tc, "descr", "Test long double operations");
1974a45a29aSjruoho }
1984a45a29aSjruoho 
ATF_TC_BODY(fpclassify_long_double,tc)1994a45a29aSjruoho ATF_TC_BODY(fpclassify_long_double, tc)
2004a45a29aSjruoho {
2014a45a29aSjruoho 	long double d0, d1, d2, f, ip;
2024a45a29aSjruoho 	int e, i;
2034a45a29aSjruoho 
2044a45a29aSjruoho 	d0 = LDBL_MIN;
20522479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL,
20622479c33Sriastradh 	    "fpclassify(%La)=%d FP_NORMAL=%d",
20722479c33Sriastradh 	    d0, fpclassify(d0), FP_NORMAL);
2084a45a29aSjruoho 	f = frexpl(d0, &e);
20922479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, LDBL_MIN_EXP,
21022479c33Sriastradh 	    "frexpl(%La) returned normalized %La, exponent %d;"
21122479c33Sriastradh 	    " expected normalized %La, exponent %d",
21222479c33Sriastradh 	    d0, f, e, 0.5L, LDBL_MIN_EXP);
21322479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0.5,
21422479c33Sriastradh 	    "frexpl(%La) returned normalized %La, exponent %d;"
21522479c33Sriastradh 	    " expected normalized %La, exponent %d",
21622479c33Sriastradh 	    d0, f, e, 0.5L, LDBL_MIN_EXP);
2174a45a29aSjruoho 	d1 = d0;
2184a45a29aSjruoho 
219*9bda4630Sriastradh #ifdef __LDBL_HAS_DENORM__
2204a45a29aSjruoho 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
2214a45a29aSjruoho 	for (i = 1; i < LDBL_MANT_DIG; i++) {
2224a45a29aSjruoho 		d1 /= 2;
22322479c33Sriastradh 		ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL,
22422479c33Sriastradh 		    "[%d] fpclassify(%La)=%d FP_SUBNORMAL=%d",
22522479c33Sriastradh 		    i, d1, fpclassify(d1), FP_SUBNORMAL);
22622479c33Sriastradh 		ATF_CHECK_MSG(d1 > 0 && d1 < d0,
22722479c33Sriastradh 		    "[%d] d1=%La d0=%La", i, d1, d0);
2284a45a29aSjruoho 
2294a45a29aSjruoho 		d2 = ldexpl(d0, -i);
23022479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexpl(%La, -%d)=%La != %La",
23122479c33Sriastradh 		    i, d0, i, d2, d1);
2324a45a29aSjruoho 
2334a45a29aSjruoho 		d2 = modfl(d1, &ip);
23422479c33Sriastradh 		ATF_CHECK_EQ_MSG(d2, d1,
23522479c33Sriastradh 		    "[%d] modfl(%La) returned int %La, frac %La;"
23622479c33Sriastradh 		    " expected int %La, frac %La",
23722479c33Sriastradh 		    i, d1, ip, d2, 0.L, d1);
23822479c33Sriastradh 		ATF_CHECK_EQ_MSG(ip, 0,
23922479c33Sriastradh 		    "[%d] modfl(%La) returned int %La, frac %La;"
24022479c33Sriastradh 		    " expected int %La, frac %La",
24122479c33Sriastradh 		    i, d1, ip, d2, 0.L, d1);
2424a45a29aSjruoho 
2434a45a29aSjruoho 		f = frexpl(d1, &e);
24422479c33Sriastradh 		ATF_CHECK_EQ_MSG(e, LDBL_MIN_EXP - i,
24522479c33Sriastradh 		    "[%d] frexpl(%La) returned normalized %La, exponent %d;"
24622479c33Sriastradh 		    " expected normalized %La, exponent %d",
24722479c33Sriastradh 		    i, d1, f, e, 0.5L, LDBL_MIN_EXP - i);
24822479c33Sriastradh 		ATF_CHECK_EQ_MSG(f, 0.5,
24922479c33Sriastradh 		    "[%d] frexpl(%La) returned normalized %La, exponent %d;"
25022479c33Sriastradh 		    " expected normalized %La, exponent %d",
25122479c33Sriastradh 		    i, d1, f, e, 0.5L, LDBL_MIN_EXP - i);
2524a45a29aSjruoho 	}
253*9bda4630Sriastradh #endif
2544a45a29aSjruoho 
2554a45a29aSjruoho 	d1 /= 2;
25622479c33Sriastradh 	ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO,
25722479c33Sriastradh 	    "fpclassify(%La)=%d FP_ZERO=%d",
25822479c33Sriastradh 	    d1, fpclassify(d1), FP_ZERO);
2594a45a29aSjruoho 	f = frexpl(d1, &e);
26022479c33Sriastradh 	ATF_CHECK_EQ_MSG(e, 0,
26122479c33Sriastradh 	    "frexpl(%La) returned normalized %La, exponent %d;"
26222479c33Sriastradh 	    " expected normalized %La, exponent %d",
26322479c33Sriastradh 	    d1, f, e, 0.L, 0);
26422479c33Sriastradh 	ATF_CHECK_EQ_MSG(f, 0,
26522479c33Sriastradh 	    "frexpl(%La) returned normalized %La, exponent %d;"
26622479c33Sriastradh 	    " expected normalized %La, exponent %d",
26722479c33Sriastradh 	    d1, f, e, 0.L, 0);
2684a45a29aSjruoho }
269d48db9a5Sriastradh 
ATF_TP_ADD_TCS(tp)2704a45a29aSjruoho ATF_TP_ADD_TCS(tp)
2714a45a29aSjruoho {
2724a45a29aSjruoho 
2734a45a29aSjruoho 	ATF_TP_ADD_TC(tp, fpclassify_float);
2744a45a29aSjruoho 	ATF_TP_ADD_TC(tp, fpclassify_double);
2754a45a29aSjruoho 	ATF_TP_ADD_TC(tp, fpclassify_long_double);
2764a45a29aSjruoho 
2774a45a29aSjruoho 	return atf_no_error();
2784a45a29aSjruoho }
279