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++) {
8479097302SEnji Cooper #ifdef __FreeBSD__
8579097302SEnji Cooper 		errno = 0;
8679097302SEnji 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++) {
2288fe9679fSEnji Cooper #ifdef __FreeBSD__
2298fe9679fSEnji Cooper 		errno = 0;
2308fe9679fSEnji Cooper #endif
23157718be8SEnji Cooper 		rv = scalbnf(tests[i].inval, tests[i].exp);
23257718be8SEnji Cooper 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
23357718be8SEnji Cooper 		    "test %zu: errno %d instead of %d", i, errno,
23457718be8SEnji Cooper 		    tests[i].error);
23557718be8SEnji Cooper 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON,
23657718be8SEnji Cooper 		    "test %zu: return value %g instead of %g (difference %g)",
23757718be8SEnji Cooper 		    i, rv, tests[i].result, tests[i].result-rv);
23857718be8SEnji Cooper 	}
23957718be8SEnji Cooper }
24057718be8SEnji Cooper 
24157718be8SEnji Cooper ATF_TC(scalbnf_nan);
24257718be8SEnji Cooper ATF_TC_HEAD(scalbnf_nan, tc)
24357718be8SEnji Cooper {
24457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
24557718be8SEnji Cooper }
24657718be8SEnji Cooper 
24757718be8SEnji Cooper ATF_TC_BODY(scalbnf_nan, tc)
24857718be8SEnji Cooper {
24957718be8SEnji Cooper 	const float x = 0.0L / 0.0L;
25057718be8SEnji Cooper 	float y;
25157718be8SEnji Cooper 	size_t i;
25257718be8SEnji Cooper 
25357718be8SEnji Cooper 	ATF_REQUIRE(isnan(x) != 0);
25457718be8SEnji Cooper 
25557718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
25657718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
25757718be8SEnji Cooper 		ATF_CHECK(isnan(y) != 0);
25857718be8SEnji Cooper 	}
25957718be8SEnji Cooper }
26057718be8SEnji Cooper 
26157718be8SEnji Cooper ATF_TC(scalbnf_inf_neg);
26257718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_neg, tc)
26357718be8SEnji Cooper {
26457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
26557718be8SEnji Cooper }
26657718be8SEnji Cooper 
26757718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_neg, tc)
26857718be8SEnji Cooper {
26957718be8SEnji Cooper 	const float x = -1.0L / 0.0L;
27057718be8SEnji Cooper 	size_t i;
27157718be8SEnji Cooper 
27257718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
27357718be8SEnji Cooper 		ATF_CHECK(scalbnf(x, exps[i]) == x);
27457718be8SEnji Cooper }
27557718be8SEnji Cooper 
27657718be8SEnji Cooper ATF_TC(scalbnf_inf_pos);
27757718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_pos, tc)
27857718be8SEnji Cooper {
27957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
28057718be8SEnji Cooper }
28157718be8SEnji Cooper 
28257718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_pos, tc)
28357718be8SEnji Cooper {
28457718be8SEnji Cooper 	const float x = 1.0L / 0.0L;
28557718be8SEnji Cooper 	size_t i;
28657718be8SEnji Cooper 
28757718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
28857718be8SEnji Cooper 		ATF_CHECK(scalbnf(x, exps[i]) == x);
28957718be8SEnji Cooper }
29057718be8SEnji Cooper 
29157718be8SEnji Cooper ATF_TC(scalbnf_ldexpf);
29257718be8SEnji Cooper ATF_TC_HEAD(scalbnf_ldexpf, tc)
29357718be8SEnji Cooper {
29457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
29557718be8SEnji Cooper }
29657718be8SEnji Cooper 
29757718be8SEnji Cooper ATF_TC_BODY(scalbnf_ldexpf, tc)
29857718be8SEnji Cooper {
29957718be8SEnji Cooper #if FLT_RADIX == 2
30057718be8SEnji Cooper 	const float x = 2.91288191221812821;
30157718be8SEnji Cooper 	float y;
30257718be8SEnji Cooper 	size_t i;
30357718be8SEnji Cooper 
30457718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
30557718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
30657718be8SEnji Cooper 		ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
30757718be8SEnji Cooper 		    "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
30857718be8SEnji Cooper 		    i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
30957718be8SEnji Cooper 	}
31057718be8SEnji Cooper #endif
31157718be8SEnji Cooper }
31257718be8SEnji Cooper 
31357718be8SEnji Cooper ATF_TC(scalbnf_zero_neg);
31457718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_neg, tc)
31557718be8SEnji Cooper {
31657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
31757718be8SEnji Cooper }
31857718be8SEnji Cooper 
31957718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_neg, tc)
32057718be8SEnji Cooper {
32157718be8SEnji Cooper 	const float x = -0.0L;
32257718be8SEnji Cooper 	float y;
32357718be8SEnji Cooper 	size_t i;
32457718be8SEnji Cooper 
32557718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) != 0);
32657718be8SEnji Cooper 
32757718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
32857718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
32957718be8SEnji Cooper 		ATF_CHECK(x == y);
33057718be8SEnji Cooper 		ATF_CHECK(signbit(y) != 0);
33157718be8SEnji Cooper 	}
33257718be8SEnji Cooper }
33357718be8SEnji Cooper 
33457718be8SEnji Cooper ATF_TC(scalbnf_zero_pos);
33557718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_pos, tc)
33657718be8SEnji Cooper {
33757718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
33857718be8SEnji Cooper }
33957718be8SEnji Cooper 
34057718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_pos, tc)
34157718be8SEnji Cooper {
34257718be8SEnji Cooper 	const float x = 0.0L;
34357718be8SEnji Cooper 	float y;
34457718be8SEnji Cooper 	size_t i;
34557718be8SEnji Cooper 
34657718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) == 0);
34757718be8SEnji Cooper 
34857718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
34957718be8SEnji Cooper 		y = scalbnf(x, exps[i]);
35057718be8SEnji Cooper 		ATF_CHECK(x == y);
35157718be8SEnji Cooper 		ATF_CHECK(signbit(y) == 0);
35257718be8SEnji Cooper 	}
35357718be8SEnji Cooper }
35457718be8SEnji Cooper 
35557718be8SEnji Cooper /*
35657718be8SEnji Cooper  * scalbnl(3)
35757718be8SEnji Cooper  */
35857718be8SEnji Cooper ATF_TC(scalbnl_val);
35957718be8SEnji Cooper ATF_TC_HEAD(scalbnl_val, tc)
36057718be8SEnji Cooper {
36157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
36257718be8SEnji Cooper }
36357718be8SEnji Cooper 
36457718be8SEnji Cooper ATF_TC_BODY(scalbnl_val, tc)
36557718be8SEnji Cooper {
36657718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
36757718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
36857718be8SEnji Cooper #else
36957718be8SEnji Cooper 	const struct testcase *tests = test_vals;
37057718be8SEnji Cooper 	const size_t tcnt = __arraycount(test_vals);
37157718be8SEnji Cooper 	size_t i;
37257718be8SEnji Cooper 	long double rv;
37357718be8SEnji Cooper 
37457718be8SEnji Cooper 	for (i = 0; i < tcnt; i++) {
3758fe9679fSEnji Cooper #ifdef __FreeBSD__
3768fe9679fSEnji Cooper 		errno = 0;
3778fe9679fSEnji Cooper #endif
37857718be8SEnji Cooper 		rv = scalbnl(tests[i].inval, tests[i].exp);
37957718be8SEnji Cooper 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
38057718be8SEnji Cooper 		    "test %zu: errno %d instead of %d", i, errno,
38157718be8SEnji Cooper 		    tests[i].error);
38257718be8SEnji Cooper 		ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON,
38357718be8SEnji Cooper 		    "test %zu: return value %Lg instead of %Lg (difference %Lg)",
38457718be8SEnji Cooper 		    i, rv, (long double)tests[i].result, (long double)tests[i].result-rv);
38557718be8SEnji Cooper 	}
38657718be8SEnji Cooper #endif
38757718be8SEnji Cooper }
38857718be8SEnji Cooper 
38957718be8SEnji Cooper ATF_TC(scalbnl_nan);
39057718be8SEnji Cooper ATF_TC_HEAD(scalbnl_nan, tc)
39157718be8SEnji Cooper {
39257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
39357718be8SEnji Cooper }
39457718be8SEnji Cooper 
39557718be8SEnji Cooper ATF_TC_BODY(scalbnl_nan, tc)
39657718be8SEnji Cooper {
39757718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
39857718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
39957718be8SEnji Cooper #else
40057718be8SEnji Cooper 	const long double x = 0.0L / 0.0L;
40157718be8SEnji Cooper 	long double y;
40257718be8SEnji Cooper 	size_t i;
40357718be8SEnji Cooper 
40457718be8SEnji Cooper 	if (isnan(x) == 0) {
40557718be8SEnji Cooper 		atf_tc_expect_fail("PR lib/45362");
40657718be8SEnji Cooper 		atf_tc_fail("(0.0L / 0.0L) != NaN");
40757718be8SEnji Cooper 	}
40857718be8SEnji Cooper 
40957718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
41057718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
41157718be8SEnji Cooper 		ATF_CHECK(isnan(y) != 0);
41257718be8SEnji Cooper 	}
41357718be8SEnji Cooper #endif
41457718be8SEnji Cooper }
41557718be8SEnji Cooper 
41657718be8SEnji Cooper ATF_TC(scalbnl_inf_neg);
41757718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_neg, tc)
41857718be8SEnji Cooper {
41957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
42057718be8SEnji Cooper }
42157718be8SEnji Cooper 
42257718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_neg, tc)
42357718be8SEnji Cooper {
42457718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
42557718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
42657718be8SEnji Cooper #else
42757718be8SEnji Cooper 	const long double x = -1.0L / 0.0L;
42857718be8SEnji Cooper 	size_t i;
42957718be8SEnji Cooper 
43057718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
43157718be8SEnji Cooper 		ATF_CHECK(scalbnl(x, exps[i]) == x);
43257718be8SEnji Cooper #endif
43357718be8SEnji Cooper }
43457718be8SEnji Cooper 
43557718be8SEnji Cooper ATF_TC(scalbnl_inf_pos);
43657718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_pos, tc)
43757718be8SEnji Cooper {
43857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
43957718be8SEnji Cooper }
44057718be8SEnji Cooper 
44157718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_pos, tc)
44257718be8SEnji Cooper {
44357718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
44457718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
44557718be8SEnji Cooper #else
44657718be8SEnji Cooper 	const long double x = 1.0L / 0.0L;
44757718be8SEnji Cooper 	size_t i;
44857718be8SEnji Cooper 
44957718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++)
45057718be8SEnji Cooper 		ATF_CHECK(scalbnl(x, exps[i]) == x);
45157718be8SEnji Cooper #endif
45257718be8SEnji Cooper }
45357718be8SEnji Cooper 
45457718be8SEnji Cooper ATF_TC(scalbnl_zero_neg);
45557718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_neg, tc)
45657718be8SEnji Cooper {
45757718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
45857718be8SEnji Cooper }
45957718be8SEnji Cooper 
46057718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_neg, tc)
46157718be8SEnji Cooper {
46257718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
46357718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
46457718be8SEnji Cooper #else
46557718be8SEnji Cooper 	const long double x = -0.0L;
46657718be8SEnji Cooper 	long double y;
46757718be8SEnji Cooper 	size_t i;
46857718be8SEnji Cooper 
46957718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) != 0);
47057718be8SEnji Cooper 
47157718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
47257718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
47357718be8SEnji Cooper 		ATF_CHECK(x == y);
47457718be8SEnji Cooper 		ATF_CHECK(signbit(y) != 0);
47557718be8SEnji Cooper 	}
47657718be8SEnji Cooper #endif
47757718be8SEnji Cooper }
47857718be8SEnji Cooper 
47957718be8SEnji Cooper ATF_TC(scalbnl_zero_pos);
48057718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_pos, tc)
48157718be8SEnji Cooper {
48257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
48357718be8SEnji Cooper }
48457718be8SEnji Cooper 
48557718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_pos, tc)
48657718be8SEnji Cooper {
48757718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
48857718be8SEnji Cooper 	atf_tc_skip("Requires long double support");
48957718be8SEnji Cooper #else
49057718be8SEnji Cooper 	const long double x = 0.0L;
49157718be8SEnji Cooper 	long double y;
49257718be8SEnji Cooper 	size_t i;
49357718be8SEnji Cooper 
49457718be8SEnji Cooper 	ATF_REQUIRE(signbit(x) == 0);
49557718be8SEnji Cooper 
49657718be8SEnji Cooper 	for (i = 0; i < __arraycount(exps); i++) {
49757718be8SEnji Cooper 		y = scalbnl(x, exps[i]);
49857718be8SEnji Cooper 		ATF_CHECK(x == y);
49957718be8SEnji Cooper 		ATF_CHECK(signbit(y) == 0);
50057718be8SEnji Cooper 	}
50157718be8SEnji Cooper #endif
50257718be8SEnji Cooper }
50357718be8SEnji Cooper 
50457718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
50557718be8SEnji Cooper {
50657718be8SEnji Cooper 
50757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_val);
50857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_nan);
50957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_inf_neg);
51057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_inf_pos);
51157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_ldexp);
51257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_zero_neg);
51357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbn_zero_pos);
51457718be8SEnji Cooper 
51557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_val);
51657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_nan);
51757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
51857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
51957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
52057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
52157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
52257718be8SEnji Cooper 
52357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_val);
52457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_nan);
52557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
52657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
52757718be8SEnji Cooper /*	ATF_TP_ADD_TC(tp, scalbnl_ldexp);	*/
52857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
52957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
53057718be8SEnji Cooper 
53157718be8SEnji Cooper 	return atf_no_error();
53257718be8SEnji Cooper }
533