xref: /freebsd-src/contrib/netbsd-tests/lib/libm/t_scalbn.c (revision 790973021f8ea886562dfa969204f7716c620cc1)
157718be8SEnji Cooper /* $NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2011 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper  * by Jukka Ruohonen.
957718be8SEnji Cooper  *
1057718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper  * are met:
1357718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper  *
1957718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper #include <sys/cdefs.h>
3257718be8SEnji Cooper __RCSID("$NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $");
3357718be8SEnji Cooper 
3457718be8SEnji Cooper #include <math.h>
3557718be8SEnji Cooper #include <limits.h>
3657718be8SEnji Cooper #include <float.h>
3757718be8SEnji Cooper #include <errno.h>
3857718be8SEnji Cooper 
3957718be8SEnji Cooper #include <atf-c.h>
4057718be8SEnji Cooper 
4157718be8SEnji Cooper static const int exps[] = { 0, 1, -1, 100, -100 };
4257718be8SEnji Cooper 
4357718be8SEnji Cooper /* tests here do not require specific precision, so we just use double */
4457718be8SEnji Cooper struct testcase {
4557718be8SEnji Cooper 	int exp;
4657718be8SEnji Cooper 	double inval;
4757718be8SEnji Cooper 	double result;
4857718be8SEnji Cooper 	int error;
4957718be8SEnji Cooper };
5057718be8SEnji Cooper struct testcase test_vals[] = {
5157718be8SEnji Cooper 	{ 0,		1.00085,	1.00085,	0 },
5257718be8SEnji Cooper 	{ 0,		0.99755,	0.99755,	0 },
5357718be8SEnji Cooper 	{ 0,		-1.00085,	-1.00085,	0 },
5457718be8SEnji Cooper 	{ 0,		-0.99755,	-0.99755,	0 },
5557718be8SEnji Cooper 	{ 1,		1.00085,	2.0* 1.00085,	0 },
5657718be8SEnji Cooper 	{ 1,		0.99755,	2.0* 0.99755,	0 },
5757718be8SEnji Cooper 	{ 1,		-1.00085,	2.0* -1.00085,	0 },
5857718be8SEnji Cooper 	{ 1,		-0.99755,	2.0* -0.99755,	0 },
5957718be8SEnji Cooper 
6057718be8SEnji Cooper 	/*
6157718be8SEnji Cooper 	 * We could add more corner test cases here, but we would have to
6257718be8SEnji Cooper 	 * add some ifdefs for the exact format and use a reliable
6357718be8SEnji Cooper 	 * generator program - bail for now and only do trivial stuff above.
6457718be8SEnji Cooper 	 */
6557718be8SEnji Cooper };
6657718be8SEnji Cooper 
6757718be8SEnji Cooper /*
6857718be8SEnji Cooper  * scalbn(3)
6957718be8SEnji Cooper  */
7057718be8SEnji Cooper ATF_TC(scalbn_val);
7157718be8SEnji Cooper ATF_TC_HEAD(scalbn_val, tc)
7257718be8SEnji Cooper {
7357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values");
7457718be8SEnji Cooper }
7557718be8SEnji Cooper 
7657718be8SEnji Cooper ATF_TC_BODY(scalbn_val, tc)
7757718be8SEnji Cooper {
7857718be8SEnji Cooper 	const struct testcase *tests = test_vals;
7957718be8SEnji Cooper 	const size_t tcnt = __arraycount(test_vals);
8057718be8SEnji Cooper 	size_t i;
8157718be8SEnji Cooper 	double rv;
8257718be8SEnji Cooper 
8357718be8SEnji Cooper 	for (i = 0; i < tcnt; i++) {
84*79097302SEnji Cooper #ifdef __FreeBSD__
85*79097302SEnji Cooper 		errno = 0;
86*79097302SEnji Cooper #endif
8757718be8SEnji Cooper 		rv = scalbn(tests[i].inval, tests[i].exp);
8857718be8SEnji Cooper 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
8957718be8SEnji Cooper 		    "test %zu: errno %d instead of %d", i, errno,
9057718be8SEnji Cooper 		    tests[i].error);
9157718be8SEnji Cooper 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON,
9257718be8SEnji Cooper 		    "test %zu: return value %g instead of %g (difference %g)",
9357718be8SEnji Cooper 		    i, rv, tests[i].result, tests[i].result-rv);
9457718be8SEnji Cooper 	}
9557718be8SEnji Cooper }
9657718be8SEnji Cooper 
9757718be8SEnji Cooper ATF_TC(scalbn_nan);
9857718be8SEnji Cooper ATF_TC_HEAD(scalbn_nan, tc)
9957718be8SEnji Cooper {
10057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN");
10157718be8SEnji Cooper }
10257718be8SEnji Cooper 
10357718be8SEnji Cooper ATF_TC_BODY(scalbn_nan, tc)
10457718be8SEnji Cooper {
10557718be8SEnji Cooper 	const double x = 0.0L / 0.0L;
10657718be8SEnji Cooper 	double y;
10757718be8SEnji Cooper 	size_t i;
10857718be8SEnji Cooper 
10957718be8SEnji Cooper 	ATF_REQUIRE(isnan(x) != 0);
11057718be8SEnji Cooper 
11157718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
11257718be8SEnji Cooper 		y = scalbn(x, exps[i]);
11357718be8SEnji Cooper 		ATF_CHECK(isnan(y) != 0);
11457718be8SEnji Cooper 	}
11557718be8SEnji Cooper }
11657718be8SEnji Cooper 
11757718be8SEnji Cooper ATF_TC(scalbn_inf_neg);
11857718be8SEnji Cooper ATF_TC_HEAD(scalbn_inf_neg, tc)
11957718be8SEnji Cooper {
12057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf");
12157718be8SEnji Cooper }
12257718be8SEnji Cooper 
12357718be8SEnji Cooper ATF_TC_BODY(scalbn_inf_neg, tc)
12457718be8SEnji Cooper {
12557718be8SEnji Cooper 	const double x = -1.0L / 0.0L;
12657718be8SEnji Cooper 	size_t i;
12757718be8SEnji Cooper 
12857718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
12957718be8SEnji Cooper 		ATF_CHECK(scalbn(x, exps[i]) == x);
13057718be8SEnji Cooper }
13157718be8SEnji Cooper 
13257718be8SEnji Cooper ATF_TC(scalbn_inf_pos);
13357718be8SEnji Cooper ATF_TC_HEAD(scalbn_inf_pos, tc)
13457718be8SEnji Cooper {
13557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf");
13657718be8SEnji Cooper }
13757718be8SEnji Cooper 
13857718be8SEnji Cooper ATF_TC_BODY(scalbn_inf_pos, tc)
13957718be8SEnji Cooper {
14057718be8SEnji Cooper 	const double x = 1.0L / 0.0L;
14157718be8SEnji Cooper 	size_t i;
14257718be8SEnji Cooper 
14357718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
14457718be8SEnji Cooper 		ATF_CHECK(scalbn(x, exps[i]) == x);
14557718be8SEnji Cooper }
14657718be8SEnji Cooper 
14757718be8SEnji Cooper ATF_TC(scalbn_ldexp);
14857718be8SEnji Cooper ATF_TC_HEAD(scalbn_ldexp, tc)
14957718be8SEnji Cooper {
15057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)");
15157718be8SEnji Cooper }
15257718be8SEnji Cooper 
15357718be8SEnji Cooper ATF_TC_BODY(scalbn_ldexp, tc)
15457718be8SEnji Cooper {
15557718be8SEnji Cooper #if FLT_RADIX == 2
15657718be8SEnji Cooper 	const double x = 2.91288191221812821;
15757718be8SEnji Cooper 	double y;
15857718be8SEnji Cooper 	size_t i;
15957718be8SEnji Cooper 
16057718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
16157718be8SEnji Cooper 		y = scalbn(x, exps[i]);
16257718be8SEnji Cooper 		ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, "
16357718be8SEnji Cooper 		    "y=%g, expected %g (diff: %g)", i, exps[i], y,
16457718be8SEnji Cooper 		    ldexp(x, exps[i]), y - ldexp(x, exps[i]));
16557718be8SEnji Cooper 	}
16657718be8SEnji Cooper #endif
16757718be8SEnji Cooper }
16857718be8SEnji Cooper 
16957718be8SEnji Cooper ATF_TC(scalbn_zero_neg);
17057718be8SEnji Cooper ATF_TC_HEAD(scalbn_zero_neg, tc)
17157718be8SEnji Cooper {
17257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0");
17357718be8SEnji Cooper }
17457718be8SEnji Cooper 
17557718be8SEnji Cooper ATF_TC_BODY(scalbn_zero_neg, tc)
17657718be8SEnji Cooper {
17757718be8SEnji Cooper 	const double x = -0.0L;
17857718be8SEnji Cooper 	double y;
17957718be8SEnji Cooper 	size_t i;
18057718be8SEnji Cooper 
18157718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) != 0);
18257718be8SEnji Cooper 
18357718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
18457718be8SEnji Cooper 		y = scalbn(x, exps[i]);
18557718be8SEnji Cooper 		ATF_CHECK(x == y);
18657718be8SEnji Cooper 		ATF_CHECK(signbit(y) != 0);
18757718be8SEnji Cooper 	}
18857718be8SEnji Cooper }
18957718be8SEnji Cooper 
19057718be8SEnji Cooper ATF_TC(scalbn_zero_pos);
19157718be8SEnji Cooper ATF_TC_HEAD(scalbn_zero_pos, tc)
19257718be8SEnji Cooper {
19357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0");
19457718be8SEnji Cooper }
19557718be8SEnji Cooper 
19657718be8SEnji Cooper ATF_TC_BODY(scalbn_zero_pos, tc)
19757718be8SEnji Cooper {
19857718be8SEnji Cooper 	const double x = 0.0L;
19957718be8SEnji Cooper 	double y;
20057718be8SEnji Cooper 	size_t i;
20157718be8SEnji Cooper 
20257718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) == 0);
20357718be8SEnji Cooper 
20457718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
20557718be8SEnji Cooper 		y = scalbn(x, exps[i]);
20657718be8SEnji Cooper 		ATF_CHECK(x == y);
20757718be8SEnji Cooper 		ATF_CHECK(signbit(y) == 0);
20857718be8SEnji Cooper 	}
20957718be8SEnji Cooper }
21057718be8SEnji Cooper 
21157718be8SEnji Cooper /*
21257718be8SEnji Cooper  * scalbnf(3)
21357718be8SEnji Cooper  */
21457718be8SEnji Cooper ATF_TC(scalbnf_val);
21557718be8SEnji Cooper ATF_TC_HEAD(scalbnf_val, tc)
21657718be8SEnji Cooper {
21757718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values");
21857718be8SEnji Cooper }
21957718be8SEnji Cooper 
22057718be8SEnji Cooper ATF_TC_BODY(scalbnf_val, tc)
22157718be8SEnji Cooper {
22257718be8SEnji Cooper 	const struct testcase *tests = test_vals;
22357718be8SEnji Cooper 	const size_t tcnt = __arraycount(test_vals);
22457718be8SEnji Cooper 	size_t i;
22557718be8SEnji Cooper 	double rv;
22657718be8SEnji Cooper 
22757718be8SEnji Cooper 	for (i = 0; i < tcnt; i++) {
22857718be8SEnji Cooper 		rv = scalbnf(tests[i].inval, tests[i].exp);
22957718be8SEnji Cooper 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
23057718be8SEnji Cooper 		    "test %zu: errno %d instead of %d", i, errno,
23157718be8SEnji Cooper 		    tests[i].error);
23257718be8SEnji Cooper 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON,
23357718be8SEnji Cooper 		    "test %zu: return value %g instead of %g (difference %g)",
23457718be8SEnji Cooper 		    i, rv, tests[i].result, tests[i].result-rv);
23557718be8SEnji Cooper 	}
23657718be8SEnji Cooper }
23757718be8SEnji Cooper 
23857718be8SEnji Cooper ATF_TC(scalbnf_nan);
23957718be8SEnji Cooper ATF_TC_HEAD(scalbnf_nan, tc)
24057718be8SEnji Cooper {
24157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
24257718be8SEnji Cooper }
24357718be8SEnji Cooper 
24457718be8SEnji Cooper ATF_TC_BODY(scalbnf_nan, tc)
24557718be8SEnji Cooper {
24657718be8SEnji Cooper 	const float x = 0.0L / 0.0L;
24757718be8SEnji Cooper 	float y;
24857718be8SEnji Cooper 	size_t i;
24957718be8SEnji Cooper 
25057718be8SEnji Cooper 	ATF_REQUIRE(isnan(x) != 0);
25157718be8SEnji Cooper 
25257718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
25357718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
25457718be8SEnji Cooper 		ATF_CHECK(isnan(y) != 0);
25557718be8SEnji Cooper 	}
25657718be8SEnji Cooper }
25757718be8SEnji Cooper 
25857718be8SEnji Cooper ATF_TC(scalbnf_inf_neg);
25957718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_neg, tc)
26057718be8SEnji Cooper {
26157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
26257718be8SEnji Cooper }
26357718be8SEnji Cooper 
26457718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_neg, tc)
26557718be8SEnji Cooper {
26657718be8SEnji Cooper 	const float x = -1.0L / 0.0L;
26757718be8SEnji Cooper 	size_t i;
26857718be8SEnji Cooper 
26957718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
27057718be8SEnji Cooper 		ATF_CHECK(scalbnf(x, exps[i]) == x);
27157718be8SEnji Cooper }
27257718be8SEnji Cooper 
27357718be8SEnji Cooper ATF_TC(scalbnf_inf_pos);
27457718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_pos, tc)
27557718be8SEnji Cooper {
27657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
27757718be8SEnji Cooper }
27857718be8SEnji Cooper 
27957718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_pos, tc)
28057718be8SEnji Cooper {
28157718be8SEnji Cooper 	const float x = 1.0L / 0.0L;
28257718be8SEnji Cooper 	size_t i;
28357718be8SEnji Cooper 
28457718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
28557718be8SEnji Cooper 		ATF_CHECK(scalbnf(x, exps[i]) == x);
28657718be8SEnji Cooper }
28757718be8SEnji Cooper 
28857718be8SEnji Cooper ATF_TC(scalbnf_ldexpf);
28957718be8SEnji Cooper ATF_TC_HEAD(scalbnf_ldexpf, tc)
29057718be8SEnji Cooper {
29157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
29257718be8SEnji Cooper }
29357718be8SEnji Cooper 
29457718be8SEnji Cooper ATF_TC_BODY(scalbnf_ldexpf, tc)
29557718be8SEnji Cooper {
29657718be8SEnji Cooper #if FLT_RADIX == 2
29757718be8SEnji Cooper 	const float x = 2.91288191221812821;
29857718be8SEnji Cooper 	float y;
29957718be8SEnji Cooper 	size_t i;
30057718be8SEnji Cooper 
30157718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
30257718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
30357718be8SEnji Cooper 		ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
30457718be8SEnji Cooper 		    "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
30557718be8SEnji Cooper 		    i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
30657718be8SEnji Cooper 	}
30757718be8SEnji Cooper #endif
30857718be8SEnji Cooper }
30957718be8SEnji Cooper 
31057718be8SEnji Cooper ATF_TC(scalbnf_zero_neg);
31157718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_neg, tc)
31257718be8SEnji Cooper {
31357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
31457718be8SEnji Cooper }
31557718be8SEnji Cooper 
31657718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_neg, tc)
31757718be8SEnji Cooper {
31857718be8SEnji Cooper 	const float x = -0.0L;
31957718be8SEnji Cooper 	float y;
32057718be8SEnji Cooper 	size_t i;
32157718be8SEnji Cooper 
32257718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) != 0);
32357718be8SEnji Cooper 
32457718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
32557718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
32657718be8SEnji Cooper 		ATF_CHECK(x == y);
32757718be8SEnji Cooper 		ATF_CHECK(signbit(y) != 0);
32857718be8SEnji Cooper 	}
32957718be8SEnji Cooper }
33057718be8SEnji Cooper 
33157718be8SEnji Cooper ATF_TC(scalbnf_zero_pos);
33257718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_pos, tc)
33357718be8SEnji Cooper {
33457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
33557718be8SEnji Cooper }
33657718be8SEnji Cooper 
33757718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_pos, tc)
33857718be8SEnji Cooper {
33957718be8SEnji Cooper 	const float x = 0.0L;
34057718be8SEnji Cooper 	float y;
34157718be8SEnji Cooper 	size_t i;
34257718be8SEnji Cooper 
34357718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) == 0);
34457718be8SEnji Cooper 
34557718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
34657718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
34757718be8SEnji Cooper 		ATF_CHECK(x == y);
34857718be8SEnji Cooper 		ATF_CHECK(signbit(y) == 0);
34957718be8SEnji Cooper 	}
35057718be8SEnji Cooper }
35157718be8SEnji Cooper 
35257718be8SEnji Cooper /*
35357718be8SEnji Cooper  * scalbnl(3)
35457718be8SEnji Cooper  */
35557718be8SEnji Cooper ATF_TC(scalbnl_val);
35657718be8SEnji Cooper ATF_TC_HEAD(scalbnl_val, tc)
35757718be8SEnji Cooper {
35857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
35957718be8SEnji Cooper }
36057718be8SEnji Cooper 
36157718be8SEnji Cooper ATF_TC_BODY(scalbnl_val, tc)
36257718be8SEnji Cooper {
36357718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
36457718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
36557718be8SEnji Cooper #else
36657718be8SEnji Cooper 	const struct testcase *tests = test_vals;
36757718be8SEnji Cooper 	const size_t tcnt = __arraycount(test_vals);
36857718be8SEnji Cooper 	size_t i;
36957718be8SEnji Cooper 	long double rv;
37057718be8SEnji Cooper 
37157718be8SEnji Cooper 	for (i = 0; i < tcnt; i++) {
37257718be8SEnji Cooper 		rv = scalbnl(tests[i].inval, tests[i].exp);
37357718be8SEnji Cooper 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
37457718be8SEnji Cooper 		    "test %zu: errno %d instead of %d", i, errno,
37557718be8SEnji Cooper 		    tests[i].error);
37657718be8SEnji Cooper 		ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON,
37757718be8SEnji Cooper 		    "test %zu: return value %Lg instead of %Lg (difference %Lg)",
37857718be8SEnji Cooper 		    i, rv, (long double)tests[i].result, (long double)tests[i].result-rv);
37957718be8SEnji Cooper 	}
38057718be8SEnji Cooper #endif
38157718be8SEnji Cooper }
38257718be8SEnji Cooper 
38357718be8SEnji Cooper ATF_TC(scalbnl_nan);
38457718be8SEnji Cooper ATF_TC_HEAD(scalbnl_nan, tc)
38557718be8SEnji Cooper {
38657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
38757718be8SEnji Cooper }
38857718be8SEnji Cooper 
38957718be8SEnji Cooper ATF_TC_BODY(scalbnl_nan, tc)
39057718be8SEnji Cooper {
39157718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
39257718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
39357718be8SEnji Cooper #else
39457718be8SEnji Cooper 	const long double x = 0.0L / 0.0L;
39557718be8SEnji Cooper 	long double y;
39657718be8SEnji Cooper 	size_t i;
39757718be8SEnji Cooper 
39857718be8SEnji Cooper 	if (isnan(x) == 0) {
39957718be8SEnji Cooper 		atf_tc_expect_fail("PR lib/45362");
40057718be8SEnji Cooper 		atf_tc_fail("(0.0L / 0.0L) != NaN");
40157718be8SEnji Cooper 	}
40257718be8SEnji Cooper 
40357718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
40457718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
40557718be8SEnji Cooper 		ATF_CHECK(isnan(y) != 0);
40657718be8SEnji Cooper 	}
40757718be8SEnji Cooper #endif
40857718be8SEnji Cooper }
40957718be8SEnji Cooper 
41057718be8SEnji Cooper ATF_TC(scalbnl_inf_neg);
41157718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_neg, tc)
41257718be8SEnji Cooper {
41357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
41457718be8SEnji Cooper }
41557718be8SEnji Cooper 
41657718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_neg, tc)
41757718be8SEnji Cooper {
41857718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
41957718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
42057718be8SEnji Cooper #else
42157718be8SEnji Cooper 	const long double x = -1.0L / 0.0L;
42257718be8SEnji Cooper 	size_t i;
42357718be8SEnji Cooper 
42457718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
42557718be8SEnji Cooper 		ATF_CHECK(scalbnl(x, exps[i]) == x);
42657718be8SEnji Cooper #endif
42757718be8SEnji Cooper }
42857718be8SEnji Cooper 
42957718be8SEnji Cooper ATF_TC(scalbnl_inf_pos);
43057718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_pos, tc)
43157718be8SEnji Cooper {
43257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
43357718be8SEnji Cooper }
43457718be8SEnji Cooper 
43557718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_pos, tc)
43657718be8SEnji Cooper {
43757718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
43857718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
43957718be8SEnji Cooper #else
44057718be8SEnji Cooper 	const long double x = 1.0L / 0.0L;
44157718be8SEnji Cooper 	size_t i;
44257718be8SEnji Cooper 
44357718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
44457718be8SEnji Cooper 		ATF_CHECK(scalbnl(x, exps[i]) == x);
44557718be8SEnji Cooper #endif
44657718be8SEnji Cooper }
44757718be8SEnji Cooper 
44857718be8SEnji Cooper ATF_TC(scalbnl_zero_neg);
44957718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_neg, tc)
45057718be8SEnji Cooper {
45157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
45257718be8SEnji Cooper }
45357718be8SEnji Cooper 
45457718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_neg, tc)
45557718be8SEnji Cooper {
45657718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
45757718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
45857718be8SEnji Cooper #else
45957718be8SEnji Cooper 	const long double x = -0.0L;
46057718be8SEnji Cooper 	long double y;
46157718be8SEnji Cooper 	size_t i;
46257718be8SEnji Cooper 
46357718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) != 0);
46457718be8SEnji Cooper 
46557718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
46657718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
46757718be8SEnji Cooper 		ATF_CHECK(x == y);
46857718be8SEnji Cooper 		ATF_CHECK(signbit(y) != 0);
46957718be8SEnji Cooper 	}
47057718be8SEnji Cooper #endif
47157718be8SEnji Cooper }
47257718be8SEnji Cooper 
47357718be8SEnji Cooper ATF_TC(scalbnl_zero_pos);
47457718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_pos, tc)
47557718be8SEnji Cooper {
47657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
47757718be8SEnji Cooper }
47857718be8SEnji Cooper 
47957718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_pos, tc)
48057718be8SEnji Cooper {
48157718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
48257718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
48357718be8SEnji Cooper #else
48457718be8SEnji Cooper 	const long double x = 0.0L;
48557718be8SEnji Cooper 	long double y;
48657718be8SEnji Cooper 	size_t i;
48757718be8SEnji Cooper 
48857718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) == 0);
48957718be8SEnji Cooper 
49057718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
49157718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
49257718be8SEnji Cooper 		ATF_CHECK(x == y);
49357718be8SEnji Cooper 		ATF_CHECK(signbit(y) == 0);
49457718be8SEnji Cooper 	}
49557718be8SEnji Cooper #endif
49657718be8SEnji Cooper }
49757718be8SEnji Cooper 
49857718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
49957718be8SEnji Cooper {
50057718be8SEnji Cooper 
50157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_val);
50257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_nan);
50357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_inf_neg);
50457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_inf_pos);
50557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_ldexp);
50657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_zero_neg);
50757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_zero_pos);
50857718be8SEnji Cooper 
50957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_val);
51057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_nan);
51157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
51257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
51357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
51457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
51557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
51657718be8SEnji Cooper 
51757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_val);
51857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_nan);
51957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
52057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
52157718be8SEnji Cooper /*	ATF_TP_ADD_TC(tp, scalbnl_ldexp);	*/
52257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
52357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
52457718be8SEnji Cooper 
52557718be8SEnji Cooper 	return atf_no_error();
52657718be8SEnji Cooper }
527