xref: /netbsd-src/tests/lib/libm/t_pow.c (revision b670cbfc5870850fcb8397dfbc399ff2e5c7e2dd)
1 /* $NetBSD: t_pow.c,v 1.6 2024/06/09 16:53:25 riastradh Exp $ */
2 
3 /*-
4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jukka Ruohonen.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_pow.c,v 1.6 2024/06/09 16:53:25 riastradh Exp $");
33 
34 #include <atf-c.h>
35 #include <math.h>
36 
37 /*
38  * pow(3)
39  */
40 ATF_TC(pow_nan_x);
ATF_TC_HEAD(pow_nan_x,tc)41 ATF_TC_HEAD(pow_nan_x, tc)
42 {
43 	atf_tc_set_md_var(tc, "descr", "Test pow(NaN, y) == NaN");
44 }
45 
ATF_TC_BODY(pow_nan_x,tc)46 ATF_TC_BODY(pow_nan_x, tc)
47 {
48 	const volatile double x = 0.0 / 0.0;
49 	const double z = pow(x, 2.0);
50 
51 	ATF_CHECK_MSG(isnan(z), "z=%a", z);
52 }
53 
54 ATF_TC(pow_nan_y);
ATF_TC_HEAD(pow_nan_y,tc)55 ATF_TC_HEAD(pow_nan_y, tc)
56 {
57 	atf_tc_set_md_var(tc, "descr", "Test pow(x, NaN) == NaN");
58 }
59 
ATF_TC_BODY(pow_nan_y,tc)60 ATF_TC_BODY(pow_nan_y, tc)
61 {
62 	const volatile double y = 0.0 / 0.0;
63 	const double z = pow(2.0, y);
64 
65 	ATF_CHECK_MSG(isnan(z), "z=%a", z);
66 }
67 
68 ATF_TC(pow_inf_neg_x);
ATF_TC_HEAD(pow_inf_neg_x,tc)69 ATF_TC_HEAD(pow_inf_neg_x, tc)
70 {
71 	atf_tc_set_md_var(tc, "descr", "Test pow(-Inf, y) == +-Inf || +-0.0");
72 }
73 
ATF_TC_BODY(pow_inf_neg_x,tc)74 ATF_TC_BODY(pow_inf_neg_x, tc)
75 {
76 	const volatile double x = -1.0 / 0.0;
77 	double z;
78 
79 	/*
80 	 * If y is odd, y > 0, and x is -Inf, -Inf is returned.
81 	 * If y is even, y > 0, and x is -Inf, +Inf is returned.
82 	 */
83 	z = pow(x, 3.0);
84 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 3.0)", z);
85 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "pow(x, 3.0)", z);
86 
87 	z = pow(x, 4.0);
88 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 4.0)", z);
89 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, 4.0)", z);
90 
91 	/*
92 	 * If y is odd, y < 0, and x is -Inf, -0.0 is returned.
93 	 * If y is even, y < 0, and x is -Inf, +0.0 is returned.
94 	 */
95 	z = pow(x, -3.0);
96 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -3.0)", z);
97 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "pow(x, -3.0)", z);
98 
99 	z = pow(x, -4.0);
100 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -4.0)", z);
101 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, -4.0)", z);
102 }
103 
104 ATF_TC(pow_inf_neg_y);
ATF_TC_HEAD(pow_inf_neg_y,tc)105 ATF_TC_HEAD(pow_inf_neg_y, tc)
106 {
107 	atf_tc_set_md_var(tc, "descr", "Test pow(x, -Inf) == +Inf || +0.0");
108 }
109 
ATF_TC_BODY(pow_inf_neg_y,tc)110 ATF_TC_BODY(pow_inf_neg_y, tc)
111 {
112 	const volatile double y = -1.0 / 0.0;
113 	double z;
114 
115 	/*
116 	 * If |x| < 1 and y is -Inf, +Inf is returned.
117 	 * If |x| > 1 and y is -Inf, +0.0 is returned.
118 	 */
119 	z = pow(0.1, y);
120 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "pow(0.1, y)", z);
121 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
122 
123 	z = pow(1.1, y);
124 	ATF_CHECK_MSG(fabs(z) == 0.0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
125 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
126 }
127 
128 ATF_TC(pow_inf_pos_x);
ATF_TC_HEAD(pow_inf_pos_x,tc)129 ATF_TC_HEAD(pow_inf_pos_x, tc)
130 {
131 	atf_tc_set_md_var(tc, "descr", "Test pow(+Inf, y) == +Inf || +0.0");
132 }
133 
ATF_TC_BODY(pow_inf_pos_x,tc)134 ATF_TC_BODY(pow_inf_pos_x, tc)
135 {
136 	const volatile double x = 1.0 / 0.0;
137 	double z;
138 
139 	/*
140 	 * For y < 0, if x is +Inf, +0.0 is returned.
141 	 * For y > 0, if x is +Inf, +Inf is returned.
142 	 */
143 	z = pow(x, -2.0);
144 	ATF_CHECK_MSG(fabs(z) == 0.0, "x=%a z=%s=%a", x, "pow(x, -2.0)", z);
145 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, -2.0)", z);
146 
147 	z = pow(x, 2.0);
148 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "pow(x, 2.0)", z);
149 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "pow(x, 2.0)", z);
150 }
151 
152 ATF_TC(pow_inf_pos_y);
ATF_TC_HEAD(pow_inf_pos_y,tc)153 ATF_TC_HEAD(pow_inf_pos_y, tc)
154 {
155 	atf_tc_set_md_var(tc, "descr", "Test pow(x, +Inf) == +Inf || +0.0");
156 }
157 
ATF_TC_BODY(pow_inf_pos_y,tc)158 ATF_TC_BODY(pow_inf_pos_y, tc)
159 {
160 	const volatile double y = 1.0 / 0.0;
161 	double z;
162 
163 	/*
164 	 * If |x| < 1 and y is +Inf, +0.0 is returned.
165 	 * If |x| > 1 and y is +Inf, +Inf is returned.
166 	 */
167 	z = pow(0.1, y);
168 	ATF_CHECK_MSG(fabs(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
169 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(0.1, y)", z);
170 
171 	z = pow(1.1, y);
172 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "pow(1.1, y)", z);
173 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "pow(1.1, y)", z);
174 }
175 
176 ATF_TC(pow_one_neg_x);
ATF_TC_HEAD(pow_one_neg_x,tc)177 ATF_TC_HEAD(pow_one_neg_x, tc)
178 {
179 	atf_tc_set_md_var(tc, "descr", "Test pow(-1.0, +-Inf) == 1.0");
180 }
181 
ATF_TC_BODY(pow_one_neg_x,tc)182 ATF_TC_BODY(pow_one_neg_x, tc)
183 {
184 	const volatile double infp = 1.0 / 0.0;
185 	const volatile double infn = -1.0 / 0.0;
186 	double z;
187 
188 	/*
189 	 * If x is -1.0, and y is +-Inf, 1.0 shall be returned.
190 	 */
191 	ATF_REQUIRE_MSG(isinf(infp), "infp=%a", infp);
192 	ATF_REQUIRE_MSG(isinf(infn), "infn=%a", infn);
193 
194 	ATF_CHECK_EQ_MSG((z = pow(-1.0, infp)), 1.0, "z=%a", z);
195 	ATF_CHECK_EQ_MSG((z = pow(-1.0, infn)), 1.0, "z=%a", z);
196 }
197 
198 ATF_TC(pow_one_pos_x);
ATF_TC_HEAD(pow_one_pos_x,tc)199 ATF_TC_HEAD(pow_one_pos_x, tc)
200 {
201 	atf_tc_set_md_var(tc, "descr", "Test pow(1.0, y) == 1.0");
202 }
203 
ATF_TC_BODY(pow_one_pos_x,tc)204 ATF_TC_BODY(pow_one_pos_x, tc)
205 {
206 	const volatile double y[] =
207 	    { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 };
208 	const volatile double z = 0.0 / 0.0;
209 	size_t i;
210 
211 	/*
212 	 * For any value of y (including NaN),
213 	 * if x is 1.0, 1.0 shall be returned.
214 	 */
215 	ATF_CHECK_EQ_MSG(pow(1.0, z), 1.0, "z=%a pow(1.0, z)=%a",
216 	    z, pow(1.0, z));
217 
218 	for (i = 0; i < __arraycount(y); i++) {
219 		ATF_CHECK_EQ_MSG(pow(1.0, y[i]), 1.0,
220 		    "i=%zu y[i]=%a pow(1.0, y[i])=%a",
221 		    i, y[i], pow(1.0, y[i]));
222 	}
223 }
224 
225 ATF_TC(pow_zero_x);
ATF_TC_HEAD(pow_zero_x,tc)226 ATF_TC_HEAD(pow_zero_x, tc)
227 {
228 	atf_tc_set_md_var(tc, "descr", "Test pow(+-0.0, y) == +-0.0 || HUGE");
229 }
230 
ATF_TC_BODY(pow_zero_x,tc)231 ATF_TC_BODY(pow_zero_x, tc)
232 {
233 	double z;
234 
235 	/*
236 	 * If x is +0.0 or -0.0, y > 0, and y
237 	 * is an odd integer, x is returned.
238 	 */
239 	z = pow(+0.0, 3.0);
240 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
241 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
242 
243 	z = pow(-0.0, 3.0);
244 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
245 	ATF_CHECK_MSG(signbit(z) != 0, "z=%a", z);
246 
247 	/*
248 	 * If y > 0 and not an odd integer,
249 	 * if x is +0.0 or -0.0, +0.0 is returned.
250 	 */
251 	z = pow(+0.0, 4.0);
252 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
253 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
254 
255 	z = pow(-0.0, 4.0);
256 	ATF_CHECK_MSG(fabs(z) == 0.0, "z=%a", z);
257 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
258 
259 	/*
260 	 * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL,
261 	 * +-HUGE_VALF, or +-HUGE_VALL shall be returned.
262 	 */
263 	z = pow(+0.0, -4.0);
264 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
265 
266 	z = pow(-0.0, -4.0);
267 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
268 
269 	z = pow(+0.0, -5.0);
270 	ATF_CHECK_EQ_MSG(z, HUGE_VAL, "z=%a", z);
271 
272 	z = pow(-0.0, -5.0);
273 	ATF_CHECK_EQ_MSG(z, -HUGE_VAL, "z=%a", z);
274 }
275 
276 ATF_TC(pow_zero_y);
ATF_TC_HEAD(pow_zero_y,tc)277 ATF_TC_HEAD(pow_zero_y, tc)
278 {
279 	atf_tc_set_md_var(tc, "descr", "Test pow(x, +-0.0) == 1.0");
280 }
281 
ATF_TC_BODY(pow_zero_y,tc)282 ATF_TC_BODY(pow_zero_y, tc)
283 {
284 	const volatile double x[] =  { 0.1, -3.0, 77.0, 99.99, 101.0000001 };
285 	const volatile double z = 0.0 / 0.0;
286 	size_t i;
287 
288 	/*
289 	 * For any value of x (including NaN),
290 	 * if y is +0.0 or -0.0, 1.0 is returned.
291 	 */
292 	ATF_CHECK_EQ_MSG(pow(z, +0.0), 1.0, "z=%a pow(z, +0.0)=%a",
293 	    z, pow(z, +0.0));
294 	ATF_CHECK_EQ_MSG(pow(z, -0.0), 1.0, "z=%a pow(z, -0.0)=%a",
295 	    z, pow(z, -0.0));
296 
297 	for (i = 0; i < __arraycount(x); i++) {
298 		ATF_CHECK_EQ_MSG(pow(x[i], +0.0), 1.0,
299 		    "i=%zu pow(%a, +0.0)=%a", i, x[i], pow(x[i], +0.0));
300 		ATF_CHECK_EQ_MSG(pow(x[i], -0.0), 1.0,
301 		    "i=%zu pow(%a, -0.0)=%a", i, x[i], pow(x[i], -0.0));
302 	}
303 }
304 
305 /*
306  * powf(3)
307  */
308 ATF_TC(powf_nan_x);
ATF_TC_HEAD(powf_nan_x,tc)309 ATF_TC_HEAD(powf_nan_x, tc)
310 {
311 	atf_tc_set_md_var(tc, "descr", "Test powf(NaN, y) == NaN");
312 }
313 
ATF_TC_BODY(powf_nan_x,tc)314 ATF_TC_BODY(powf_nan_x, tc)
315 {
316 	const volatile float x = 0.0f / 0.0f;
317 	const float z = powf(x, 2.0f);
318 
319 	ATF_CHECK_MSG(isnanf(z), "z=%a", z);
320 }
321 
322 ATF_TC(powf_nan_y);
ATF_TC_HEAD(powf_nan_y,tc)323 ATF_TC_HEAD(powf_nan_y, tc)
324 {
325 	atf_tc_set_md_var(tc, "descr", "Test powf(x, NaN) == NaN");
326 }
327 
ATF_TC_BODY(powf_nan_y,tc)328 ATF_TC_BODY(powf_nan_y, tc)
329 {
330 	const volatile float y = 0.0f / 0.0f;
331 	const float z = powf(2.0f, y);
332 
333 	ATF_CHECK_MSG(isnanf(z), "z=%a", z);
334 }
335 
336 ATF_TC(powf_inf_neg_x);
ATF_TC_HEAD(powf_inf_neg_x,tc)337 ATF_TC_HEAD(powf_inf_neg_x, tc)
338 {
339 	atf_tc_set_md_var(tc, "descr", "Test powf(-Inf, y) == +-Inf || +-0.0");
340 }
341 
ATF_TC_BODY(powf_inf_neg_x,tc)342 ATF_TC_BODY(powf_inf_neg_x, tc)
343 {
344 	const volatile float x = -1.0f / 0.0f;
345 	float z;
346 
347 	/*
348 	 * If y is odd, y > 0, and x is -Inf, -Inf is returned.
349 	 * If y is even, y > 0, and x is -Inf, +Inf is returned.
350 	 */
351 	z = powf(x, 3.0);
352 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 3.0)", z);
353 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "powf(x, 3.0)", z);
354 
355 	z = powf(x, 4.0);
356 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 4.0)", z);
357 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, 4.0)", z);
358 
359 	/*
360 	 * If y is odd, y < 0, and x is -Inf, -0.0 is returned.
361 	 * If y is even, y < 0, and x is -Inf, +0.0 is returned.
362 	 */
363 	z = powf(x, -3.0);
364 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -3.0)", z);
365 	ATF_CHECK_MSG(signbit(z) != 0, "x=%a z=%s=%a", x, "powf(x, -3.0)", z);
366 
367 	z = powf(x, -4.0);
368 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -4.0)", z);
369 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, -4.0)", z);
370 }
371 
372 ATF_TC(powf_inf_neg_y);
ATF_TC_HEAD(powf_inf_neg_y,tc)373 ATF_TC_HEAD(powf_inf_neg_y, tc)
374 {
375 	atf_tc_set_md_var(tc, "descr", "Test powf(x, -Inf) == +Inf || +0.0");
376 }
377 
ATF_TC_BODY(powf_inf_neg_y,tc)378 ATF_TC_BODY(powf_inf_neg_y, tc)
379 {
380 	const volatile float y = -1.0f / 0.0f;
381 	float z;
382 
383 	/*
384 	 * If |x| < 1 and y is -Inf, +Inf is returned.
385 	 * If |x| > 1 and y is -Inf, +0.0 is returned.
386 	 */
387 	z = powf(0.1, y);
388 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "powf(0.1, y)", z);
389 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
390 
391 	z = powf(1.1, y);
392 	ATF_CHECK_MSG(fabsf(z) == 0.0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
393 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
394 }
395 
396 ATF_TC(powf_inf_pos_x);
ATF_TC_HEAD(powf_inf_pos_x,tc)397 ATF_TC_HEAD(powf_inf_pos_x, tc)
398 {
399 	atf_tc_set_md_var(tc, "descr", "Test powf(+Inf, y) == +Inf || +0.0");
400 }
401 
ATF_TC_BODY(powf_inf_pos_x,tc)402 ATF_TC_BODY(powf_inf_pos_x, tc)
403 {
404 	const volatile float x = 1.0f / 0.0f;
405 	float z;
406 
407 	/*
408 	 * For y < 0, if x is +Inf, +0.0 is returned.
409 	 * For y > 0, if x is +Inf, +Inf is returned.
410 	 */
411 	z = powf(x, -2.0);
412 	ATF_CHECK_MSG(fabsf(z) == 0.0, "x=%a z=%s=%a", x, "powf(x, -2.0)", z);
413 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, -2.0)", z);
414 
415 	z = powf(x, 2.0);
416 	ATF_CHECK_MSG(isinf(z), "x=%a z=%s=%a", x, "powf(x, 2.0)", z);
417 	ATF_CHECK_MSG(signbit(z) == 0, "x=%a z=%s=%a", x, "powf(x, 2.0)", z);
418 }
419 
420 ATF_TC(powf_inf_pos_y);
ATF_TC_HEAD(powf_inf_pos_y,tc)421 ATF_TC_HEAD(powf_inf_pos_y, tc)
422 {
423 	atf_tc_set_md_var(tc, "descr", "Test powf(x, +Inf) == +Inf || +0.0");
424 }
425 
ATF_TC_BODY(powf_inf_pos_y,tc)426 ATF_TC_BODY(powf_inf_pos_y, tc)
427 {
428 	const float y = 1.0L / 0.0L;
429 	float z;
430 
431 	/*
432 	 * If |x| < 1 and y is +Inf, +0.0 is returned.
433 	 * If |x| > 1 and y is +Inf, +Inf is returned.
434 	 */
435 	z = powf(0.1, y);
436 	ATF_CHECK_MSG(fabsf(z) == 0.0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
437 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(0.1, y)", z);
438 
439 	z = powf(1.1, y);
440 	ATF_CHECK_MSG(isinf(z), "y=%a z=%s=%a", y, "powf(1.1, y)", z);
441 	ATF_CHECK_MSG(signbit(z) == 0, "y=%a z=%s=%a", y, "powf(1.1, y)", z);
442 }
443 
444 ATF_TC(powf_one_neg_x);
ATF_TC_HEAD(powf_one_neg_x,tc)445 ATF_TC_HEAD(powf_one_neg_x, tc)
446 {
447 	atf_tc_set_md_var(tc, "descr", "Test powf(-1.0, +-Inf) == 1.0");
448 }
449 
ATF_TC_BODY(powf_one_neg_x,tc)450 ATF_TC_BODY(powf_one_neg_x, tc)
451 {
452 	const volatile float infp = 1.0f / 0.0f;
453 	const volatile float infn = -1.0f / 0.0f;
454 	double z;
455 
456 	/*
457 	 * If x is -1.0, and y is +-Inf, 1.0 shall be returned.
458 	 */
459 	ATF_REQUIRE_MSG(isinf(infp), "infp=%a", infp);
460 	ATF_REQUIRE_MSG(isinf(infn), "infn=%a", infn);
461 
462 	ATF_CHECK_EQ_MSG((z = powf(-1.0, infp)), 1.0, "z=%a", z);
463 	ATF_CHECK_EQ_MSG((z = powf(-1.0, infn)), 1.0, "z=%a", z);
464 }
465 
466 ATF_TC(powf_one_pos_x);
ATF_TC_HEAD(powf_one_pos_x,tc)467 ATF_TC_HEAD(powf_one_pos_x, tc)
468 {
469 	atf_tc_set_md_var(tc, "descr", "Test powf(1.0, y) == 1.0");
470 }
471 
ATF_TC_BODY(powf_one_pos_x,tc)472 ATF_TC_BODY(powf_one_pos_x, tc)
473 {
474 	const volatile float y[] =
475 	    { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 };
476 	const volatile float z = 0.0f / 0.0f;
477 	size_t i;
478 
479 	/*
480 	 * For any value of y (including NaN),
481 	 * if x is 1.0, 1.0 shall be returned.
482 	 */
483 	ATF_CHECK_EQ_MSG(powf(1.0, z), 1.0, "z=%a powf(1.0, z)=%a",
484 	    z, powf(1.0, z));
485 
486 	for (i = 0; i < __arraycount(y); i++) {
487 		ATF_CHECK_EQ_MSG(powf(1.0, y[i]), 1.0,
488 		    "i=%zu y[i]=%a powf(1.0, y[i])=%a",
489 		    i, y[i], powf(1.0, y[i]));
490 	}
491 }
492 
493 ATF_TC(powf_zero_x);
ATF_TC_HEAD(powf_zero_x,tc)494 ATF_TC_HEAD(powf_zero_x, tc)
495 {
496 	atf_tc_set_md_var(tc, "descr", "Test powf(+-0.0, y) == +-0.0 || HUGE");
497 }
498 
ATF_TC_BODY(powf_zero_x,tc)499 ATF_TC_BODY(powf_zero_x, tc)
500 {
501 	float z;
502 
503 	/*
504 	 * If x is +0.0 or -0.0, y > 0, and y
505 	 * is an odd integer, x is returned.
506 	 */
507 	z = powf(+0.0, 3.0);
508 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
509 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
510 
511 	z = powf(-0.0, 3.0);
512 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
513 	ATF_CHECK_MSG(signbit(z) != 0, "z=%a", z);
514 
515 	/*
516 	 * If y > 0 and not an odd integer,
517 	 * if x is +0.0 or -0.0, +0.0 is returned.
518 	 */
519 	z = powf(+0.0, 4.0);
520 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
521 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
522 
523 	z = powf(-0.0, 4.0);
524 	ATF_CHECK_MSG(fabsf(z) == 0.0, "z=%a", z);
525 	ATF_CHECK_MSG(signbit(z) == 0, "z=%a", z);
526 
527 	/*
528 	 * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL,
529 	 * +-HUGE_VALF, or +-HUGE_VALL shall be returned.
530 	 */
531 	z = powf(+0.0, -4.0);
532 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
533 
534 	z = powf(-0.0, -4.0);
535 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
536 
537 	z = powf(+0.0, -5.0);
538 	ATF_CHECK_EQ_MSG(z, HUGE_VALF, "z=%a", z);
539 
540 	z = powf(-0.0, -5.0);
541 	ATF_CHECK_EQ_MSG(z, -HUGE_VALF, "z=%a", z);
542 }
543 
544 ATF_TC(powf_zero_y);
ATF_TC_HEAD(powf_zero_y,tc)545 ATF_TC_HEAD(powf_zero_y, tc)
546 {
547 	atf_tc_set_md_var(tc, "descr", "Test powf(x, +-0.0) == 1.0");
548 }
549 
ATF_TC_BODY(powf_zero_y,tc)550 ATF_TC_BODY(powf_zero_y, tc)
551 {
552 	const volatile float x[] =  { 0.1, -3.0, 77.0, 99.99, 101.0000001 };
553 	const volatile float z = 0.0f / 0.0f;
554 	size_t i;
555 
556 	/*
557 	 * For any value of x (including NaN),
558 	 * if y is +0.0 or -0.0, 1.0 is returned.
559 	 */
560 	ATF_CHECK_EQ_MSG(powf(z, +0.0), 1.0, "z=%a powf(z, +0.0)=%a",
561 	    z, powf(z, +0.0));
562 	ATF_CHECK_EQ_MSG(powf(z, -0.0), 1.0, "z=%a powf(z, -0.0)=%a",
563 	    z, powf(z, -0.0));
564 
565 	for (i = 0; i < __arraycount(x); i++) {
566 		ATF_CHECK_EQ_MSG(powf(x[i], +0.0), 1.0,
567 		    "i=%zu powf(%a, +0.0)=%a", i, x[i], powf(x[i], +0.0));
568 		ATF_CHECK_EQ_MSG(powf(x[i], -0.0), 1.0,
569 		    "i=%zu powf(%a, -0.0)=%a", i, x[i], powf(x[i], -0.0));
570 	}
571 }
572 
ATF_TP_ADD_TCS(tp)573 ATF_TP_ADD_TCS(tp)
574 {
575 
576 	ATF_TP_ADD_TC(tp, pow_nan_x);
577 	ATF_TP_ADD_TC(tp, pow_nan_y);
578 	ATF_TP_ADD_TC(tp, pow_inf_neg_x);
579 	ATF_TP_ADD_TC(tp, pow_inf_neg_y);
580 	ATF_TP_ADD_TC(tp, pow_inf_pos_x);
581 	ATF_TP_ADD_TC(tp, pow_inf_pos_y);
582 	ATF_TP_ADD_TC(tp, pow_one_neg_x);
583 	ATF_TP_ADD_TC(tp, pow_one_pos_x);
584 	ATF_TP_ADD_TC(tp, pow_zero_x);
585 	ATF_TP_ADD_TC(tp, pow_zero_y);
586 
587 	ATF_TP_ADD_TC(tp, powf_nan_x);
588 	ATF_TP_ADD_TC(tp, powf_nan_y);
589 	ATF_TP_ADD_TC(tp, powf_inf_neg_x);
590 	ATF_TP_ADD_TC(tp, powf_inf_neg_y);
591 	ATF_TP_ADD_TC(tp, powf_inf_pos_x);
592 	ATF_TP_ADD_TC(tp, powf_inf_pos_y);
593 	ATF_TP_ADD_TC(tp, powf_one_neg_x);
594 	ATF_TP_ADD_TC(tp, powf_one_pos_x);
595 	ATF_TP_ADD_TC(tp, powf_zero_x);
596 	ATF_TP_ADD_TC(tp, powf_zero_y);
597 
598 	return atf_no_error();
599 }
600