xref: /netbsd-src/tests/lib/libm/t_scalbn.c (revision 6442493f2ffd9de79989674a2201aa1c86eff8b6)
1*6442493fSriastradh /* $NetBSD: t_scalbn.c,v 1.18 2024/06/09 16:53:12 riastradh Exp $ */
2e4094036Sjruoho 
3e4094036Sjruoho /*-
4e4094036Sjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5e4094036Sjruoho  * All rights reserved.
6e4094036Sjruoho  *
7e4094036Sjruoho  * This code is derived from software contributed to The NetBSD Foundation
8e4094036Sjruoho  * by Jukka Ruohonen.
9e4094036Sjruoho  *
10e4094036Sjruoho  * Redistribution and use in source and binary forms, with or without
11e4094036Sjruoho  * modification, are permitted provided that the following conditions
12e4094036Sjruoho  * are met:
13e4094036Sjruoho  * 1. Redistributions of source code must retain the above copyright
14e4094036Sjruoho  *    notice, this list of conditions and the following disclaimer.
15e4094036Sjruoho  * 2. Redistributions in binary form must reproduce the above copyright
16e4094036Sjruoho  *    notice, this list of conditions and the following disclaimer in the
17e4094036Sjruoho  *    documentation and/or other materials provided with the distribution.
18e4094036Sjruoho  *
19e4094036Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20e4094036Sjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21e4094036Sjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22e4094036Sjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23e4094036Sjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24e4094036Sjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25e4094036Sjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26e4094036Sjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27e4094036Sjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28e4094036Sjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29e4094036Sjruoho  * POSSIBILITY OF SUCH DAMAGE.
30e4094036Sjruoho  */
31e4094036Sjruoho #include <sys/cdefs.h>
32*6442493fSriastradh __RCSID("$NetBSD: t_scalbn.c,v 1.18 2024/06/09 16:53:12 riastradh Exp $");
33e4094036Sjruoho 
34e4094036Sjruoho #include <math.h>
35e4094036Sjruoho #include <limits.h>
3685d85a18Smartin #include <float.h>
3785d85a18Smartin #include <errno.h>
382b3568b3Smaya #include <fenv.h>
39e4094036Sjruoho 
40e4094036Sjruoho #include <atf-c.h>
41e4094036Sjruoho 
42e4094036Sjruoho static const int exps[] = { 0, 1, -1, 100, -100 };
43e4094036Sjruoho 
4485d85a18Smartin /* tests here do not require specific precision, so we just use double */
4585d85a18Smartin struct testcase {
4685d85a18Smartin 	int exp;
4785d85a18Smartin 	double inval;
4885d85a18Smartin 	double result;
4985d85a18Smartin 	int error;
502b3568b3Smaya 	int except;
5185d85a18Smartin };
5285d85a18Smartin struct testcase test_vals[] = {
532b3568b3Smaya 	{ 0,		1.00085,	1.00085,	0, 0 },
542b3568b3Smaya 	{ 0,		0.99755,	0.99755,	0, 0 },
552b3568b3Smaya 	{ 0,		-1.00085,	-1.00085,	0, 0 },
562b3568b3Smaya 	{ 0,		-0.99755,	-0.99755,	0, 0 },
572b3568b3Smaya 	{ 1,		1.00085,	2.0* 1.00085,	0, 0 },
582b3568b3Smaya 	{ 1,		0.99755,	2.0* 0.99755,	0, 0 },
592b3568b3Smaya 	{ 1,		-1.00085,	2.0* -1.00085,	0, 0 },
602b3568b3Smaya 	{ 1,		-0.99755,	2.0* -0.99755,	0, 0 },
6185d85a18Smartin 
6285d85a18Smartin 	/*
6385d85a18Smartin 	 * We could add more corner test cases here, but we would have to
6485d85a18Smartin 	 * add some ifdefs for the exact format and use a reliable
6585d85a18Smartin 	 * generator program - bail for now and only do trivial stuff above.
6685d85a18Smartin 	 */
6785d85a18Smartin };
6885d85a18Smartin 
69e4094036Sjruoho /*
70e4094036Sjruoho  * scalbn(3)
71e4094036Sjruoho  */
7285d85a18Smartin ATF_TC(scalbn_val);
ATF_TC_HEAD(scalbn_val,tc)7385d85a18Smartin ATF_TC_HEAD(scalbn_val, tc)
7485d85a18Smartin {
7585d85a18Smartin 	atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values");
7685d85a18Smartin }
7785d85a18Smartin 
ATF_TC_BODY(scalbn_val,tc)7885d85a18Smartin ATF_TC_BODY(scalbn_val, tc)
7985d85a18Smartin {
8085d85a18Smartin 	const struct testcase *tests = test_vals;
8185d85a18Smartin 	const size_t tcnt = __arraycount(test_vals);
8285d85a18Smartin 	size_t i;
8385d85a18Smartin 	double rv;
8485d85a18Smartin 
8585d85a18Smartin 	for (i = 0; i < tcnt; i++) {
86a5445b4eSagc 		errno = 0;
872b3568b3Smaya #ifndef __vax__
882b3568b3Smaya 		feclearexcept(FE_ALL_EXCEPT);
892b3568b3Smaya #endif
9085d85a18Smartin 		rv = scalbn(tests[i].inval, tests[i].exp);
9185d85a18Smartin 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
9285d85a18Smartin 		    "test %zu: errno %d instead of %d", i, errno,
9385d85a18Smartin 		    tests[i].error);
942b3568b3Smaya #ifndef __vax__
952b3568b3Smaya 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
962b3568b3Smaya 		    "test %zu: fetestexcept %d instead of %d", i,
972b3568b3Smaya 		    fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW),
982b3568b3Smaya 		    tests[i].except);
992b3568b3Smaya #endif
100a8a8e5f5Sriastradh 		/* scalbn is always exact except for underflow or overflow.  */
101a8a8e5f5Sriastradh 		ATF_CHECK_MSG(rv == tests[i].result,
102a8a8e5f5Sriastradh 		    "test %zu: return value %.17g instead of %.17g"
103a8a8e5f5Sriastradh 		    " (error %.17g)",
104a8a8e5f5Sriastradh 		    i, rv, tests[i].result,
105a8a8e5f5Sriastradh 		    fabs((tests[i].result - rv)/tests[i].result));
10685d85a18Smartin 	}
10785d85a18Smartin }
10885d85a18Smartin 
109e4094036Sjruoho ATF_TC(scalbn_nan);
ATF_TC_HEAD(scalbn_nan,tc)110e4094036Sjruoho ATF_TC_HEAD(scalbn_nan, tc)
111e4094036Sjruoho {
11295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN");
113e4094036Sjruoho }
114e4094036Sjruoho 
ATF_TC_BODY(scalbn_nan,tc)115e4094036Sjruoho ATF_TC_BODY(scalbn_nan, tc)
116e4094036Sjruoho {
117e4094036Sjruoho 	const double x = 0.0L / 0.0L;
118e4094036Sjruoho 	double y;
119e4094036Sjruoho 	size_t i;
120e4094036Sjruoho 
121173345a5Sjruoho 	ATF_REQUIRE(isnan(x) != 0);
122173345a5Sjruoho 
123e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
124e4094036Sjruoho 		y = scalbn(x, exps[i]);
125e4094036Sjruoho 		ATF_CHECK(isnan(y) != 0);
126e4094036Sjruoho 	}
127e4094036Sjruoho }
128e4094036Sjruoho 
129e4094036Sjruoho ATF_TC(scalbn_inf_neg);
ATF_TC_HEAD(scalbn_inf_neg,tc)130e4094036Sjruoho ATF_TC_HEAD(scalbn_inf_neg, tc)
131e4094036Sjruoho {
13295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf");
133e4094036Sjruoho }
134e4094036Sjruoho 
ATF_TC_BODY(scalbn_inf_neg,tc)135e4094036Sjruoho ATF_TC_BODY(scalbn_inf_neg, tc)
136e4094036Sjruoho {
137e4094036Sjruoho 	const double x = -1.0L / 0.0L;
138e4094036Sjruoho 	size_t i;
139e4094036Sjruoho 
140e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
141e4094036Sjruoho 		ATF_CHECK(scalbn(x, exps[i]) == x);
142e4094036Sjruoho }
143e4094036Sjruoho 
144e4094036Sjruoho ATF_TC(scalbn_inf_pos);
ATF_TC_HEAD(scalbn_inf_pos,tc)145e4094036Sjruoho ATF_TC_HEAD(scalbn_inf_pos, tc)
146e4094036Sjruoho {
14795a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf");
148e4094036Sjruoho }
149e4094036Sjruoho 
ATF_TC_BODY(scalbn_inf_pos,tc)150e4094036Sjruoho ATF_TC_BODY(scalbn_inf_pos, tc)
151e4094036Sjruoho {
152e4094036Sjruoho 	const double x = 1.0L / 0.0L;
153e4094036Sjruoho 	size_t i;
154e4094036Sjruoho 
155e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
156e4094036Sjruoho 		ATF_CHECK(scalbn(x, exps[i]) == x);
157e4094036Sjruoho }
158e4094036Sjruoho 
1598fa0fcafSjruoho ATF_TC(scalbn_ldexp);
ATF_TC_HEAD(scalbn_ldexp,tc)1608fa0fcafSjruoho ATF_TC_HEAD(scalbn_ldexp, tc)
1618fa0fcafSjruoho {
16295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)");
1638fa0fcafSjruoho }
1648fa0fcafSjruoho 
ATF_TC_BODY(scalbn_ldexp,tc)1658fa0fcafSjruoho ATF_TC_BODY(scalbn_ldexp, tc)
1668fa0fcafSjruoho {
1678fa0fcafSjruoho #if FLT_RADIX == 2
1688fa0fcafSjruoho 	const double x = 2.91288191221812821;
1698fa0fcafSjruoho 	double y;
1708fa0fcafSjruoho 	size_t i;
1718fa0fcafSjruoho 
1728fa0fcafSjruoho 	for (i = 0; i < __arraycount(exps); i++) {
1738fa0fcafSjruoho 		y = scalbn(x, exps[i]);
17485d85a18Smartin 		ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, "
17585d85a18Smartin 		    "y=%g, expected %g (diff: %g)", i, exps[i], y,
17685d85a18Smartin 		    ldexp(x, exps[i]), y - ldexp(x, exps[i]));
1778fa0fcafSjruoho 	}
1788fa0fcafSjruoho #endif
1798fa0fcafSjruoho }
1808fa0fcafSjruoho 
181e4094036Sjruoho ATF_TC(scalbn_zero_neg);
ATF_TC_HEAD(scalbn_zero_neg,tc)182e4094036Sjruoho ATF_TC_HEAD(scalbn_zero_neg, tc)
183e4094036Sjruoho {
18495a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0");
185e4094036Sjruoho }
186e4094036Sjruoho 
ATF_TC_BODY(scalbn_zero_neg,tc)187e4094036Sjruoho ATF_TC_BODY(scalbn_zero_neg, tc)
188e4094036Sjruoho {
189e4094036Sjruoho 	const double x = -0.0L;
190173345a5Sjruoho 	double y;
191e4094036Sjruoho 	size_t i;
192e4094036Sjruoho 
193173345a5Sjruoho 	ATF_REQUIRE(signbit(x) != 0);
194173345a5Sjruoho 
195173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
196173345a5Sjruoho 		y = scalbn(x, exps[i]);
197173345a5Sjruoho 		ATF_CHECK(x == y);
198173345a5Sjruoho 		ATF_CHECK(signbit(y) != 0);
199173345a5Sjruoho 	}
200e4094036Sjruoho }
201e4094036Sjruoho 
202e4094036Sjruoho ATF_TC(scalbn_zero_pos);
ATF_TC_HEAD(scalbn_zero_pos,tc)203e4094036Sjruoho ATF_TC_HEAD(scalbn_zero_pos, tc)
204e4094036Sjruoho {
20595a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0");
206e4094036Sjruoho }
207e4094036Sjruoho 
ATF_TC_BODY(scalbn_zero_pos,tc)208e4094036Sjruoho ATF_TC_BODY(scalbn_zero_pos, tc)
209e4094036Sjruoho {
210e4094036Sjruoho 	const double x = 0.0L;
211173345a5Sjruoho 	double y;
212e4094036Sjruoho 	size_t i;
213e4094036Sjruoho 
214173345a5Sjruoho 	ATF_REQUIRE(signbit(x) == 0);
215173345a5Sjruoho 
216173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
217173345a5Sjruoho 		y = scalbn(x, exps[i]);
218173345a5Sjruoho 		ATF_CHECK(x == y);
219173345a5Sjruoho 		ATF_CHECK(signbit(y) == 0);
220173345a5Sjruoho 	}
221e4094036Sjruoho }
222e4094036Sjruoho 
223e4094036Sjruoho /*
224e4094036Sjruoho  * scalbnf(3)
225e4094036Sjruoho  */
22685d85a18Smartin ATF_TC(scalbnf_val);
ATF_TC_HEAD(scalbnf_val,tc)22785d85a18Smartin ATF_TC_HEAD(scalbnf_val, tc)
22885d85a18Smartin {
22985d85a18Smartin 	atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values");
23085d85a18Smartin }
23185d85a18Smartin 
ATF_TC_BODY(scalbnf_val,tc)23285d85a18Smartin ATF_TC_BODY(scalbnf_val, tc)
23385d85a18Smartin {
23485d85a18Smartin 	const struct testcase *tests = test_vals;
23585d85a18Smartin 	const size_t tcnt = __arraycount(test_vals);
23685d85a18Smartin 	size_t i;
23785d85a18Smartin 	double rv;
23885d85a18Smartin 
23985d85a18Smartin 	for (i = 0; i < tcnt; i++) {
24056556fc2Sagc 		errno = 0;
24185d85a18Smartin 		rv = scalbnf(tests[i].inval, tests[i].exp);
24285d85a18Smartin 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
24385d85a18Smartin 		    "test %zu: errno %d instead of %d", i, errno,
24485d85a18Smartin 		    tests[i].error);
245a8a8e5f5Sriastradh 		/* scalbn is always exact except for underflow or overflow.  */
246a8a8e5f5Sriastradh 		ATF_CHECK_MSG(rv == (float)tests[i].result,
247a8a8e5f5Sriastradh 		    "test %zu: return value %.8g instead of %.8g"
248a8a8e5f5Sriastradh 		    " (error %.8g)",
249a8a8e5f5Sriastradh 		    i, rv, tests[i].result,
250a8a8e5f5Sriastradh 		    fabsf((tests[i].result - rv)/tests[i].result));
25185d85a18Smartin 	}
25285d85a18Smartin }
25385d85a18Smartin 
254e4094036Sjruoho ATF_TC(scalbnf_nan);
ATF_TC_HEAD(scalbnf_nan,tc)255e4094036Sjruoho ATF_TC_HEAD(scalbnf_nan, tc)
256e4094036Sjruoho {
25795a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
258e4094036Sjruoho }
259e4094036Sjruoho 
ATF_TC_BODY(scalbnf_nan,tc)260e4094036Sjruoho ATF_TC_BODY(scalbnf_nan, tc)
261e4094036Sjruoho {
262e4094036Sjruoho 	const float x = 0.0L / 0.0L;
263e4094036Sjruoho 	float y;
264e4094036Sjruoho 	size_t i;
265e4094036Sjruoho 
266173345a5Sjruoho 	ATF_REQUIRE(isnan(x) != 0);
267173345a5Sjruoho 
268e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
269e4094036Sjruoho 		y = scalbnf(x, exps[i]);
270e4094036Sjruoho 		ATF_CHECK(isnan(y) != 0);
271e4094036Sjruoho 	}
272e4094036Sjruoho }
273e4094036Sjruoho 
274e4094036Sjruoho ATF_TC(scalbnf_inf_neg);
ATF_TC_HEAD(scalbnf_inf_neg,tc)275e4094036Sjruoho ATF_TC_HEAD(scalbnf_inf_neg, tc)
276e4094036Sjruoho {
27795a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
278e4094036Sjruoho }
279e4094036Sjruoho 
ATF_TC_BODY(scalbnf_inf_neg,tc)280e4094036Sjruoho ATF_TC_BODY(scalbnf_inf_neg, tc)
281e4094036Sjruoho {
282e4094036Sjruoho 	const float x = -1.0L / 0.0L;
283e4094036Sjruoho 	size_t i;
284e4094036Sjruoho 
285e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
286e4094036Sjruoho 		ATF_CHECK(scalbnf(x, exps[i]) == x);
287e4094036Sjruoho }
288e4094036Sjruoho 
289e4094036Sjruoho ATF_TC(scalbnf_inf_pos);
ATF_TC_HEAD(scalbnf_inf_pos,tc)290e4094036Sjruoho ATF_TC_HEAD(scalbnf_inf_pos, tc)
291e4094036Sjruoho {
29295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
293e4094036Sjruoho }
294e4094036Sjruoho 
ATF_TC_BODY(scalbnf_inf_pos,tc)295e4094036Sjruoho ATF_TC_BODY(scalbnf_inf_pos, tc)
296e4094036Sjruoho {
297e4094036Sjruoho 	const float x = 1.0L / 0.0L;
298e4094036Sjruoho 	size_t i;
299e4094036Sjruoho 
300e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
301e4094036Sjruoho 		ATF_CHECK(scalbnf(x, exps[i]) == x);
302e4094036Sjruoho }
303e4094036Sjruoho 
30495a05df2Sjruoho ATF_TC(scalbnf_ldexpf);
ATF_TC_HEAD(scalbnf_ldexpf,tc)30595a05df2Sjruoho ATF_TC_HEAD(scalbnf_ldexpf, tc)
3068fa0fcafSjruoho {
30795a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
3088fa0fcafSjruoho }
3098fa0fcafSjruoho 
ATF_TC_BODY(scalbnf_ldexpf,tc)31095a05df2Sjruoho ATF_TC_BODY(scalbnf_ldexpf, tc)
3118fa0fcafSjruoho {
3128fa0fcafSjruoho #if FLT_RADIX == 2
3138fa0fcafSjruoho 	const float x = 2.91288191221812821;
3148fa0fcafSjruoho 	float y;
3158fa0fcafSjruoho 	size_t i;
3168fa0fcafSjruoho 
3178fa0fcafSjruoho 	for (i = 0; i < __arraycount(exps); i++) {
3188fa0fcafSjruoho 		y = scalbnf(x, exps[i]);
31985d85a18Smartin 		ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
32085d85a18Smartin 		    "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
32185d85a18Smartin 		    i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
3228fa0fcafSjruoho 	}
3238fa0fcafSjruoho #endif
3248fa0fcafSjruoho }
3258fa0fcafSjruoho 
326e4094036Sjruoho ATF_TC(scalbnf_zero_neg);
ATF_TC_HEAD(scalbnf_zero_neg,tc)327e4094036Sjruoho ATF_TC_HEAD(scalbnf_zero_neg, tc)
328e4094036Sjruoho {
32995a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
330e4094036Sjruoho }
331e4094036Sjruoho 
ATF_TC_BODY(scalbnf_zero_neg,tc)332e4094036Sjruoho ATF_TC_BODY(scalbnf_zero_neg, tc)
333e4094036Sjruoho {
334e4094036Sjruoho 	const float x = -0.0L;
335173345a5Sjruoho 	float y;
336e4094036Sjruoho 	size_t i;
337e4094036Sjruoho 
338173345a5Sjruoho 	ATF_REQUIRE(signbit(x) != 0);
339173345a5Sjruoho 
340173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
341173345a5Sjruoho 		y = scalbnf(x, exps[i]);
342173345a5Sjruoho 		ATF_CHECK(x == y);
343173345a5Sjruoho 		ATF_CHECK(signbit(y) != 0);
344173345a5Sjruoho 	}
345e4094036Sjruoho }
346e4094036Sjruoho 
347e4094036Sjruoho ATF_TC(scalbnf_zero_pos);
ATF_TC_HEAD(scalbnf_zero_pos,tc)348e4094036Sjruoho ATF_TC_HEAD(scalbnf_zero_pos, tc)
349e4094036Sjruoho {
35095a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
351e4094036Sjruoho }
352e4094036Sjruoho 
ATF_TC_BODY(scalbnf_zero_pos,tc)353e4094036Sjruoho ATF_TC_BODY(scalbnf_zero_pos, tc)
354e4094036Sjruoho {
355e4094036Sjruoho 	const float x = 0.0L;
356173345a5Sjruoho 	float y;
357e4094036Sjruoho 	size_t i;
358e4094036Sjruoho 
359173345a5Sjruoho 	ATF_REQUIRE(signbit(x) == 0);
360173345a5Sjruoho 
361173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
362173345a5Sjruoho 		y = scalbnf(x, exps[i]);
363173345a5Sjruoho 		ATF_CHECK(x == y);
364173345a5Sjruoho 		ATF_CHECK(signbit(y) == 0);
365173345a5Sjruoho 	}
366e4094036Sjruoho }
367e4094036Sjruoho 
368e4094036Sjruoho /*
369e4094036Sjruoho  * scalbnl(3)
370e4094036Sjruoho  */
37185d85a18Smartin ATF_TC(scalbnl_val);
ATF_TC_HEAD(scalbnl_val,tc)37285d85a18Smartin ATF_TC_HEAD(scalbnl_val, tc)
37385d85a18Smartin {
37485d85a18Smartin 	atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
37585d85a18Smartin }
37685d85a18Smartin 
ATF_TC_BODY(scalbnl_val,tc)37785d85a18Smartin ATF_TC_BODY(scalbnl_val, tc)
37885d85a18Smartin {
37985d85a18Smartin 	const struct testcase *tests = test_vals;
38085d85a18Smartin 	const size_t tcnt = __arraycount(test_vals);
38185d85a18Smartin 	size_t i;
38285d85a18Smartin 	long double rv;
38385d85a18Smartin 
38485d85a18Smartin 	for (i = 0; i < tcnt; i++) {
385a5445b4eSagc 		errno = 0;
38685d85a18Smartin 		rv = scalbnl(tests[i].inval, tests[i].exp);
38785d85a18Smartin 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
38885d85a18Smartin 		    "test %zu: errno %d instead of %d", i, errno,
38985d85a18Smartin 		    tests[i].error);
390a8a8e5f5Sriastradh 		/* scalbn is always exact except for underflow or overflow.  */
391a8a8e5f5Sriastradh 		ATF_CHECK_MSG(rv == (long double)tests[i].result,
392a8a8e5f5Sriastradh 		    "test %zu: return value %.35Lg instead of %.35Lg"
393a8a8e5f5Sriastradh 		    " (error %.35Lg)",
394a8a8e5f5Sriastradh 		    i, rv, (long double)tests[i].result,
395a8a8e5f5Sriastradh 		    fabsl(((long double)tests[i].result - rv)/tests[i].result));
39685d85a18Smartin 	}
39785d85a18Smartin }
39885d85a18Smartin 
399e4094036Sjruoho ATF_TC(scalbnl_nan);
ATF_TC_HEAD(scalbnl_nan,tc)400e4094036Sjruoho ATF_TC_HEAD(scalbnl_nan, tc)
401e4094036Sjruoho {
40295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
403e4094036Sjruoho }
404e4094036Sjruoho 
ATF_TC_BODY(scalbnl_nan,tc)405e4094036Sjruoho ATF_TC_BODY(scalbnl_nan, tc)
406e4094036Sjruoho {
407e4094036Sjruoho 	const long double x = 0.0L / 0.0L;
408e4094036Sjruoho 	long double y;
409e4094036Sjruoho 	size_t i;
410e4094036Sjruoho 
411*6442493fSriastradh 	ATF_CHECK_MSG(isnan(x), "x=%La", x);
412173345a5Sjruoho 
413e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
414e4094036Sjruoho 		y = scalbnl(x, exps[i]);
415*6442493fSriastradh 		ATF_CHECK_MSG(isnan(y), "y=%La", y);
416e4094036Sjruoho 	}
417e4094036Sjruoho }
418e4094036Sjruoho 
419e4094036Sjruoho ATF_TC(scalbnl_inf_neg);
ATF_TC_HEAD(scalbnl_inf_neg,tc)420e4094036Sjruoho ATF_TC_HEAD(scalbnl_inf_neg, tc)
421e4094036Sjruoho {
42295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
423e4094036Sjruoho }
424e4094036Sjruoho 
ATF_TC_BODY(scalbnl_inf_neg,tc)425e4094036Sjruoho ATF_TC_BODY(scalbnl_inf_neg, tc)
426e4094036Sjruoho {
427e4094036Sjruoho 	const long double x = -1.0L / 0.0L;
428e4094036Sjruoho 	size_t i;
429e4094036Sjruoho 
430e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
431e4094036Sjruoho 		ATF_CHECK(scalbnl(x, exps[i]) == x);
432e4094036Sjruoho }
433e4094036Sjruoho 
434e4094036Sjruoho ATF_TC(scalbnl_inf_pos);
ATF_TC_HEAD(scalbnl_inf_pos,tc)435e4094036Sjruoho ATF_TC_HEAD(scalbnl_inf_pos, tc)
436e4094036Sjruoho {
43795a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
438e4094036Sjruoho }
439e4094036Sjruoho 
ATF_TC_BODY(scalbnl_inf_pos,tc)440e4094036Sjruoho ATF_TC_BODY(scalbnl_inf_pos, tc)
441e4094036Sjruoho {
442e4094036Sjruoho 	const long double x = 1.0L / 0.0L;
443e4094036Sjruoho 	size_t i;
444e4094036Sjruoho 
445e4094036Sjruoho 	for (i = 0; i < __arraycount(exps); i++)
446e4094036Sjruoho 		ATF_CHECK(scalbnl(x, exps[i]) == x);
447e4094036Sjruoho }
448e4094036Sjruoho 
449e4094036Sjruoho ATF_TC(scalbnl_zero_neg);
ATF_TC_HEAD(scalbnl_zero_neg,tc)450e4094036Sjruoho ATF_TC_HEAD(scalbnl_zero_neg, tc)
451e4094036Sjruoho {
45295a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
453e4094036Sjruoho }
454e4094036Sjruoho 
ATF_TC_BODY(scalbnl_zero_neg,tc)455e4094036Sjruoho ATF_TC_BODY(scalbnl_zero_neg, tc)
456e4094036Sjruoho {
457e4094036Sjruoho 	const long double x = -0.0L;
458173345a5Sjruoho 	long double y;
459e4094036Sjruoho 	size_t i;
460e4094036Sjruoho 
461173345a5Sjruoho 	ATF_REQUIRE(signbit(x) != 0);
462173345a5Sjruoho 
463173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
464173345a5Sjruoho 		y = scalbnl(x, exps[i]);
465173345a5Sjruoho 		ATF_CHECK(x == y);
466173345a5Sjruoho 		ATF_CHECK(signbit(y) != 0);
467173345a5Sjruoho 	}
468e4094036Sjruoho }
469e4094036Sjruoho 
470e4094036Sjruoho ATF_TC(scalbnl_zero_pos);
ATF_TC_HEAD(scalbnl_zero_pos,tc)471e4094036Sjruoho ATF_TC_HEAD(scalbnl_zero_pos, tc)
472e4094036Sjruoho {
47395a05df2Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
474e4094036Sjruoho }
475e4094036Sjruoho 
ATF_TC_BODY(scalbnl_zero_pos,tc)476e4094036Sjruoho ATF_TC_BODY(scalbnl_zero_pos, tc)
477e4094036Sjruoho {
478e4094036Sjruoho 	const long double x = 0.0L;
479173345a5Sjruoho 	long double y;
480e4094036Sjruoho 	size_t i;
481e4094036Sjruoho 
482173345a5Sjruoho 	ATF_REQUIRE(signbit(x) == 0);
483173345a5Sjruoho 
484173345a5Sjruoho 	for (i = 0; i < __arraycount(exps); i++) {
485173345a5Sjruoho 		y = scalbnl(x, exps[i]);
486173345a5Sjruoho 		ATF_CHECK(x == y);
487173345a5Sjruoho 		ATF_CHECK(signbit(y) == 0);
488173345a5Sjruoho 	}
489e4094036Sjruoho }
490e4094036Sjruoho 
ATF_TP_ADD_TCS(tp)491e4094036Sjruoho ATF_TP_ADD_TCS(tp)
492e4094036Sjruoho {
493e4094036Sjruoho 
49485d85a18Smartin 	ATF_TP_ADD_TC(tp, scalbn_val);
495e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbn_nan);
496e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbn_inf_neg);
497e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbn_inf_pos);
4988fa0fcafSjruoho 	ATF_TP_ADD_TC(tp, scalbn_ldexp);
499e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbn_zero_neg);
500e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbn_zero_pos);
501e4094036Sjruoho 
50285d85a18Smartin 	ATF_TP_ADD_TC(tp, scalbnf_val);
503e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_nan);
504e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
505e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
50695a05df2Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
507e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
508e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
509e4094036Sjruoho 
51085d85a18Smartin 	ATF_TP_ADD_TC(tp, scalbnl_val);
511e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnl_nan);
512e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
513e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
5148fa0fcafSjruoho /*	ATF_TP_ADD_TC(tp, scalbnl_ldexp);	*/
515e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
516e4094036Sjruoho 	ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
517e4094036Sjruoho 
518e4094036Sjruoho 	return atf_no_error();
519e4094036Sjruoho }
520