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