xref: /netbsd-src/tests/lib/libm/t_pow.c (revision b670cbfc5870850fcb8397dfbc399ff2e5c7e2dd)
1*b670cbfcSriastradh /* $NetBSD: t_pow.c,v 1.6 2024/06/09 16:53:25 riastradh Exp $ */
2719ceba5Sjruoho 
3719ceba5Sjruoho /*-
4719ceba5Sjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5719ceba5Sjruoho  * All rights reserved.
6719ceba5Sjruoho  *
7719ceba5Sjruoho  * This code is derived from software contributed to The NetBSD Foundation
8719ceba5Sjruoho  * by Jukka Ruohonen.
9719ceba5Sjruoho  *
10719ceba5Sjruoho  * Redistribution and use in source and binary forms, with or without
11719ceba5Sjruoho  * modification, are permitted provided that the following conditions
12719ceba5Sjruoho  * are met:
13719ceba5Sjruoho  * 1. Redistributions of source code must retain the above copyright
14719ceba5Sjruoho  *    notice, this list of conditions and the following disclaimer.
15719ceba5Sjruoho  * 2. Redistributions in binary form must reproduce the above copyright
16719ceba5Sjruoho  *    notice, this list of conditions and the following disclaimer in the
17719ceba5Sjruoho  *    documentation and/or other materials provided with the distribution.
18719ceba5Sjruoho  *
19719ceba5Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20719ceba5Sjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21719ceba5Sjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22719ceba5Sjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23719ceba5Sjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24719ceba5Sjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25719ceba5Sjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26719ceba5Sjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27719ceba5Sjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28719ceba5Sjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29719ceba5Sjruoho  * POSSIBILITY OF SUCH DAMAGE.
30719ceba5Sjruoho  */
31719ceba5Sjruoho #include <sys/cdefs.h>
32*b670cbfcSriastradh __RCSID("$NetBSD: t_pow.c,v 1.6 2024/06/09 16:53:25 riastradh Exp $");
33719ceba5Sjruoho 
34719ceba5Sjruoho #include <atf-c.h>
35719ceba5Sjruoho #include <math.h>
36719ceba5Sjruoho 
37719ceba5Sjruoho /*
38719ceba5Sjruoho  * pow(3)
39719ceba5Sjruoho  */
40719ceba5Sjruoho ATF_TC(pow_nan_x);
ATF_TC_HEAD(pow_nan_x,tc)41719ceba5Sjruoho ATF_TC_HEAD(pow_nan_x, tc)
42719ceba5Sjruoho {
43719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(NaN, y) == NaN");
44719ceba5Sjruoho }
45719ceba5Sjruoho 
ATF_TC_BODY(pow_nan_x,tc)46719ceba5Sjruoho ATF_TC_BODY(pow_nan_x, tc)
47719ceba5Sjruoho {
48*b670cbfcSriastradh 	const volatile double x = 0.0 / 0.0;
49*b670cbfcSriastradh 	const double z = pow(x, 2.0);
50719ceba5Sjruoho 
51*b670cbfcSriastradh 	ATF_CHECK_MSG(isnan(z), "z=%a", z);
52719ceba5Sjruoho }
53719ceba5Sjruoho 
54719ceba5Sjruoho ATF_TC(pow_nan_y);
ATF_TC_HEAD(pow_nan_y,tc)55719ceba5Sjruoho ATF_TC_HEAD(pow_nan_y, tc)
56719ceba5Sjruoho {
57719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(x, NaN) == NaN");
58719ceba5Sjruoho }
59719ceba5Sjruoho 
ATF_TC_BODY(pow_nan_y,tc)60719ceba5Sjruoho ATF_TC_BODY(pow_nan_y, tc)
61719ceba5Sjruoho {
62*b670cbfcSriastradh 	const volatile double y = 0.0 / 0.0;
63*b670cbfcSriastradh 	const double z = pow(2.0, y);
64719ceba5Sjruoho 
65*b670cbfcSriastradh 	ATF_CHECK_MSG(isnan(z), "z=%a", z);
66719ceba5Sjruoho }
67719ceba5Sjruoho 
68719ceba5Sjruoho ATF_TC(pow_inf_neg_x);
ATF_TC_HEAD(pow_inf_neg_x,tc)69719ceba5Sjruoho ATF_TC_HEAD(pow_inf_neg_x, tc)
70719ceba5Sjruoho {
71719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(-Inf, y) == +-Inf || +-0.0");
72719ceba5Sjruoho }
73719ceba5Sjruoho 
ATF_TC_BODY(pow_inf_neg_x,tc)74719ceba5Sjruoho ATF_TC_BODY(pow_inf_neg_x, tc)
75719ceba5Sjruoho {
76*b670cbfcSriastradh 	const volatile double x = -1.0 / 0.0;
77719ceba5Sjruoho 	double z;
78719ceba5Sjruoho 
79719ceba5Sjruoho 	/*
80719ceba5Sjruoho 	 * If y is odd, y > 0, and x is -Inf, -Inf is returned.
81719ceba5Sjruoho 	 * If y is even, y > 0, and x is -Inf, +Inf is returned.
82719ceba5Sjruoho 	 */
83719ceba5Sjruoho 	z = pow(x, 3.0);
84*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 3.0)", z);
85*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "pow(x, 3.0)", z);
86719ceba5Sjruoho 
87719ceba5Sjruoho 	z = pow(x, 4.0);
88*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 4.0)", z);
89*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, 4.0)", z);
90719ceba5Sjruoho 
91719ceba5Sjruoho 	/*
92719ceba5Sjruoho 	 * If y is odd, y < 0, and x is -Inf, -0.0 is returned.
93719ceba5Sjruoho 	 * If y is even, y < 0, and x is -Inf, +0.0 is returned.
94719ceba5Sjruoho 	 */
95719ceba5Sjruoho 	z = pow(x, -3.0);
96*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -3.0)", z);
97*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "pow(x, -3.0)", z);
98719ceba5Sjruoho 
99719ceba5Sjruoho 	z = pow(x, -4.0);
100*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -4.0)", z);
101*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, -4.0)", z);
102719ceba5Sjruoho }
103719ceba5Sjruoho 
104719ceba5Sjruoho ATF_TC(pow_inf_neg_y);
ATF_TC_HEAD(pow_inf_neg_y,tc)105719ceba5Sjruoho ATF_TC_HEAD(pow_inf_neg_y, tc)
106719ceba5Sjruoho {
107719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(x, -Inf) == +Inf || +0.0");
108719ceba5Sjruoho }
109719ceba5Sjruoho 
ATF_TC_BODY(pow_inf_neg_y,tc)110719ceba5Sjruoho ATF_TC_BODY(pow_inf_neg_y, tc)
111719ceba5Sjruoho {
112*b670cbfcSriastradh 	const volatile double y = -1.0 / 0.0;
113719ceba5Sjruoho 	double z;
114719ceba5Sjruoho 
115719ceba5Sjruoho 	/*
116719ceba5Sjruoho 	 * If |x| < 1 and y is -Inf, +Inf is returned.
117719ceba5Sjruoho 	 * If |x| > 1 and y is -Inf, +0.0 is returned.
118719ceba5Sjruoho 	 */
119719ceba5Sjruoho 	z = pow(0.1, y);
120*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "pow(0.1, y)", z);
121*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
122719ceba5Sjruoho 
123719ceba5Sjruoho 	z = pow(1.1, y);
124*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
125*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
126719ceba5Sjruoho }
127719ceba5Sjruoho 
128719ceba5Sjruoho ATF_TC(pow_inf_pos_x);
ATF_TC_HEAD(pow_inf_pos_x,tc)129719ceba5Sjruoho ATF_TC_HEAD(pow_inf_pos_x, tc)
130719ceba5Sjruoho {
131719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(+Inf, y) == +Inf || +0.0");
132719ceba5Sjruoho }
133719ceba5Sjruoho 
ATF_TC_BODY(pow_inf_pos_x,tc)134719ceba5Sjruoho ATF_TC_BODY(pow_inf_pos_x, tc)
135719ceba5Sjruoho {
136*b670cbfcSriastradh 	const volatile double x = 1.0 / 0.0;
137719ceba5Sjruoho 	double z;
138719ceba5Sjruoho 
139719ceba5Sjruoho 	/*
140719ceba5Sjruoho 	 * For y < 0, if x is +Inf, +0.0 is returned.
141719ceba5Sjruoho 	 * For y > 0, if x is +Inf, +Inf is returned.
142719ceba5Sjruoho 	 */
143719ceba5Sjruoho 	z = pow(x, -2.0);
144*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -2.0)", z);
145*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, -2.0)", z);
146719ceba5Sjruoho 
147719ceba5Sjruoho 	z = pow(x, 2.0);
148*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 2.0)", z);
149*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, 2.0)", z);
150719ceba5Sjruoho }
151719ceba5Sjruoho 
152719ceba5Sjruoho ATF_TC(pow_inf_pos_y);
ATF_TC_HEAD(pow_inf_pos_y,tc)153719ceba5Sjruoho ATF_TC_HEAD(pow_inf_pos_y, tc)
154719ceba5Sjruoho {
155719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(x, +Inf) == +Inf || +0.0");
156719ceba5Sjruoho }
157719ceba5Sjruoho 
ATF_TC_BODY(pow_inf_pos_y,tc)158719ceba5Sjruoho ATF_TC_BODY(pow_inf_pos_y, tc)
159719ceba5Sjruoho {
160*b670cbfcSriastradh 	const volatile double y = 1.0 / 0.0;
161719ceba5Sjruoho 	double z;
162719ceba5Sjruoho 
163719ceba5Sjruoho 	/*
164719ceba5Sjruoho 	 * If |x| < 1 and y is +Inf, +0.0 is returned.
165719ceba5Sjruoho 	 * If |x| > 1 and y is +Inf, +Inf is returned.
166719ceba5Sjruoho 	 */
167719ceba5Sjruoho 	z = pow(0.1, y);
168*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
169*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
170719ceba5Sjruoho 
171719ceba5Sjruoho 	z = pow(1.1, y);
172*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "pow(1.1, y)", z);
173*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
174719ceba5Sjruoho }
175719ceba5Sjruoho 
176719ceba5Sjruoho ATF_TC(pow_one_neg_x);
ATF_TC_HEAD(pow_one_neg_x,tc)177719ceba5Sjruoho ATF_TC_HEAD(pow_one_neg_x, tc)
178719ceba5Sjruoho {
179719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(-1.0, +-Inf) == 1.0");
180719ceba5Sjruoho }
181719ceba5Sjruoho 
ATF_TC_BODY(pow_one_neg_x,tc)182719ceba5Sjruoho ATF_TC_BODY(pow_one_neg_x, tc)
183719ceba5Sjruoho {
184*b670cbfcSriastradh 	const volatile double infp = 1.0 / 0.0;
185*b670cbfcSriastradh 	const volatile double infn = -1.0 / 0.0;
186*b670cbfcSriastradh 	double z;
187719ceba5Sjruoho 
188719ceba5Sjruoho 	/*
189719ceba5Sjruoho 	 * If x is -1.0, and y is +-Inf, 1.0 shall be returned.
190719ceba5Sjruoho 	 */
191*b670cbfcSriastradh 	ATF_REQUIRE_MSG(isinf(infp), "infp=%a", infp);
192*b670cbfcSriastradh 	ATF_REQUIRE_MSG(isinf(infn), "infn=%a", infn);
193719ceba5Sjruoho 
194*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG((z = pow(-1.0, infp)), 1.0, "z=%a", z);
195*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG((z = pow(-1.0, infn)), 1.0, "z=%a", z);
196719ceba5Sjruoho }
197719ceba5Sjruoho 
198719ceba5Sjruoho ATF_TC(pow_one_pos_x);
ATF_TC_HEAD(pow_one_pos_x,tc)199719ceba5Sjruoho ATF_TC_HEAD(pow_one_pos_x, tc)
200719ceba5Sjruoho {
201719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(1.0, y) == 1.0");
202719ceba5Sjruoho }
203719ceba5Sjruoho 
ATF_TC_BODY(pow_one_pos_x,tc)204719ceba5Sjruoho ATF_TC_BODY(pow_one_pos_x, tc)
205719ceba5Sjruoho {
206*b670cbfcSriastradh 	const volatile double y[] =
207*b670cbfcSriastradh 	    { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 };
208*b670cbfcSriastradh 	const volatile double z = 0.0 / 0.0;
209719ceba5Sjruoho 	size_t i;
210719ceba5Sjruoho 
211719ceba5Sjruoho 	/*
212719ceba5Sjruoho 	 * For any value of y (including NaN),
213719ceba5Sjruoho 	 * if x is 1.0, 1.0 shall be returned.
214719ceba5Sjruoho 	 */
215*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(pow(1.0, z), 1.0, "z=%a pow(1.0, z)=%a",
216*b670cbfcSriastradh 	    z, pow(1.0, z));
217719ceba5Sjruoho 
218719ceba5Sjruoho 	for (i = 0; i < __arraycount(y); i++) {
219*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(pow(1.0, y[i]), 1.0,
220*b670cbfcSriastradh 		    "i=%zu y[i]=%a pow(1.0, y[i])=%a",
221*b670cbfcSriastradh 		    i, y[i], pow(1.0, y[i]));
222719ceba5Sjruoho 	}
223719ceba5Sjruoho }
224719ceba5Sjruoho 
225719ceba5Sjruoho ATF_TC(pow_zero_x);
ATF_TC_HEAD(pow_zero_x,tc)226719ceba5Sjruoho ATF_TC_HEAD(pow_zero_x, tc)
227719ceba5Sjruoho {
228719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(+-0.0, y) == +-0.0 || HUGE");
229719ceba5Sjruoho }
230719ceba5Sjruoho 
ATF_TC_BODY(pow_zero_x,tc)231719ceba5Sjruoho ATF_TC_BODY(pow_zero_x, tc)
232719ceba5Sjruoho {
233719ceba5Sjruoho 	double z;
234719ceba5Sjruoho 
235719ceba5Sjruoho 	/*
236719ceba5Sjruoho 	 * If x is +0.0 or -0.0, y > 0, and y
237719ceba5Sjruoho 	 * is an odd integer, x is returned.
238719ceba5Sjruoho 	 */
239719ceba5Sjruoho 	z = pow(+0.0, 3.0);
240*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
241*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
242719ceba5Sjruoho 
243719ceba5Sjruoho 	z = pow(-0.0, 3.0);
244*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
245*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "z=%a", z);
246719ceba5Sjruoho 
247719ceba5Sjruoho 	/*
248719ceba5Sjruoho 	 * If y > 0 and not an odd integer,
249719ceba5Sjruoho 	 * if x is +0.0 or -0.0, +0.0 is returned.
250719ceba5Sjruoho 	 */
251719ceba5Sjruoho 	z = pow(+0.0, 4.0);
252*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
253*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
254719ceba5Sjruoho 
255719ceba5Sjruoho 	z = pow(-0.0, 4.0);
256*b670cbfcSriastradh 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
257*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
258719ceba5Sjruoho 
259719ceba5Sjruoho 	/*
260719ceba5Sjruoho 	 * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL,
261719ceba5Sjruoho 	 * +-HUGE_VALF, or +-HUGE_VALL shall be returned.
262719ceba5Sjruoho 	 */
263719ceba5Sjruoho 	z = pow(+0.0, -4.0);
264*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
265719ceba5Sjruoho 
266719ceba5Sjruoho 	z = pow(-0.0, -4.0);
267*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
268b78b1689Sjruoho 
269b78b1689Sjruoho 	z = pow(+0.0, -5.0);
270*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
271b78b1689Sjruoho 
272b78b1689Sjruoho 	z = pow(-0.0, -5.0);
273*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, -HUGE_VAL, "z=%a", z);
274719ceba5Sjruoho }
275719ceba5Sjruoho 
276719ceba5Sjruoho ATF_TC(pow_zero_y);
ATF_TC_HEAD(pow_zero_y,tc)277719ceba5Sjruoho ATF_TC_HEAD(pow_zero_y, tc)
278719ceba5Sjruoho {
279719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test pow(x, +-0.0) == 1.0");
280719ceba5Sjruoho }
281719ceba5Sjruoho 
ATF_TC_BODY(pow_zero_y,tc)282719ceba5Sjruoho ATF_TC_BODY(pow_zero_y, tc)
283719ceba5Sjruoho {
284*b670cbfcSriastradh 	const volatile double x[] =  { 0.1, -3.0, 77.0, 99.99, 101.0000001 };
285*b670cbfcSriastradh 	const volatile double z = 0.0 / 0.0;
286719ceba5Sjruoho 	size_t i;
287719ceba5Sjruoho 
288719ceba5Sjruoho 	/*
289719ceba5Sjruoho 	 * For any value of x (including NaN),
290719ceba5Sjruoho 	 * if y is +0.0 or -0.0, 1.0 is returned.
291719ceba5Sjruoho 	 */
292*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(pow(z, +0.0), 1.0, "z=%a pow(z, +0.0)=%a",
293*b670cbfcSriastradh 	    z, pow(z, +0.0));
294*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(pow(z, -0.0), 1.0, "z=%a pow(z, -0.0)=%a",
295*b670cbfcSriastradh 	    z, pow(z, -0.0));
296719ceba5Sjruoho 
297719ceba5Sjruoho 	for (i = 0; i < __arraycount(x); i++) {
298*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(pow(x[i], +0.0), 1.0,
299*b670cbfcSriastradh 		    "i=%zu pow(%a, +0.0)=%a", i, x[i], pow(x[i], +0.0));
300*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(pow(x[i], -0.0), 1.0,
301*b670cbfcSriastradh 		    "i=%zu pow(%a, -0.0)=%a", i, x[i], pow(x[i], -0.0));
302719ceba5Sjruoho 	}
303719ceba5Sjruoho }
304719ceba5Sjruoho 
305719ceba5Sjruoho /*
306719ceba5Sjruoho  * powf(3)
307719ceba5Sjruoho  */
308719ceba5Sjruoho ATF_TC(powf_nan_x);
ATF_TC_HEAD(powf_nan_x,tc)309719ceba5Sjruoho ATF_TC_HEAD(powf_nan_x, tc)
310719ceba5Sjruoho {
311719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(NaN, y) == NaN");
312719ceba5Sjruoho }
313719ceba5Sjruoho 
ATF_TC_BODY(powf_nan_x,tc)314719ceba5Sjruoho ATF_TC_BODY(powf_nan_x, tc)
315719ceba5Sjruoho {
316*b670cbfcSriastradh 	const volatile float x = 0.0f / 0.0f;
317*b670cbfcSriastradh 	const float z = powf(x, 2.0f);
318719ceba5Sjruoho 
319*b670cbfcSriastradh 	ATF_CHECK_MSG(isnanf(z), "z=%a", z);
320719ceba5Sjruoho }
321719ceba5Sjruoho 
322719ceba5Sjruoho ATF_TC(powf_nan_y);
ATF_TC_HEAD(powf_nan_y,tc)323719ceba5Sjruoho ATF_TC_HEAD(powf_nan_y, tc)
324719ceba5Sjruoho {
325719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(x, NaN) == NaN");
326719ceba5Sjruoho }
327719ceba5Sjruoho 
ATF_TC_BODY(powf_nan_y,tc)328719ceba5Sjruoho ATF_TC_BODY(powf_nan_y, tc)
329719ceba5Sjruoho {
330*b670cbfcSriastradh 	const volatile float y = 0.0f / 0.0f;
331*b670cbfcSriastradh 	const float z = powf(2.0f, y);
332719ceba5Sjruoho 
333*b670cbfcSriastradh 	ATF_CHECK_MSG(isnanf(z), "z=%a", z);
334719ceba5Sjruoho }
335719ceba5Sjruoho 
336719ceba5Sjruoho ATF_TC(powf_inf_neg_x);
ATF_TC_HEAD(powf_inf_neg_x,tc)337719ceba5Sjruoho ATF_TC_HEAD(powf_inf_neg_x, tc)
338719ceba5Sjruoho {
339719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(-Inf, y) == +-Inf || +-0.0");
340719ceba5Sjruoho }
341719ceba5Sjruoho 
ATF_TC_BODY(powf_inf_neg_x,tc)342719ceba5Sjruoho ATF_TC_BODY(powf_inf_neg_x, tc)
343719ceba5Sjruoho {
344*b670cbfcSriastradh 	const volatile float x = -1.0f / 0.0f;
345719ceba5Sjruoho 	float z;
346719ceba5Sjruoho 
347719ceba5Sjruoho 	/*
348719ceba5Sjruoho 	 * If y is odd, y > 0, and x is -Inf, -Inf is returned.
349719ceba5Sjruoho 	 * If y is even, y > 0, and x is -Inf, +Inf is returned.
350719ceba5Sjruoho 	 */
351719ceba5Sjruoho 	z = powf(x, 3.0);
352*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 3.0)", z);
353*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "powf(x, 3.0)", z);
354719ceba5Sjruoho 
355719ceba5Sjruoho 	z = powf(x, 4.0);
356*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 4.0)", z);
357*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, 4.0)", z);
358719ceba5Sjruoho 
359719ceba5Sjruoho 	/*
360719ceba5Sjruoho 	 * If y is odd, y < 0, and x is -Inf, -0.0 is returned.
361719ceba5Sjruoho 	 * If y is even, y < 0, and x is -Inf, +0.0 is returned.
362719ceba5Sjruoho 	 */
363719ceba5Sjruoho 	z = powf(x, -3.0);
364*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -3.0)", z);
365*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "powf(x, -3.0)", z);
366719ceba5Sjruoho 
367719ceba5Sjruoho 	z = powf(x, -4.0);
368*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -4.0)", z);
369*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, -4.0)", z);
370719ceba5Sjruoho }
371719ceba5Sjruoho 
372719ceba5Sjruoho ATF_TC(powf_inf_neg_y);
ATF_TC_HEAD(powf_inf_neg_y,tc)373719ceba5Sjruoho ATF_TC_HEAD(powf_inf_neg_y, tc)
374719ceba5Sjruoho {
375719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(x, -Inf) == +Inf || +0.0");
376719ceba5Sjruoho }
377719ceba5Sjruoho 
ATF_TC_BODY(powf_inf_neg_y,tc)378719ceba5Sjruoho ATF_TC_BODY(powf_inf_neg_y, tc)
379719ceba5Sjruoho {
380*b670cbfcSriastradh 	const volatile float y = -1.0f / 0.0f;
381719ceba5Sjruoho 	float z;
382719ceba5Sjruoho 
383719ceba5Sjruoho 	/*
384719ceba5Sjruoho 	 * If |x| < 1 and y is -Inf, +Inf is returned.
385719ceba5Sjruoho 	 * If |x| > 1 and y is -Inf, +0.0 is returned.
386719ceba5Sjruoho 	 */
387719ceba5Sjruoho 	z = powf(0.1, y);
388*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "powf(0.1, y)", z);
389*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
390719ceba5Sjruoho 
391719ceba5Sjruoho 	z = powf(1.1, y);
392*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
393*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
394719ceba5Sjruoho }
395719ceba5Sjruoho 
396719ceba5Sjruoho ATF_TC(powf_inf_pos_x);
ATF_TC_HEAD(powf_inf_pos_x,tc)397719ceba5Sjruoho ATF_TC_HEAD(powf_inf_pos_x, tc)
398719ceba5Sjruoho {
399719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(+Inf, y) == +Inf || +0.0");
400719ceba5Sjruoho }
401719ceba5Sjruoho 
ATF_TC_BODY(powf_inf_pos_x,tc)402719ceba5Sjruoho ATF_TC_BODY(powf_inf_pos_x, tc)
403719ceba5Sjruoho {
404*b670cbfcSriastradh 	const volatile float x = 1.0f / 0.0f;
405719ceba5Sjruoho 	float z;
406719ceba5Sjruoho 
407719ceba5Sjruoho 	/*
408719ceba5Sjruoho 	 * For y < 0, if x is +Inf, +0.0 is returned.
409719ceba5Sjruoho 	 * For y > 0, if x is +Inf, +Inf is returned.
410719ceba5Sjruoho 	 */
411719ceba5Sjruoho 	z = powf(x, -2.0);
412*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -2.0)", z);
413*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, -2.0)", z);
414719ceba5Sjruoho 
415719ceba5Sjruoho 	z = powf(x, 2.0);
416*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 2.0)", z);
417*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, 2.0)", z);
418719ceba5Sjruoho }
419719ceba5Sjruoho 
420719ceba5Sjruoho ATF_TC(powf_inf_pos_y);
ATF_TC_HEAD(powf_inf_pos_y,tc)421719ceba5Sjruoho ATF_TC_HEAD(powf_inf_pos_y, tc)
422719ceba5Sjruoho {
423719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(x, +Inf) == +Inf || +0.0");
424719ceba5Sjruoho }
425719ceba5Sjruoho 
ATF_TC_BODY(powf_inf_pos_y,tc)426719ceba5Sjruoho ATF_TC_BODY(powf_inf_pos_y, tc)
427719ceba5Sjruoho {
428719ceba5Sjruoho 	const float y = 1.0L / 0.0L;
429719ceba5Sjruoho 	float z;
430719ceba5Sjruoho 
431719ceba5Sjruoho 	/*
432719ceba5Sjruoho 	 * If |x| < 1 and y is +Inf, +0.0 is returned.
433719ceba5Sjruoho 	 * If |x| > 1 and y is +Inf, +Inf is returned.
434719ceba5Sjruoho 	 */
435719ceba5Sjruoho 	z = powf(0.1, y);
436*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
437*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
438719ceba5Sjruoho 
439719ceba5Sjruoho 	z = powf(1.1, y);
440*b670cbfcSriastradh 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "powf(1.1, y)", z);
441*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
442719ceba5Sjruoho }
443719ceba5Sjruoho 
444719ceba5Sjruoho ATF_TC(powf_one_neg_x);
ATF_TC_HEAD(powf_one_neg_x,tc)445719ceba5Sjruoho ATF_TC_HEAD(powf_one_neg_x, tc)
446719ceba5Sjruoho {
447719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(-1.0, +-Inf) == 1.0");
448719ceba5Sjruoho }
449719ceba5Sjruoho 
ATF_TC_BODY(powf_one_neg_x,tc)450719ceba5Sjruoho ATF_TC_BODY(powf_one_neg_x, tc)
451719ceba5Sjruoho {
452*b670cbfcSriastradh 	const volatile float infp = 1.0f / 0.0f;
453*b670cbfcSriastradh 	const volatile float infn = -1.0f / 0.0f;
454*b670cbfcSriastradh 	double z;
455719ceba5Sjruoho 
456719ceba5Sjruoho 	/*
457719ceba5Sjruoho 	 * If x is -1.0, and y is +-Inf, 1.0 shall be returned.
458719ceba5Sjruoho 	 */
459*b670cbfcSriastradh 	ATF_REQUIRE_MSG(isinf(infp), "infp=%a", infp);
460*b670cbfcSriastradh 	ATF_REQUIRE_MSG(isinf(infn), "infn=%a", infn);
461719ceba5Sjruoho 
462*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG((z = powf(-1.0, infp)), 1.0, "z=%a", z);
463*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG((z = powf(-1.0, infn)), 1.0, "z=%a", z);
464719ceba5Sjruoho }
465719ceba5Sjruoho 
466719ceba5Sjruoho ATF_TC(powf_one_pos_x);
ATF_TC_HEAD(powf_one_pos_x,tc)467719ceba5Sjruoho ATF_TC_HEAD(powf_one_pos_x, tc)
468719ceba5Sjruoho {
469719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(1.0, y) == 1.0");
470719ceba5Sjruoho }
471719ceba5Sjruoho 
ATF_TC_BODY(powf_one_pos_x,tc)472719ceba5Sjruoho ATF_TC_BODY(powf_one_pos_x, tc)
473719ceba5Sjruoho {
474*b670cbfcSriastradh 	const volatile float y[] =
475*b670cbfcSriastradh 	    { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 };
476*b670cbfcSriastradh 	const volatile float z = 0.0f / 0.0f;
477719ceba5Sjruoho 	size_t i;
478719ceba5Sjruoho 
479719ceba5Sjruoho 	/*
480719ceba5Sjruoho 	 * For any value of y (including NaN),
481719ceba5Sjruoho 	 * if x is 1.0, 1.0 shall be returned.
482719ceba5Sjruoho 	 */
483*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(powf(1.0, z), 1.0, "z=%a powf(1.0, z)=%a",
484*b670cbfcSriastradh 	    z, powf(1.0, z));
485719ceba5Sjruoho 
486719ceba5Sjruoho 	for (i = 0; i < __arraycount(y); i++) {
487*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(powf(1.0, y[i]), 1.0,
488*b670cbfcSriastradh 		    "i=%zu y[i]=%a powf(1.0, y[i])=%a",
489*b670cbfcSriastradh 		    i, y[i], powf(1.0, y[i]));
490719ceba5Sjruoho 	}
491719ceba5Sjruoho }
492719ceba5Sjruoho 
493719ceba5Sjruoho ATF_TC(powf_zero_x);
ATF_TC_HEAD(powf_zero_x,tc)494719ceba5Sjruoho ATF_TC_HEAD(powf_zero_x, tc)
495719ceba5Sjruoho {
496719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(+-0.0, y) == +-0.0 || HUGE");
497719ceba5Sjruoho }
498719ceba5Sjruoho 
ATF_TC_BODY(powf_zero_x,tc)499719ceba5Sjruoho ATF_TC_BODY(powf_zero_x, tc)
500719ceba5Sjruoho {
501719ceba5Sjruoho 	float z;
502719ceba5Sjruoho 
503719ceba5Sjruoho 	/*
504719ceba5Sjruoho 	 * If x is +0.0 or -0.0, y > 0, and y
505719ceba5Sjruoho 	 * is an odd integer, x is returned.
506719ceba5Sjruoho 	 */
507719ceba5Sjruoho 	z = powf(+0.0, 3.0);
508*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
509*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
510719ceba5Sjruoho 
511719ceba5Sjruoho 	z = powf(-0.0, 3.0);
512*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
513*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) != 0, "z=%a", z);
514719ceba5Sjruoho 
515719ceba5Sjruoho 	/*
516719ceba5Sjruoho 	 * If y > 0 and not an odd integer,
517719ceba5Sjruoho 	 * if x is +0.0 or -0.0, +0.0 is returned.
518719ceba5Sjruoho 	 */
519719ceba5Sjruoho 	z = powf(+0.0, 4.0);
520*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
521*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
522719ceba5Sjruoho 
523719ceba5Sjruoho 	z = powf(-0.0, 4.0);
524*b670cbfcSriastradh 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
525*b670cbfcSriastradh 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
526719ceba5Sjruoho 
527719ceba5Sjruoho 	/*
528719ceba5Sjruoho 	 * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL,
529719ceba5Sjruoho 	 * +-HUGE_VALF, or +-HUGE_VALL shall be returned.
530719ceba5Sjruoho 	 */
531719ceba5Sjruoho 	z = powf(+0.0, -4.0);
532*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
533719ceba5Sjruoho 
534719ceba5Sjruoho 	z = powf(-0.0, -4.0);
535*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
536b78b1689Sjruoho 
537b78b1689Sjruoho 	z = powf(+0.0, -5.0);
538*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
539b78b1689Sjruoho 
540b78b1689Sjruoho 	z = powf(-0.0, -5.0);
541*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(z, -HUGE_VALF, "z=%a", z);
542719ceba5Sjruoho }
543719ceba5Sjruoho 
544719ceba5Sjruoho ATF_TC(powf_zero_y);
ATF_TC_HEAD(powf_zero_y,tc)545719ceba5Sjruoho ATF_TC_HEAD(powf_zero_y, tc)
546719ceba5Sjruoho {
547719ceba5Sjruoho 	atf_tc_set_md_var(tc, "descr", "Test powf(x, +-0.0) == 1.0");
548719ceba5Sjruoho }
549719ceba5Sjruoho 
ATF_TC_BODY(powf_zero_y,tc)550719ceba5Sjruoho ATF_TC_BODY(powf_zero_y, tc)
551719ceba5Sjruoho {
552*b670cbfcSriastradh 	const volatile float x[] =  { 0.1, -3.0, 77.0, 99.99, 101.0000001 };
553*b670cbfcSriastradh 	const volatile float z = 0.0f / 0.0f;
554719ceba5Sjruoho 	size_t i;
555719ceba5Sjruoho 
556719ceba5Sjruoho 	/*
557719ceba5Sjruoho 	 * For any value of x (including NaN),
558719ceba5Sjruoho 	 * if y is +0.0 or -0.0, 1.0 is returned.
559719ceba5Sjruoho 	 */
560*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(powf(z, +0.0), 1.0, "z=%a powf(z, +0.0)=%a",
561*b670cbfcSriastradh 	    z, powf(z, +0.0));
562*b670cbfcSriastradh 	ATF_CHECK_EQ_MSG(powf(z, -0.0), 1.0, "z=%a powf(z, -0.0)=%a",
563*b670cbfcSriastradh 	    z, powf(z, -0.0));
564719ceba5Sjruoho 
565719ceba5Sjruoho 	for (i = 0; i < __arraycount(x); i++) {
566*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(powf(x[i], +0.0), 1.0,
567*b670cbfcSriastradh 		    "i=%zu powf(%a, +0.0)=%a", i, x[i], powf(x[i], +0.0));
568*b670cbfcSriastradh 		ATF_CHECK_EQ_MSG(powf(x[i], -0.0), 1.0,
569*b670cbfcSriastradh 		    "i=%zu powf(%a, -0.0)=%a", i, x[i], powf(x[i], -0.0));
570719ceba5Sjruoho 	}
571719ceba5Sjruoho }
572719ceba5Sjruoho 
ATF_TP_ADD_TCS(tp)573719ceba5Sjruoho ATF_TP_ADD_TCS(tp)
574719ceba5Sjruoho {
575719ceba5Sjruoho 
576719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_nan_x);
577719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_nan_y);
578719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_inf_neg_x);
579719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_inf_neg_y);
580719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_inf_pos_x);
581719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_inf_pos_y);
582719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_one_neg_x);
583719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_one_pos_x);
584719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_zero_x);
585719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, pow_zero_y);
586719ceba5Sjruoho 
587719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_nan_x);
588719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_nan_y);
589719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_inf_neg_x);
590719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_inf_neg_y);
591719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_inf_pos_x);
592719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_inf_pos_y);
593719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_one_neg_x);
594719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_one_pos_x);
595719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_zero_x);
596719ceba5Sjruoho 	ATF_TP_ADD_TC(tp, powf_zero_y);
597719ceba5Sjruoho 
598719ceba5Sjruoho 	return atf_no_error();
599719ceba5Sjruoho }
600