xref: /minix3/tests/lib/libm/t_scalbn.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $ */
211be35a1SLionel Sambuc 
311be35a1SLionel Sambuc /*-
411be35a1SLionel Sambuc  * Copyright (c) 2011 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc  * All rights reserved.
611be35a1SLionel Sambuc  *
711be35a1SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
811be35a1SLionel Sambuc  * by Jukka Ruohonen.
911be35a1SLionel Sambuc  *
1011be35a1SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
1111be35a1SLionel Sambuc  * modification, are permitted provided that the following conditions
1211be35a1SLionel Sambuc  * are met:
1311be35a1SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1411be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1511be35a1SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1611be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1711be35a1SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1811be35a1SLionel Sambuc  *
1911be35a1SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2011be35a1SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2111be35a1SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2211be35a1SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2311be35a1SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2411be35a1SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2511be35a1SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2611be35a1SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2711be35a1SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2811be35a1SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2911be35a1SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
3011be35a1SLionel Sambuc  */
3111be35a1SLionel Sambuc #include <sys/cdefs.h>
32*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $");
3311be35a1SLionel Sambuc 
3411be35a1SLionel Sambuc #include <math.h>
3511be35a1SLionel Sambuc #include <limits.h>
3611be35a1SLionel Sambuc #include <float.h>
3711be35a1SLionel Sambuc #include <errno.h>
3811be35a1SLionel Sambuc 
3911be35a1SLionel Sambuc #include <atf-c.h>
4011be35a1SLionel Sambuc 
4111be35a1SLionel Sambuc static const int exps[] = { 0, 1, -1, 100, -100 };
4211be35a1SLionel Sambuc 
4311be35a1SLionel Sambuc /* tests here do not require specific precision, so we just use double */
4411be35a1SLionel Sambuc struct testcase {
4511be35a1SLionel Sambuc 	int exp;
4611be35a1SLionel Sambuc 	double inval;
4711be35a1SLionel Sambuc 	double result;
4811be35a1SLionel Sambuc 	int error;
4911be35a1SLionel Sambuc };
5011be35a1SLionel Sambuc struct testcase test_vals[] = {
5111be35a1SLionel Sambuc 	{ 0,		1.00085,	1.00085,	0 },
5211be35a1SLionel Sambuc 	{ 0,		0.99755,	0.99755,	0 },
5311be35a1SLionel Sambuc 	{ 0,		-1.00085,	-1.00085,	0 },
5411be35a1SLionel Sambuc 	{ 0,		-0.99755,	-0.99755,	0 },
5511be35a1SLionel Sambuc 	{ 1,		1.00085,	2.0* 1.00085,	0 },
5611be35a1SLionel Sambuc 	{ 1,		0.99755,	2.0* 0.99755,	0 },
5711be35a1SLionel Sambuc 	{ 1,		-1.00085,	2.0* -1.00085,	0 },
5811be35a1SLionel Sambuc 	{ 1,		-0.99755,	2.0* -0.99755,	0 },
5911be35a1SLionel Sambuc 
6011be35a1SLionel Sambuc 	/*
6111be35a1SLionel Sambuc 	 * We could add more corner test cases here, but we would have to
6211be35a1SLionel Sambuc 	 * add some ifdefs for the exact format and use a reliable
6311be35a1SLionel Sambuc 	 * generator program - bail for now and only do trivial stuff above.
6411be35a1SLionel Sambuc 	 */
6511be35a1SLionel Sambuc };
6611be35a1SLionel Sambuc 
6711be35a1SLionel Sambuc /*
6811be35a1SLionel Sambuc  * scalbn(3)
6911be35a1SLionel Sambuc  */
7011be35a1SLionel Sambuc ATF_TC(scalbn_val);
ATF_TC_HEAD(scalbn_val,tc)7111be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_val, tc)
7211be35a1SLionel Sambuc {
7311be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values");
7411be35a1SLionel Sambuc }
7511be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_val,tc)7611be35a1SLionel Sambuc ATF_TC_BODY(scalbn_val, tc)
7711be35a1SLionel Sambuc {
7811be35a1SLionel Sambuc 	const struct testcase *tests = test_vals;
7911be35a1SLionel Sambuc 	const size_t tcnt = __arraycount(test_vals);
8011be35a1SLionel Sambuc 	size_t i;
8111be35a1SLionel Sambuc 	double rv;
8211be35a1SLionel Sambuc 
8311be35a1SLionel Sambuc 	for (i = 0; i < tcnt; i++) {
8411be35a1SLionel Sambuc 		rv = scalbn(tests[i].inval, tests[i].exp);
8511be35a1SLionel Sambuc 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
8611be35a1SLionel Sambuc 		    "test %zu: errno %d instead of %d", i, errno,
8711be35a1SLionel Sambuc 		    tests[i].error);
8811be35a1SLionel Sambuc 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON,
8911be35a1SLionel Sambuc 		    "test %zu: return value %g instead of %g (difference %g)",
9011be35a1SLionel Sambuc 		    i, rv, tests[i].result, tests[i].result-rv);
9111be35a1SLionel Sambuc 	}
9211be35a1SLionel Sambuc }
9311be35a1SLionel Sambuc 
9411be35a1SLionel Sambuc ATF_TC(scalbn_nan);
ATF_TC_HEAD(scalbn_nan,tc)9511be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_nan, tc)
9611be35a1SLionel Sambuc {
9711be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN");
9811be35a1SLionel Sambuc }
9911be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_nan,tc)10011be35a1SLionel Sambuc ATF_TC_BODY(scalbn_nan, tc)
10111be35a1SLionel Sambuc {
10211be35a1SLionel Sambuc 	const double x = 0.0L / 0.0L;
10311be35a1SLionel Sambuc 	double y;
10411be35a1SLionel Sambuc 	size_t i;
10511be35a1SLionel Sambuc 
10611be35a1SLionel Sambuc 	ATF_REQUIRE(isnan(x) != 0);
10711be35a1SLionel Sambuc 
10811be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
10911be35a1SLionel Sambuc 		y = scalbn(x, exps[i]);
11011be35a1SLionel Sambuc 		ATF_CHECK(isnan(y) != 0);
11111be35a1SLionel Sambuc 	}
11211be35a1SLionel Sambuc }
11311be35a1SLionel Sambuc 
11411be35a1SLionel Sambuc ATF_TC(scalbn_inf_neg);
ATF_TC_HEAD(scalbn_inf_neg,tc)11511be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_inf_neg, tc)
11611be35a1SLionel Sambuc {
11711be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf");
11811be35a1SLionel Sambuc }
11911be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_inf_neg,tc)12011be35a1SLionel Sambuc ATF_TC_BODY(scalbn_inf_neg, tc)
12111be35a1SLionel Sambuc {
12211be35a1SLionel Sambuc 	const double x = -1.0L / 0.0L;
12311be35a1SLionel Sambuc 	size_t i;
12411be35a1SLionel Sambuc 
12511be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
12611be35a1SLionel Sambuc 		ATF_CHECK(scalbn(x, exps[i]) == x);
12711be35a1SLionel Sambuc }
12811be35a1SLionel Sambuc 
12911be35a1SLionel Sambuc ATF_TC(scalbn_inf_pos);
ATF_TC_HEAD(scalbn_inf_pos,tc)13011be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_inf_pos, tc)
13111be35a1SLionel Sambuc {
13211be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf");
13311be35a1SLionel Sambuc }
13411be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_inf_pos,tc)13511be35a1SLionel Sambuc ATF_TC_BODY(scalbn_inf_pos, tc)
13611be35a1SLionel Sambuc {
13711be35a1SLionel Sambuc 	const double x = 1.0L / 0.0L;
13811be35a1SLionel Sambuc 	size_t i;
13911be35a1SLionel Sambuc 
14011be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
14111be35a1SLionel Sambuc 		ATF_CHECK(scalbn(x, exps[i]) == x);
14211be35a1SLionel Sambuc }
14311be35a1SLionel Sambuc 
14411be35a1SLionel Sambuc ATF_TC(scalbn_ldexp);
ATF_TC_HEAD(scalbn_ldexp,tc)14511be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_ldexp, tc)
14611be35a1SLionel Sambuc {
14711be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)");
14811be35a1SLionel Sambuc }
14911be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_ldexp,tc)15011be35a1SLionel Sambuc ATF_TC_BODY(scalbn_ldexp, tc)
15111be35a1SLionel Sambuc {
15211be35a1SLionel Sambuc #if FLT_RADIX == 2
15311be35a1SLionel Sambuc 	const double x = 2.91288191221812821;
15411be35a1SLionel Sambuc 	double y;
15511be35a1SLionel Sambuc 	size_t i;
15611be35a1SLionel Sambuc 
15711be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
15811be35a1SLionel Sambuc 		y = scalbn(x, exps[i]);
15911be35a1SLionel Sambuc 		ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, "
16011be35a1SLionel Sambuc 		    "y=%g, expected %g (diff: %g)", i, exps[i], y,
16111be35a1SLionel Sambuc 		    ldexp(x, exps[i]), y - ldexp(x, exps[i]));
16211be35a1SLionel Sambuc 	}
16311be35a1SLionel Sambuc #endif
16411be35a1SLionel Sambuc }
16511be35a1SLionel Sambuc 
16611be35a1SLionel Sambuc ATF_TC(scalbn_zero_neg);
ATF_TC_HEAD(scalbn_zero_neg,tc)16711be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_zero_neg, tc)
16811be35a1SLionel Sambuc {
16911be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0");
17011be35a1SLionel Sambuc }
17111be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_zero_neg,tc)17211be35a1SLionel Sambuc ATF_TC_BODY(scalbn_zero_neg, tc)
17311be35a1SLionel Sambuc {
17411be35a1SLionel Sambuc 	const double x = -0.0L;
17511be35a1SLionel Sambuc 	double y;
17611be35a1SLionel Sambuc 	size_t i;
17711be35a1SLionel Sambuc 
17811be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) != 0);
17911be35a1SLionel Sambuc 
18011be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
18111be35a1SLionel Sambuc 		y = scalbn(x, exps[i]);
18211be35a1SLionel Sambuc 		ATF_CHECK(x == y);
18311be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) != 0);
18411be35a1SLionel Sambuc 	}
18511be35a1SLionel Sambuc }
18611be35a1SLionel Sambuc 
18711be35a1SLionel Sambuc ATF_TC(scalbn_zero_pos);
ATF_TC_HEAD(scalbn_zero_pos,tc)18811be35a1SLionel Sambuc ATF_TC_HEAD(scalbn_zero_pos, tc)
18911be35a1SLionel Sambuc {
19011be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0");
19111be35a1SLionel Sambuc }
19211be35a1SLionel Sambuc 
ATF_TC_BODY(scalbn_zero_pos,tc)19311be35a1SLionel Sambuc ATF_TC_BODY(scalbn_zero_pos, tc)
19411be35a1SLionel Sambuc {
19511be35a1SLionel Sambuc 	const double x = 0.0L;
19611be35a1SLionel Sambuc 	double y;
19711be35a1SLionel Sambuc 	size_t i;
19811be35a1SLionel Sambuc 
19911be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) == 0);
20011be35a1SLionel Sambuc 
20111be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
20211be35a1SLionel Sambuc 		y = scalbn(x, exps[i]);
20311be35a1SLionel Sambuc 		ATF_CHECK(x == y);
20411be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) == 0);
20511be35a1SLionel Sambuc 	}
20611be35a1SLionel Sambuc }
20711be35a1SLionel Sambuc 
20811be35a1SLionel Sambuc /*
20911be35a1SLionel Sambuc  * scalbnf(3)
21011be35a1SLionel Sambuc  */
21111be35a1SLionel Sambuc ATF_TC(scalbnf_val);
ATF_TC_HEAD(scalbnf_val,tc)21211be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_val, tc)
21311be35a1SLionel Sambuc {
21411be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values");
21511be35a1SLionel Sambuc }
21611be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_val,tc)21711be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_val, tc)
21811be35a1SLionel Sambuc {
21911be35a1SLionel Sambuc 	const struct testcase *tests = test_vals;
22011be35a1SLionel Sambuc 	const size_t tcnt = __arraycount(test_vals);
22111be35a1SLionel Sambuc 	size_t i;
22211be35a1SLionel Sambuc 	double rv;
22311be35a1SLionel Sambuc 
22411be35a1SLionel Sambuc 	for (i = 0; i < tcnt; i++) {
22511be35a1SLionel Sambuc 		rv = scalbnf(tests[i].inval, tests[i].exp);
22611be35a1SLionel Sambuc 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
22711be35a1SLionel Sambuc 		    "test %zu: errno %d instead of %d", i, errno,
22811be35a1SLionel Sambuc 		    tests[i].error);
22911be35a1SLionel Sambuc 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON,
23011be35a1SLionel Sambuc 		    "test %zu: return value %g instead of %g (difference %g)",
23111be35a1SLionel Sambuc 		    i, rv, tests[i].result, tests[i].result-rv);
23211be35a1SLionel Sambuc 	}
23311be35a1SLionel Sambuc }
23411be35a1SLionel Sambuc 
23511be35a1SLionel Sambuc ATF_TC(scalbnf_nan);
ATF_TC_HEAD(scalbnf_nan,tc)23611be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_nan, tc)
23711be35a1SLionel Sambuc {
23811be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
23911be35a1SLionel Sambuc }
24011be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_nan,tc)24111be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_nan, tc)
24211be35a1SLionel Sambuc {
24311be35a1SLionel Sambuc 	const float x = 0.0L / 0.0L;
24411be35a1SLionel Sambuc 	float y;
24511be35a1SLionel Sambuc 	size_t i;
24611be35a1SLionel Sambuc 
24711be35a1SLionel Sambuc 	ATF_REQUIRE(isnan(x) != 0);
24811be35a1SLionel Sambuc 
24911be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
25011be35a1SLionel Sambuc 		y = scalbnf(x, exps[i]);
25111be35a1SLionel Sambuc 		ATF_CHECK(isnan(y) != 0);
25211be35a1SLionel Sambuc 	}
25311be35a1SLionel Sambuc }
25411be35a1SLionel Sambuc 
25511be35a1SLionel Sambuc ATF_TC(scalbnf_inf_neg);
ATF_TC_HEAD(scalbnf_inf_neg,tc)25611be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_inf_neg, tc)
25711be35a1SLionel Sambuc {
25811be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
25911be35a1SLionel Sambuc }
26011be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_inf_neg,tc)26111be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_inf_neg, tc)
26211be35a1SLionel Sambuc {
26311be35a1SLionel Sambuc 	const float x = -1.0L / 0.0L;
26411be35a1SLionel Sambuc 	size_t i;
26511be35a1SLionel Sambuc 
26611be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
26711be35a1SLionel Sambuc 		ATF_CHECK(scalbnf(x, exps[i]) == x);
26811be35a1SLionel Sambuc }
26911be35a1SLionel Sambuc 
27011be35a1SLionel Sambuc ATF_TC(scalbnf_inf_pos);
ATF_TC_HEAD(scalbnf_inf_pos,tc)27111be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_inf_pos, tc)
27211be35a1SLionel Sambuc {
27311be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
27411be35a1SLionel Sambuc }
27511be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_inf_pos,tc)27611be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_inf_pos, tc)
27711be35a1SLionel Sambuc {
27811be35a1SLionel Sambuc 	const float x = 1.0L / 0.0L;
27911be35a1SLionel Sambuc 	size_t i;
28011be35a1SLionel Sambuc 
28111be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
28211be35a1SLionel Sambuc 		ATF_CHECK(scalbnf(x, exps[i]) == x);
28311be35a1SLionel Sambuc }
28411be35a1SLionel Sambuc 
28511be35a1SLionel Sambuc ATF_TC(scalbnf_ldexpf);
ATF_TC_HEAD(scalbnf_ldexpf,tc)28611be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_ldexpf, tc)
28711be35a1SLionel Sambuc {
28811be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
28911be35a1SLionel Sambuc }
29011be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_ldexpf,tc)29111be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_ldexpf, tc)
29211be35a1SLionel Sambuc {
29311be35a1SLionel Sambuc #if FLT_RADIX == 2
29411be35a1SLionel Sambuc 	const float x = 2.91288191221812821;
29511be35a1SLionel Sambuc 	float y;
29611be35a1SLionel Sambuc 	size_t i;
29711be35a1SLionel Sambuc 
29811be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
29911be35a1SLionel Sambuc 		y = scalbnf(x, exps[i]);
30011be35a1SLionel Sambuc 		ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
30111be35a1SLionel Sambuc 		    "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
30211be35a1SLionel Sambuc 		    i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
30311be35a1SLionel Sambuc 	}
30411be35a1SLionel Sambuc #endif
30511be35a1SLionel Sambuc }
30611be35a1SLionel Sambuc 
30711be35a1SLionel Sambuc ATF_TC(scalbnf_zero_neg);
ATF_TC_HEAD(scalbnf_zero_neg,tc)30811be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_zero_neg, tc)
30911be35a1SLionel Sambuc {
31011be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
31111be35a1SLionel Sambuc }
31211be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_zero_neg,tc)31311be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_zero_neg, tc)
31411be35a1SLionel Sambuc {
31511be35a1SLionel Sambuc 	const float x = -0.0L;
31611be35a1SLionel Sambuc 	float y;
31711be35a1SLionel Sambuc 	size_t i;
31811be35a1SLionel Sambuc 
31911be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) != 0);
32011be35a1SLionel Sambuc 
32111be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
32211be35a1SLionel Sambuc 		y = scalbnf(x, exps[i]);
32311be35a1SLionel Sambuc 		ATF_CHECK(x == y);
32411be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) != 0);
32511be35a1SLionel Sambuc 	}
32611be35a1SLionel Sambuc }
32711be35a1SLionel Sambuc 
32811be35a1SLionel Sambuc ATF_TC(scalbnf_zero_pos);
ATF_TC_HEAD(scalbnf_zero_pos,tc)32911be35a1SLionel Sambuc ATF_TC_HEAD(scalbnf_zero_pos, tc)
33011be35a1SLionel Sambuc {
33111be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
33211be35a1SLionel Sambuc }
33311be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnf_zero_pos,tc)33411be35a1SLionel Sambuc ATF_TC_BODY(scalbnf_zero_pos, tc)
33511be35a1SLionel Sambuc {
33611be35a1SLionel Sambuc 	const float x = 0.0L;
33711be35a1SLionel Sambuc 	float y;
33811be35a1SLionel Sambuc 	size_t i;
33911be35a1SLionel Sambuc 
34011be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) == 0);
34111be35a1SLionel Sambuc 
34211be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
34311be35a1SLionel Sambuc 		y = scalbnf(x, exps[i]);
34411be35a1SLionel Sambuc 		ATF_CHECK(x == y);
34511be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) == 0);
34611be35a1SLionel Sambuc 	}
34711be35a1SLionel Sambuc }
34811be35a1SLionel Sambuc 
34911be35a1SLionel Sambuc /*
35011be35a1SLionel Sambuc  * scalbnl(3)
35111be35a1SLionel Sambuc  */
35211be35a1SLionel Sambuc ATF_TC(scalbnl_val);
ATF_TC_HEAD(scalbnl_val,tc)35311be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_val, tc)
35411be35a1SLionel Sambuc {
35511be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
35611be35a1SLionel Sambuc }
35711be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_val,tc)35811be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_val, tc)
35911be35a1SLionel Sambuc {
36011be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
36111be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
36211be35a1SLionel Sambuc #else
36311be35a1SLionel Sambuc 	const struct testcase *tests = test_vals;
36411be35a1SLionel Sambuc 	const size_t tcnt = __arraycount(test_vals);
36511be35a1SLionel Sambuc 	size_t i;
36611be35a1SLionel Sambuc 	long double rv;
36711be35a1SLionel Sambuc 
36811be35a1SLionel Sambuc 	for (i = 0; i < tcnt; i++) {
36911be35a1SLionel Sambuc 		rv = scalbnl(tests[i].inval, tests[i].exp);
37011be35a1SLionel Sambuc 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
37111be35a1SLionel Sambuc 		    "test %zu: errno %d instead of %d", i, errno,
37211be35a1SLionel Sambuc 		    tests[i].error);
37311be35a1SLionel Sambuc 		ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON,
37411be35a1SLionel Sambuc 		    "test %zu: return value %Lg instead of %Lg (difference %Lg)",
37511be35a1SLionel Sambuc 		    i, rv, (long double)tests[i].result, (long double)tests[i].result-rv);
37611be35a1SLionel Sambuc 	}
37711be35a1SLionel Sambuc #endif
37811be35a1SLionel Sambuc }
37911be35a1SLionel Sambuc 
38011be35a1SLionel Sambuc ATF_TC(scalbnl_nan);
ATF_TC_HEAD(scalbnl_nan,tc)38111be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_nan, tc)
38211be35a1SLionel Sambuc {
38311be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
38411be35a1SLionel Sambuc }
38511be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_nan,tc)38611be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_nan, tc)
38711be35a1SLionel Sambuc {
38811be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
38911be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
39011be35a1SLionel Sambuc #else
39111be35a1SLionel Sambuc 	const long double x = 0.0L / 0.0L;
39211be35a1SLionel Sambuc 	long double y;
39311be35a1SLionel Sambuc 	size_t i;
39411be35a1SLionel Sambuc 
39511be35a1SLionel Sambuc 	if (isnan(x) == 0) {
39611be35a1SLionel Sambuc 		atf_tc_expect_fail("PR lib/45362");
39711be35a1SLionel Sambuc 		atf_tc_fail("(0.0L / 0.0L) != NaN");
39811be35a1SLionel Sambuc 	}
39911be35a1SLionel Sambuc 
40011be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
40111be35a1SLionel Sambuc 		y = scalbnl(x, exps[i]);
40211be35a1SLionel Sambuc 		ATF_CHECK(isnan(y) != 0);
40311be35a1SLionel Sambuc 	}
40411be35a1SLionel Sambuc #endif
40511be35a1SLionel Sambuc }
40611be35a1SLionel Sambuc 
40711be35a1SLionel Sambuc ATF_TC(scalbnl_inf_neg);
ATF_TC_HEAD(scalbnl_inf_neg,tc)40811be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_inf_neg, tc)
40911be35a1SLionel Sambuc {
41011be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
41111be35a1SLionel Sambuc }
41211be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_inf_neg,tc)41311be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_inf_neg, tc)
41411be35a1SLionel Sambuc {
41511be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
41611be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
41711be35a1SLionel Sambuc #else
41811be35a1SLionel Sambuc 	const long double x = -1.0L / 0.0L;
41911be35a1SLionel Sambuc 	size_t i;
42011be35a1SLionel Sambuc 
42111be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
42211be35a1SLionel Sambuc 		ATF_CHECK(scalbnl(x, exps[i]) == x);
42311be35a1SLionel Sambuc #endif
42411be35a1SLionel Sambuc }
42511be35a1SLionel Sambuc 
42611be35a1SLionel Sambuc ATF_TC(scalbnl_inf_pos);
ATF_TC_HEAD(scalbnl_inf_pos,tc)42711be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_inf_pos, tc)
42811be35a1SLionel Sambuc {
42911be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
43011be35a1SLionel Sambuc }
43111be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_inf_pos,tc)43211be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_inf_pos, tc)
43311be35a1SLionel Sambuc {
43411be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
43511be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
43611be35a1SLionel Sambuc #else
43711be35a1SLionel Sambuc 	const long double x = 1.0L / 0.0L;
43811be35a1SLionel Sambuc 	size_t i;
43911be35a1SLionel Sambuc 
44011be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++)
44111be35a1SLionel Sambuc 		ATF_CHECK(scalbnl(x, exps[i]) == x);
44211be35a1SLionel Sambuc #endif
44311be35a1SLionel Sambuc }
44411be35a1SLionel Sambuc 
44511be35a1SLionel Sambuc ATF_TC(scalbnl_zero_neg);
ATF_TC_HEAD(scalbnl_zero_neg,tc)44611be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_zero_neg, tc)
44711be35a1SLionel Sambuc {
44811be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
44911be35a1SLionel Sambuc }
45011be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_zero_neg,tc)45111be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_zero_neg, tc)
45211be35a1SLionel Sambuc {
45311be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
45411be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
45511be35a1SLionel Sambuc #else
45611be35a1SLionel Sambuc 	const long double x = -0.0L;
45711be35a1SLionel Sambuc 	long double y;
45811be35a1SLionel Sambuc 	size_t i;
45911be35a1SLionel Sambuc 
46011be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) != 0);
46111be35a1SLionel Sambuc 
46211be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
46311be35a1SLionel Sambuc 		y = scalbnl(x, exps[i]);
46411be35a1SLionel Sambuc 		ATF_CHECK(x == y);
46511be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) != 0);
46611be35a1SLionel Sambuc 	}
46711be35a1SLionel Sambuc #endif
46811be35a1SLionel Sambuc }
46911be35a1SLionel Sambuc 
47011be35a1SLionel Sambuc ATF_TC(scalbnl_zero_pos);
ATF_TC_HEAD(scalbnl_zero_pos,tc)47111be35a1SLionel Sambuc ATF_TC_HEAD(scalbnl_zero_pos, tc)
47211be35a1SLionel Sambuc {
47311be35a1SLionel Sambuc 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
47411be35a1SLionel Sambuc }
47511be35a1SLionel Sambuc 
ATF_TC_BODY(scalbnl_zero_pos,tc)47611be35a1SLionel Sambuc ATF_TC_BODY(scalbnl_zero_pos, tc)
47711be35a1SLionel Sambuc {
47811be35a1SLionel Sambuc #ifndef __HAVE_LONG_DOUBLE
47911be35a1SLionel Sambuc 	atf_tc_skip("Requires long double support");
48011be35a1SLionel Sambuc #else
48111be35a1SLionel Sambuc 	const long double x = 0.0L;
48211be35a1SLionel Sambuc 	long double y;
48311be35a1SLionel Sambuc 	size_t i;
48411be35a1SLionel Sambuc 
48511be35a1SLionel Sambuc 	ATF_REQUIRE(signbit(x) == 0);
48611be35a1SLionel Sambuc 
48711be35a1SLionel Sambuc 	for (i = 0; i < __arraycount(exps); i++) {
48811be35a1SLionel Sambuc 		y = scalbnl(x, exps[i]);
48911be35a1SLionel Sambuc 		ATF_CHECK(x == y);
49011be35a1SLionel Sambuc 		ATF_CHECK(signbit(y) == 0);
49111be35a1SLionel Sambuc 	}
49211be35a1SLionel Sambuc #endif
49311be35a1SLionel Sambuc }
49411be35a1SLionel Sambuc 
ATF_TP_ADD_TCS(tp)49511be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
49611be35a1SLionel Sambuc {
49711be35a1SLionel Sambuc 
49811be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_val);
49911be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_nan);
50011be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_inf_neg);
50111be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_inf_pos);
50211be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_ldexp);
50311be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_zero_neg);
50411be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbn_zero_pos);
50511be35a1SLionel Sambuc 
50611be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_val);
50711be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_nan);
50811be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
50911be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
51011be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
51111be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
51211be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
51311be35a1SLionel Sambuc 
51411be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_val);
51511be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_nan);
51611be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
51711be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
51811be35a1SLionel Sambuc /*	ATF_TP_ADD_TC(tp, scalbnl_ldexp);	*/
51911be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
52011be35a1SLionel Sambuc 	ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
52111be35a1SLionel Sambuc 
52211be35a1SLionel Sambuc 	return atf_no_error();
52311be35a1SLionel Sambuc }
524