11ec3feb6SAlex Richardson /* $NetBSD: t_scalbn.c,v 1.16 2018/11/07 03:59:36 riastradh 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>
321ec3feb6SAlex Richardson __RCSID("$NetBSD: t_scalbn.c,v 1.16 2018/11/07 03:59:36 riastradh Exp $");
3357718be8SEnji Cooper
3457718be8SEnji Cooper #include <math.h>
3557718be8SEnji Cooper #include <limits.h>
3657718be8SEnji Cooper #include <float.h>
3757718be8SEnji Cooper #include <errno.h>
381ec3feb6SAlex Richardson #include <fenv.h>
3957718be8SEnji Cooper
4057718be8SEnji Cooper #include <atf-c.h>
4157718be8SEnji Cooper
4257718be8SEnji Cooper static const int exps[] = { 0, 1, -1, 100, -100 };
4357718be8SEnji Cooper
4457718be8SEnji Cooper /* tests here do not require specific precision, so we just use double */
4557718be8SEnji Cooper struct testcase {
4657718be8SEnji Cooper int exp;
4757718be8SEnji Cooper double inval;
4857718be8SEnji Cooper double result;
4957718be8SEnji Cooper int error;
501ec3feb6SAlex Richardson int except;
5157718be8SEnji Cooper };
52*87d65c74SAlex Richardson static struct testcase test_vals[] = {
531ec3feb6SAlex Richardson { 0, 1.00085, 1.00085, 0, 0 },
541ec3feb6SAlex Richardson { 0, 0.99755, 0.99755, 0, 0 },
551ec3feb6SAlex Richardson { 0, -1.00085, -1.00085, 0, 0 },
561ec3feb6SAlex Richardson { 0, -0.99755, -0.99755, 0, 0 },
571ec3feb6SAlex Richardson { 1, 1.00085, 2.0* 1.00085, 0, 0 },
581ec3feb6SAlex Richardson { 1, 0.99755, 2.0* 0.99755, 0, 0 },
591ec3feb6SAlex Richardson { 1, -1.00085, 2.0* -1.00085, 0, 0 },
601ec3feb6SAlex Richardson { 1, -0.99755, 2.0* -0.99755, 0, 0 },
6157718be8SEnji Cooper
6257718be8SEnji Cooper /*
6357718be8SEnji Cooper * We could add more corner test cases here, but we would have to
6457718be8SEnji Cooper * add some ifdefs for the exact format and use a reliable
6557718be8SEnji Cooper * generator program - bail for now and only do trivial stuff above.
6657718be8SEnji Cooper */
6757718be8SEnji Cooper };
6857718be8SEnji Cooper
6957718be8SEnji Cooper /*
7057718be8SEnji Cooper * scalbn(3)
7157718be8SEnji Cooper */
7257718be8SEnji Cooper ATF_TC(scalbn_val);
ATF_TC_HEAD(scalbn_val,tc)7357718be8SEnji Cooper ATF_TC_HEAD(scalbn_val, tc)
7457718be8SEnji Cooper {
7557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values");
7657718be8SEnji Cooper }
7757718be8SEnji Cooper
ATF_TC_BODY(scalbn_val,tc)7857718be8SEnji Cooper ATF_TC_BODY(scalbn_val, tc)
7957718be8SEnji Cooper {
8057718be8SEnji Cooper const struct testcase *tests = test_vals;
8157718be8SEnji Cooper const size_t tcnt = __arraycount(test_vals);
8257718be8SEnji Cooper size_t i;
8357718be8SEnji Cooper double rv;
8457718be8SEnji Cooper
8557718be8SEnji Cooper for (i = 0; i < tcnt; i++) {
8679097302SEnji Cooper errno = 0;
871ec3feb6SAlex Richardson #ifndef __vax__
881ec3feb6SAlex Richardson feclearexcept(FE_ALL_EXCEPT);
891ec3feb6SAlex Richardson #endif
9057718be8SEnji Cooper rv = scalbn(tests[i].inval, tests[i].exp);
9157718be8SEnji Cooper ATF_CHECK_EQ_MSG(errno, tests[i].error,
9257718be8SEnji Cooper "test %zu: errno %d instead of %d", i, errno,
9357718be8SEnji Cooper tests[i].error);
941ec3feb6SAlex Richardson #ifndef __vax__
951ec3feb6SAlex Richardson ATF_CHECK_EQ_MSG(errno, tests[i].error,
961ec3feb6SAlex Richardson "test %zu: fetestexcept %d instead of %d", i,
971ec3feb6SAlex Richardson fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW),
981ec3feb6SAlex Richardson tests[i].except);
991ec3feb6SAlex Richardson #endif
1001ec3feb6SAlex Richardson /* scalbn is always exact except for underflow or overflow. */
1011ec3feb6SAlex Richardson ATF_CHECK_MSG(rv == tests[i].result,
1021ec3feb6SAlex Richardson "test %zu: return value %.17g instead of %.17g"
1031ec3feb6SAlex Richardson " (error %.17g)",
1041ec3feb6SAlex Richardson i, rv, tests[i].result,
1051ec3feb6SAlex Richardson fabs((tests[i].result - rv)/tests[i].result));
10657718be8SEnji Cooper }
10757718be8SEnji Cooper }
10857718be8SEnji Cooper
10957718be8SEnji Cooper ATF_TC(scalbn_nan);
ATF_TC_HEAD(scalbn_nan,tc)11057718be8SEnji Cooper ATF_TC_HEAD(scalbn_nan, tc)
11157718be8SEnji Cooper {
11257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN");
11357718be8SEnji Cooper }
11457718be8SEnji Cooper
ATF_TC_BODY(scalbn_nan,tc)11557718be8SEnji Cooper ATF_TC_BODY(scalbn_nan, tc)
11657718be8SEnji Cooper {
11757718be8SEnji Cooper const double x = 0.0L / 0.0L;
11857718be8SEnji Cooper double y;
11957718be8SEnji Cooper size_t i;
12057718be8SEnji Cooper
12157718be8SEnji Cooper ATF_REQUIRE(isnan(x) != 0);
12257718be8SEnji Cooper
12357718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
12457718be8SEnji Cooper y = scalbn(x, exps[i]);
12557718be8SEnji Cooper ATF_CHECK(isnan(y) != 0);
12657718be8SEnji Cooper }
12757718be8SEnji Cooper }
12857718be8SEnji Cooper
12957718be8SEnji Cooper ATF_TC(scalbn_inf_neg);
ATF_TC_HEAD(scalbn_inf_neg,tc)13057718be8SEnji Cooper ATF_TC_HEAD(scalbn_inf_neg, tc)
13157718be8SEnji Cooper {
13257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf");
13357718be8SEnji Cooper }
13457718be8SEnji Cooper
ATF_TC_BODY(scalbn_inf_neg,tc)13557718be8SEnji Cooper ATF_TC_BODY(scalbn_inf_neg, tc)
13657718be8SEnji Cooper {
13757718be8SEnji Cooper const double x = -1.0L / 0.0L;
13857718be8SEnji Cooper size_t i;
13957718be8SEnji Cooper
14057718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
14157718be8SEnji Cooper ATF_CHECK(scalbn(x, exps[i]) == x);
14257718be8SEnji Cooper }
14357718be8SEnji Cooper
14457718be8SEnji Cooper ATF_TC(scalbn_inf_pos);
ATF_TC_HEAD(scalbn_inf_pos,tc)14557718be8SEnji Cooper ATF_TC_HEAD(scalbn_inf_pos, tc)
14657718be8SEnji Cooper {
14757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf");
14857718be8SEnji Cooper }
14957718be8SEnji Cooper
ATF_TC_BODY(scalbn_inf_pos,tc)15057718be8SEnji Cooper ATF_TC_BODY(scalbn_inf_pos, tc)
15157718be8SEnji Cooper {
15257718be8SEnji Cooper const double x = 1.0L / 0.0L;
15357718be8SEnji Cooper size_t i;
15457718be8SEnji Cooper
15557718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
15657718be8SEnji Cooper ATF_CHECK(scalbn(x, exps[i]) == x);
15757718be8SEnji Cooper }
15857718be8SEnji Cooper
15957718be8SEnji Cooper ATF_TC(scalbn_ldexp);
ATF_TC_HEAD(scalbn_ldexp,tc)16057718be8SEnji Cooper ATF_TC_HEAD(scalbn_ldexp, tc)
16157718be8SEnji Cooper {
16257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)");
16357718be8SEnji Cooper }
16457718be8SEnji Cooper
ATF_TC_BODY(scalbn_ldexp,tc)16557718be8SEnji Cooper ATF_TC_BODY(scalbn_ldexp, tc)
16657718be8SEnji Cooper {
16757718be8SEnji Cooper #if FLT_RADIX == 2
16857718be8SEnji Cooper const double x = 2.91288191221812821;
16957718be8SEnji Cooper double y;
17057718be8SEnji Cooper size_t i;
17157718be8SEnji Cooper
17257718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
17357718be8SEnji Cooper y = scalbn(x, exps[i]);
17457718be8SEnji Cooper ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, "
17557718be8SEnji Cooper "y=%g, expected %g (diff: %g)", i, exps[i], y,
17657718be8SEnji Cooper ldexp(x, exps[i]), y - ldexp(x, exps[i]));
17757718be8SEnji Cooper }
17857718be8SEnji Cooper #endif
17957718be8SEnji Cooper }
18057718be8SEnji Cooper
18157718be8SEnji Cooper ATF_TC(scalbn_zero_neg);
ATF_TC_HEAD(scalbn_zero_neg,tc)18257718be8SEnji Cooper ATF_TC_HEAD(scalbn_zero_neg, tc)
18357718be8SEnji Cooper {
18457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0");
18557718be8SEnji Cooper }
18657718be8SEnji Cooper
ATF_TC_BODY(scalbn_zero_neg,tc)18757718be8SEnji Cooper ATF_TC_BODY(scalbn_zero_neg, tc)
18857718be8SEnji Cooper {
18957718be8SEnji Cooper const double x = -0.0L;
19057718be8SEnji Cooper double y;
19157718be8SEnji Cooper size_t i;
19257718be8SEnji Cooper
19357718be8SEnji Cooper ATF_REQUIRE(signbit(x) != 0);
19457718be8SEnji Cooper
19557718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
19657718be8SEnji Cooper y = scalbn(x, exps[i]);
19757718be8SEnji Cooper ATF_CHECK(x == y);
19857718be8SEnji Cooper ATF_CHECK(signbit(y) != 0);
19957718be8SEnji Cooper }
20057718be8SEnji Cooper }
20157718be8SEnji Cooper
20257718be8SEnji Cooper ATF_TC(scalbn_zero_pos);
ATF_TC_HEAD(scalbn_zero_pos,tc)20357718be8SEnji Cooper ATF_TC_HEAD(scalbn_zero_pos, tc)
20457718be8SEnji Cooper {
20557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0");
20657718be8SEnji Cooper }
20757718be8SEnji Cooper
ATF_TC_BODY(scalbn_zero_pos,tc)20857718be8SEnji Cooper ATF_TC_BODY(scalbn_zero_pos, tc)
20957718be8SEnji Cooper {
21057718be8SEnji Cooper const double x = 0.0L;
21157718be8SEnji Cooper double y;
21257718be8SEnji Cooper size_t i;
21357718be8SEnji Cooper
21457718be8SEnji Cooper ATF_REQUIRE(signbit(x) == 0);
21557718be8SEnji Cooper
21657718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
21757718be8SEnji Cooper y = scalbn(x, exps[i]);
21857718be8SEnji Cooper ATF_CHECK(x == y);
21957718be8SEnji Cooper ATF_CHECK(signbit(y) == 0);
22057718be8SEnji Cooper }
22157718be8SEnji Cooper }
22257718be8SEnji Cooper
22357718be8SEnji Cooper /*
22457718be8SEnji Cooper * scalbnf(3)
22557718be8SEnji Cooper */
22657718be8SEnji Cooper ATF_TC(scalbnf_val);
ATF_TC_HEAD(scalbnf_val,tc)22757718be8SEnji Cooper ATF_TC_HEAD(scalbnf_val, tc)
22857718be8SEnji Cooper {
22957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values");
23057718be8SEnji Cooper }
23157718be8SEnji Cooper
ATF_TC_BODY(scalbnf_val,tc)23257718be8SEnji Cooper ATF_TC_BODY(scalbnf_val, tc)
23357718be8SEnji Cooper {
23457718be8SEnji Cooper const struct testcase *tests = test_vals;
23557718be8SEnji Cooper const size_t tcnt = __arraycount(test_vals);
23657718be8SEnji Cooper size_t i;
23757718be8SEnji Cooper double rv;
23857718be8SEnji Cooper
23957718be8SEnji Cooper for (i = 0; i < tcnt; i++) {
2408fe9679fSEnji Cooper errno = 0;
24157718be8SEnji Cooper rv = scalbnf(tests[i].inval, tests[i].exp);
24257718be8SEnji Cooper ATF_CHECK_EQ_MSG(errno, tests[i].error,
24357718be8SEnji Cooper "test %zu: errno %d instead of %d", i, errno,
24457718be8SEnji Cooper tests[i].error);
2451ec3feb6SAlex Richardson /* scalbn is always exact except for underflow or overflow. */
2461ec3feb6SAlex Richardson ATF_CHECK_MSG(rv == (float)tests[i].result,
2471ec3feb6SAlex Richardson "test %zu: return value %.8g instead of %.8g"
2481ec3feb6SAlex Richardson " (error %.8g)",
2491ec3feb6SAlex Richardson i, rv, tests[i].result,
2501ec3feb6SAlex Richardson fabs((tests[i].result - rv)/tests[i].result));
25157718be8SEnji Cooper }
25257718be8SEnji Cooper }
25357718be8SEnji Cooper
25457718be8SEnji Cooper ATF_TC(scalbnf_nan);
ATF_TC_HEAD(scalbnf_nan,tc)25557718be8SEnji Cooper ATF_TC_HEAD(scalbnf_nan, tc)
25657718be8SEnji Cooper {
25757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
25857718be8SEnji Cooper }
25957718be8SEnji Cooper
ATF_TC_BODY(scalbnf_nan,tc)26057718be8SEnji Cooper ATF_TC_BODY(scalbnf_nan, tc)
26157718be8SEnji Cooper {
26257718be8SEnji Cooper const float x = 0.0L / 0.0L;
26357718be8SEnji Cooper float y;
26457718be8SEnji Cooper size_t i;
26557718be8SEnji Cooper
26657718be8SEnji Cooper ATF_REQUIRE(isnan(x) != 0);
26757718be8SEnji Cooper
26857718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
26957718be8SEnji Cooper y = scalbnf(x, exps[i]);
27057718be8SEnji Cooper ATF_CHECK(isnan(y) != 0);
27157718be8SEnji Cooper }
27257718be8SEnji Cooper }
27357718be8SEnji Cooper
27457718be8SEnji Cooper ATF_TC(scalbnf_inf_neg);
ATF_TC_HEAD(scalbnf_inf_neg,tc)27557718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_neg, tc)
27657718be8SEnji Cooper {
27757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
27857718be8SEnji Cooper }
27957718be8SEnji Cooper
ATF_TC_BODY(scalbnf_inf_neg,tc)28057718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_neg, tc)
28157718be8SEnji Cooper {
28257718be8SEnji Cooper const float x = -1.0L / 0.0L;
28357718be8SEnji Cooper size_t i;
28457718be8SEnji Cooper
28557718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
28657718be8SEnji Cooper ATF_CHECK(scalbnf(x, exps[i]) == x);
28757718be8SEnji Cooper }
28857718be8SEnji Cooper
28957718be8SEnji Cooper ATF_TC(scalbnf_inf_pos);
ATF_TC_HEAD(scalbnf_inf_pos,tc)29057718be8SEnji Cooper ATF_TC_HEAD(scalbnf_inf_pos, tc)
29157718be8SEnji Cooper {
29257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
29357718be8SEnji Cooper }
29457718be8SEnji Cooper
ATF_TC_BODY(scalbnf_inf_pos,tc)29557718be8SEnji Cooper ATF_TC_BODY(scalbnf_inf_pos, tc)
29657718be8SEnji Cooper {
29757718be8SEnji Cooper const float x = 1.0L / 0.0L;
29857718be8SEnji Cooper size_t i;
29957718be8SEnji Cooper
30057718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
30157718be8SEnji Cooper ATF_CHECK(scalbnf(x, exps[i]) == x);
30257718be8SEnji Cooper }
30357718be8SEnji Cooper
30457718be8SEnji Cooper ATF_TC(scalbnf_ldexpf);
ATF_TC_HEAD(scalbnf_ldexpf,tc)30557718be8SEnji Cooper ATF_TC_HEAD(scalbnf_ldexpf, tc)
30657718be8SEnji Cooper {
30757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
30857718be8SEnji Cooper }
30957718be8SEnji Cooper
ATF_TC_BODY(scalbnf_ldexpf,tc)31057718be8SEnji Cooper ATF_TC_BODY(scalbnf_ldexpf, tc)
31157718be8SEnji Cooper {
31257718be8SEnji Cooper #if FLT_RADIX == 2
31357718be8SEnji Cooper const float x = 2.91288191221812821;
31457718be8SEnji Cooper float y;
31557718be8SEnji Cooper size_t i;
31657718be8SEnji Cooper
31757718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
31857718be8SEnji Cooper y = scalbnf(x, exps[i]);
31957718be8SEnji Cooper ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
32057718be8SEnji Cooper "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
32157718be8SEnji Cooper i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
32257718be8SEnji Cooper }
32357718be8SEnji Cooper #endif
32457718be8SEnji Cooper }
32557718be8SEnji Cooper
32657718be8SEnji Cooper ATF_TC(scalbnf_zero_neg);
ATF_TC_HEAD(scalbnf_zero_neg,tc)32757718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_neg, tc)
32857718be8SEnji Cooper {
32957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
33057718be8SEnji Cooper }
33157718be8SEnji Cooper
ATF_TC_BODY(scalbnf_zero_neg,tc)33257718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_neg, tc)
33357718be8SEnji Cooper {
33457718be8SEnji Cooper const float x = -0.0L;
33557718be8SEnji Cooper float y;
33657718be8SEnji Cooper size_t i;
33757718be8SEnji Cooper
33857718be8SEnji Cooper ATF_REQUIRE(signbit(x) != 0);
33957718be8SEnji Cooper
34057718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
34157718be8SEnji Cooper y = scalbnf(x, exps[i]);
34257718be8SEnji Cooper ATF_CHECK(x == y);
34357718be8SEnji Cooper ATF_CHECK(signbit(y) != 0);
34457718be8SEnji Cooper }
34557718be8SEnji Cooper }
34657718be8SEnji Cooper
34757718be8SEnji Cooper ATF_TC(scalbnf_zero_pos);
ATF_TC_HEAD(scalbnf_zero_pos,tc)34857718be8SEnji Cooper ATF_TC_HEAD(scalbnf_zero_pos, tc)
34957718be8SEnji Cooper {
35057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
35157718be8SEnji Cooper }
35257718be8SEnji Cooper
ATF_TC_BODY(scalbnf_zero_pos,tc)35357718be8SEnji Cooper ATF_TC_BODY(scalbnf_zero_pos, tc)
35457718be8SEnji Cooper {
35557718be8SEnji Cooper const float x = 0.0L;
35657718be8SEnji Cooper float y;
35757718be8SEnji Cooper size_t i;
35857718be8SEnji Cooper
35957718be8SEnji Cooper ATF_REQUIRE(signbit(x) == 0);
36057718be8SEnji Cooper
36157718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
36257718be8SEnji Cooper y = scalbnf(x, exps[i]);
36357718be8SEnji Cooper ATF_CHECK(x == y);
36457718be8SEnji Cooper ATF_CHECK(signbit(y) == 0);
36557718be8SEnji Cooper }
36657718be8SEnji Cooper }
36757718be8SEnji Cooper
36857718be8SEnji Cooper /*
36957718be8SEnji Cooper * scalbnl(3)
37057718be8SEnji Cooper */
37157718be8SEnji Cooper ATF_TC(scalbnl_val);
ATF_TC_HEAD(scalbnl_val,tc)37257718be8SEnji Cooper ATF_TC_HEAD(scalbnl_val, tc)
37357718be8SEnji Cooper {
37457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
37557718be8SEnji Cooper }
37657718be8SEnji Cooper
ATF_TC_BODY(scalbnl_val,tc)37757718be8SEnji Cooper ATF_TC_BODY(scalbnl_val, tc)
37857718be8SEnji Cooper {
37957718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
38057718be8SEnji Cooper atf_tc_skip("Requires long double support");
38157718be8SEnji Cooper #else
38257718be8SEnji Cooper const struct testcase *tests = test_vals;
38357718be8SEnji Cooper const size_t tcnt = __arraycount(test_vals);
38457718be8SEnji Cooper size_t i;
38557718be8SEnji Cooper long double rv;
38657718be8SEnji Cooper
38757718be8SEnji Cooper for (i = 0; i < tcnt; i++) {
3888fe9679fSEnji Cooper errno = 0;
38957718be8SEnji Cooper rv = scalbnl(tests[i].inval, tests[i].exp);
39057718be8SEnji Cooper ATF_CHECK_EQ_MSG(errno, tests[i].error,
39157718be8SEnji Cooper "test %zu: errno %d instead of %d", i, errno,
39257718be8SEnji Cooper tests[i].error);
3931ec3feb6SAlex Richardson /* scalbn is always exact except for underflow or overflow. */
3941ec3feb6SAlex Richardson ATF_CHECK_MSG(rv == (long double)tests[i].result,
3951ec3feb6SAlex Richardson "test %zu: return value %.35Lg instead of %.35Lg"
3961ec3feb6SAlex Richardson " (error %.35Lg)",
3971ec3feb6SAlex Richardson i, rv, (long double)tests[i].result,
3981ec3feb6SAlex Richardson fabsl(((long double)tests[i].result - rv)/tests[i].result));
39957718be8SEnji Cooper }
40057718be8SEnji Cooper #endif
40157718be8SEnji Cooper }
40257718be8SEnji Cooper
40357718be8SEnji Cooper ATF_TC(scalbnl_nan);
ATF_TC_HEAD(scalbnl_nan,tc)40457718be8SEnji Cooper ATF_TC_HEAD(scalbnl_nan, tc)
40557718be8SEnji Cooper {
40657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
40757718be8SEnji Cooper }
40857718be8SEnji Cooper
ATF_TC_BODY(scalbnl_nan,tc)40957718be8SEnji Cooper ATF_TC_BODY(scalbnl_nan, tc)
41057718be8SEnji Cooper {
41157718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
41257718be8SEnji Cooper atf_tc_skip("Requires long double support");
41357718be8SEnji Cooper #else
41457718be8SEnji Cooper const long double x = 0.0L / 0.0L;
41557718be8SEnji Cooper long double y;
41657718be8SEnji Cooper size_t i;
41757718be8SEnji Cooper
41857718be8SEnji Cooper if (isnan(x) == 0) {
41957718be8SEnji Cooper atf_tc_expect_fail("PR lib/45362");
42057718be8SEnji Cooper atf_tc_fail("(0.0L / 0.0L) != NaN");
42157718be8SEnji Cooper }
42257718be8SEnji Cooper
42357718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
42457718be8SEnji Cooper y = scalbnl(x, exps[i]);
42557718be8SEnji Cooper ATF_CHECK(isnan(y) != 0);
42657718be8SEnji Cooper }
42757718be8SEnji Cooper #endif
42857718be8SEnji Cooper }
42957718be8SEnji Cooper
43057718be8SEnji Cooper ATF_TC(scalbnl_inf_neg);
ATF_TC_HEAD(scalbnl_inf_neg,tc)43157718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_neg, tc)
43257718be8SEnji Cooper {
43357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
43457718be8SEnji Cooper }
43557718be8SEnji Cooper
ATF_TC_BODY(scalbnl_inf_neg,tc)43657718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_neg, tc)
43757718be8SEnji Cooper {
43857718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
43957718be8SEnji Cooper atf_tc_skip("Requires long double support");
44057718be8SEnji Cooper #else
44157718be8SEnji Cooper const long double x = -1.0L / 0.0L;
44257718be8SEnji Cooper size_t i;
44357718be8SEnji Cooper
44457718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
44557718be8SEnji Cooper ATF_CHECK(scalbnl(x, exps[i]) == x);
44657718be8SEnji Cooper #endif
44757718be8SEnji Cooper }
44857718be8SEnji Cooper
44957718be8SEnji Cooper ATF_TC(scalbnl_inf_pos);
ATF_TC_HEAD(scalbnl_inf_pos,tc)45057718be8SEnji Cooper ATF_TC_HEAD(scalbnl_inf_pos, tc)
45157718be8SEnji Cooper {
45257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
45357718be8SEnji Cooper }
45457718be8SEnji Cooper
ATF_TC_BODY(scalbnl_inf_pos,tc)45557718be8SEnji Cooper ATF_TC_BODY(scalbnl_inf_pos, tc)
45657718be8SEnji Cooper {
45757718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
45857718be8SEnji Cooper atf_tc_skip("Requires long double support");
45957718be8SEnji Cooper #else
46057718be8SEnji Cooper const long double x = 1.0L / 0.0L;
46157718be8SEnji Cooper size_t i;
46257718be8SEnji Cooper
46357718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++)
46457718be8SEnji Cooper ATF_CHECK(scalbnl(x, exps[i]) == x);
46557718be8SEnji Cooper #endif
46657718be8SEnji Cooper }
46757718be8SEnji Cooper
46857718be8SEnji Cooper ATF_TC(scalbnl_zero_neg);
ATF_TC_HEAD(scalbnl_zero_neg,tc)46957718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_neg, tc)
47057718be8SEnji Cooper {
47157718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
47257718be8SEnji Cooper }
47357718be8SEnji Cooper
ATF_TC_BODY(scalbnl_zero_neg,tc)47457718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_neg, tc)
47557718be8SEnji Cooper {
47657718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
47757718be8SEnji Cooper atf_tc_skip("Requires long double support");
47857718be8SEnji Cooper #else
47957718be8SEnji Cooper const long double x = -0.0L;
48057718be8SEnji Cooper long double y;
48157718be8SEnji Cooper size_t i;
48257718be8SEnji Cooper
48357718be8SEnji Cooper ATF_REQUIRE(signbit(x) != 0);
48457718be8SEnji Cooper
48557718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
48657718be8SEnji Cooper y = scalbnl(x, exps[i]);
48757718be8SEnji Cooper ATF_CHECK(x == y);
48857718be8SEnji Cooper ATF_CHECK(signbit(y) != 0);
48957718be8SEnji Cooper }
49057718be8SEnji Cooper #endif
49157718be8SEnji Cooper }
49257718be8SEnji Cooper
49357718be8SEnji Cooper ATF_TC(scalbnl_zero_pos);
ATF_TC_HEAD(scalbnl_zero_pos,tc)49457718be8SEnji Cooper ATF_TC_HEAD(scalbnl_zero_pos, tc)
49557718be8SEnji Cooper {
49657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
49757718be8SEnji Cooper }
49857718be8SEnji Cooper
ATF_TC_BODY(scalbnl_zero_pos,tc)49957718be8SEnji Cooper ATF_TC_BODY(scalbnl_zero_pos, tc)
50057718be8SEnji Cooper {
50157718be8SEnji Cooper #ifndef __HAVE_LONG_DOUBLE
50257718be8SEnji Cooper atf_tc_skip("Requires long double support");
50357718be8SEnji Cooper #else
50457718be8SEnji Cooper const long double x = 0.0L;
50557718be8SEnji Cooper long double y;
50657718be8SEnji Cooper size_t i;
50757718be8SEnji Cooper
50857718be8SEnji Cooper ATF_REQUIRE(signbit(x) == 0);
50957718be8SEnji Cooper
51057718be8SEnji Cooper for (i = 0; i < __arraycount(exps); i++) {
51157718be8SEnji Cooper y = scalbnl(x, exps[i]);
51257718be8SEnji Cooper ATF_CHECK(x == y);
51357718be8SEnji Cooper ATF_CHECK(signbit(y) == 0);
51457718be8SEnji Cooper }
51557718be8SEnji Cooper #endif
51657718be8SEnji Cooper }
51757718be8SEnji Cooper
ATF_TP_ADD_TCS(tp)51857718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
51957718be8SEnji Cooper {
52057718be8SEnji Cooper
52157718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_val);
52257718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_nan);
52357718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_inf_neg);
52457718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_inf_pos);
52557718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_ldexp);
52657718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_zero_neg);
52757718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbn_zero_pos);
52857718be8SEnji Cooper
52957718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_val);
53057718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_nan);
53157718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
53257718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
53357718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
53457718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
53557718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
53657718be8SEnji Cooper
53757718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_val);
53857718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_nan);
53957718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
54057718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
54157718be8SEnji Cooper /* ATF_TP_ADD_TC(tp, scalbnl_ldexp); */
54257718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
54357718be8SEnji Cooper ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
54457718be8SEnji Cooper
54557718be8SEnji Cooper return atf_no_error();
54657718be8SEnji Cooper }
547