xref: /minix3/tests/lib/libm/t_scalbn.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 /* $NetBSD: t_scalbn.c,v 1.10 2013/05/24 11:47:13 martin 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_scalbn.c,v 1.10 2013/05/24 11:47:13 martin Exp $");
33 
34 #include <math.h>
35 #include <limits.h>
36 #include <float.h>
37 #include <errno.h>
38 
39 #include <atf-c.h>
40 
41 static const int exps[] = { 0, 1, -1, 100, -100 };
42 
43 /* tests here do not require specific precision, so we just use double */
44 struct testcase {
45 	int exp;
46 	double inval;
47 	double result;
48 	int error;
49 };
50 struct testcase test_vals[] = {
51 	{ 0,		1.00085,	1.00085,	0 },
52 	{ 0,		0.99755,	0.99755,	0 },
53 	{ 0,		-1.00085,	-1.00085,	0 },
54 	{ 0,		-0.99755,	-0.99755,	0 },
55 	{ 1,		1.00085,	2.0* 1.00085,	0 },
56 	{ 1,		0.99755,	2.0* 0.99755,	0 },
57 	{ 1,		-1.00085,	2.0* -1.00085,	0 },
58 	{ 1,		-0.99755,	2.0* -0.99755,	0 },
59 
60 	/*
61 	 * We could add more corner test cases here, but we would have to
62 	 * add some ifdefs for the exact format and use a reliable
63 	 * generator program - bail for now and only do trivial stuff above.
64 	 */
65 };
66 
67 /*
68  * scalbn(3)
69  */
70 ATF_TC(scalbn_val);
71 ATF_TC_HEAD(scalbn_val, tc)
72 {
73 	atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values");
74 }
75 
76 ATF_TC_BODY(scalbn_val, tc)
77 {
78 	const struct testcase *tests = test_vals;
79 	const size_t tcnt = __arraycount(test_vals);
80 	size_t i;
81 	double rv;
82 
83 	for (i = 0; i < tcnt; i++) {
84 		rv = scalbn(tests[i].inval, tests[i].exp);
85 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
86 		    "test %zu: errno %d instead of %d", i, errno,
87 		    tests[i].error);
88 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON,
89 		    "test %zu: return value %g instead of %g (difference %g)",
90 		    i, rv, tests[i].result, tests[i].result-rv);
91 	}
92 }
93 
94 ATF_TC(scalbn_nan);
95 ATF_TC_HEAD(scalbn_nan, tc)
96 {
97 	atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN");
98 }
99 
100 ATF_TC_BODY(scalbn_nan, tc)
101 {
102 #ifndef __vax__
103 	const double x = 0.0L / 0.0L;
104 	double y;
105 	size_t i;
106 
107 	ATF_REQUIRE(isnan(x) != 0);
108 
109 	for (i = 0; i < __arraycount(exps); i++) {
110 		y = scalbn(x, exps[i]);
111 		ATF_CHECK(isnan(y) != 0);
112 	}
113 #endif
114 }
115 
116 ATF_TC(scalbn_inf_neg);
117 ATF_TC_HEAD(scalbn_inf_neg, tc)
118 {
119 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf");
120 }
121 
122 ATF_TC_BODY(scalbn_inf_neg, tc)
123 {
124 #ifndef __vax__
125 	const double x = -1.0L / 0.0L;
126 	size_t i;
127 
128 	for (i = 0; i < __arraycount(exps); i++)
129 		ATF_CHECK(scalbn(x, exps[i]) == x);
130 #endif
131 }
132 
133 ATF_TC(scalbn_inf_pos);
134 ATF_TC_HEAD(scalbn_inf_pos, tc)
135 {
136 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf");
137 }
138 
139 ATF_TC_BODY(scalbn_inf_pos, tc)
140 {
141 #ifndef __vax__
142 	const double x = 1.0L / 0.0L;
143 	size_t i;
144 
145 	for (i = 0; i < __arraycount(exps); i++)
146 		ATF_CHECK(scalbn(x, exps[i]) == x);
147 #endif
148 }
149 
150 ATF_TC(scalbn_ldexp);
151 ATF_TC_HEAD(scalbn_ldexp, tc)
152 {
153 	atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)");
154 }
155 
156 ATF_TC_BODY(scalbn_ldexp, tc)
157 {
158 #ifndef __vax__
159 #if FLT_RADIX == 2
160 	const double x = 2.91288191221812821;
161 	double y;
162 	size_t i;
163 
164 	for (i = 0; i < __arraycount(exps); i++) {
165 		y = scalbn(x, exps[i]);
166 		ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, "
167 		    "y=%g, expected %g (diff: %g)", i, exps[i], y,
168 		    ldexp(x, exps[i]), y - ldexp(x, exps[i]));
169 	}
170 #endif
171 #endif
172 }
173 
174 ATF_TC(scalbn_zero_neg);
175 ATF_TC_HEAD(scalbn_zero_neg, tc)
176 {
177 	atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0");
178 }
179 
180 ATF_TC_BODY(scalbn_zero_neg, tc)
181 {
182 #ifndef __vax__
183 	const double x = -0.0L;
184 	double y;
185 	size_t i;
186 
187 	ATF_REQUIRE(signbit(x) != 0);
188 
189 	for (i = 0; i < __arraycount(exps); i++) {
190 		y = scalbn(x, exps[i]);
191 		ATF_CHECK(x == y);
192 		ATF_CHECK(signbit(y) != 0);
193 	}
194 #endif
195 }
196 
197 ATF_TC(scalbn_zero_pos);
198 ATF_TC_HEAD(scalbn_zero_pos, tc)
199 {
200 	atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0");
201 }
202 
203 ATF_TC_BODY(scalbn_zero_pos, tc)
204 {
205 #ifndef __vax__
206 	const double x = 0.0L;
207 	double y;
208 	size_t i;
209 
210 	ATF_REQUIRE(signbit(x) == 0);
211 
212 	for (i = 0; i < __arraycount(exps); i++) {
213 		y = scalbn(x, exps[i]);
214 		ATF_CHECK(x == y);
215 		ATF_CHECK(signbit(y) == 0);
216 	}
217 #endif
218 }
219 
220 /*
221  * scalbnf(3)
222  */
223 ATF_TC(scalbnf_val);
224 ATF_TC_HEAD(scalbnf_val, tc)
225 {
226 	atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values");
227 }
228 
229 ATF_TC_BODY(scalbnf_val, tc)
230 {
231 #ifndef __vax__
232 	const struct testcase *tests = test_vals;
233 	const size_t tcnt = __arraycount(test_vals);
234 	size_t i;
235 	double rv;
236 
237 	for (i = 0; i < tcnt; i++) {
238 		rv = scalbnf(tests[i].inval, tests[i].exp);
239 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
240 		    "test %zu: errno %d instead of %d", i, errno,
241 		    tests[i].error);
242 		ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON,
243 		    "test %zu: return value %g instead of %g (difference %g)",
244 		    i, rv, tests[i].result, tests[i].result-rv);
245 	}
246 #endif
247 }
248 
249 ATF_TC(scalbnf_nan);
250 ATF_TC_HEAD(scalbnf_nan, tc)
251 {
252 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN");
253 }
254 
255 ATF_TC_BODY(scalbnf_nan, tc)
256 {
257 #ifndef __vax__
258 	const float x = 0.0L / 0.0L;
259 	float y;
260 	size_t i;
261 
262 	ATF_REQUIRE(isnan(x) != 0);
263 
264 	for (i = 0; i < __arraycount(exps); i++) {
265 		y = scalbnf(x, exps[i]);
266 		ATF_CHECK(isnan(y) != 0);
267 	}
268 #endif
269 }
270 
271 ATF_TC(scalbnf_inf_neg);
272 ATF_TC_HEAD(scalbnf_inf_neg, tc)
273 {
274 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf");
275 }
276 
277 ATF_TC_BODY(scalbnf_inf_neg, tc)
278 {
279 #ifndef __vax__
280 	const float x = -1.0L / 0.0L;
281 	size_t i;
282 
283 	for (i = 0; i < __arraycount(exps); i++)
284 		ATF_CHECK(scalbnf(x, exps[i]) == x);
285 #endif
286 }
287 
288 ATF_TC(scalbnf_inf_pos);
289 ATF_TC_HEAD(scalbnf_inf_pos, tc)
290 {
291 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf");
292 }
293 
294 ATF_TC_BODY(scalbnf_inf_pos, tc)
295 {
296 #ifndef __vax__
297 	const float x = 1.0L / 0.0L;
298 	size_t i;
299 
300 	for (i = 0; i < __arraycount(exps); i++)
301 		ATF_CHECK(scalbnf(x, exps[i]) == x);
302 #endif
303 }
304 
305 ATF_TC(scalbnf_ldexpf);
306 ATF_TC_HEAD(scalbnf_ldexpf, tc)
307 {
308 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)");
309 }
310 
311 ATF_TC_BODY(scalbnf_ldexpf, tc)
312 {
313 #ifndef __vax__
314 #if FLT_RADIX == 2
315 	const float x = 2.91288191221812821;
316 	float y;
317 	size_t i;
318 
319 	for (i = 0; i < __arraycount(exps); i++) {
320 		y = scalbnf(x, exps[i]);
321 		ATF_CHECK_MSG(y == ldexpf(x, exps[i]),
322 		    "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)",
323 		    i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i]));
324 	}
325 #endif
326 #endif
327 }
328 
329 ATF_TC(scalbnf_zero_neg);
330 ATF_TC_HEAD(scalbnf_zero_neg, tc)
331 {
332 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0");
333 }
334 
335 ATF_TC_BODY(scalbnf_zero_neg, tc)
336 {
337 #ifndef __vax__
338 	const float x = -0.0L;
339 	float y;
340 	size_t i;
341 
342 	ATF_REQUIRE(signbit(x) != 0);
343 
344 	for (i = 0; i < __arraycount(exps); i++) {
345 		y = scalbnf(x, exps[i]);
346 		ATF_CHECK(x == y);
347 		ATF_CHECK(signbit(y) != 0);
348 	}
349 #endif
350 }
351 
352 ATF_TC(scalbnf_zero_pos);
353 ATF_TC_HEAD(scalbnf_zero_pos, tc)
354 {
355 	atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0");
356 }
357 
358 ATF_TC_BODY(scalbnf_zero_pos, tc)
359 {
360 #ifndef __vax__
361 	const float x = 0.0L;
362 	float y;
363 	size_t i;
364 
365 	ATF_REQUIRE(signbit(x) == 0);
366 
367 	for (i = 0; i < __arraycount(exps); i++) {
368 		y = scalbnf(x, exps[i]);
369 		ATF_CHECK(x == y);
370 		ATF_CHECK(signbit(y) == 0);
371 	}
372 #endif
373 }
374 
375 /*
376  * scalbnl(3)
377  */
378 ATF_TC(scalbnl_val);
379 ATF_TC_HEAD(scalbnl_val, tc)
380 {
381 	atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values");
382 }
383 
384 ATF_TC_BODY(scalbnl_val, tc)
385 {
386 #ifndef __HAVE_LONG_DOUBLE
387 	atf_tc_skip("Requires long double support");
388 #else
389 	const struct testcase *tests = test_vals;
390 	const size_t tcnt = __arraycount(test_vals);
391 	size_t i;
392 	long double rv;
393 
394 	for (i = 0; i < tcnt; i++) {
395 		rv = scalbnl(tests[i].inval, tests[i].exp);
396 		ATF_CHECK_EQ_MSG(errno, tests[i].error,
397 		    "test %zu: errno %d instead of %d", i, errno,
398 		    tests[i].error);
399 		ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON,
400 		    "test %zu: return value %Lg instead of %Lg (difference %Lg)",
401 		    i, rv, (long double)tests[i].result, (long double)tests[i].result-rv);
402 	}
403 #endif
404 }
405 
406 ATF_TC(scalbnl_nan);
407 ATF_TC_HEAD(scalbnl_nan, tc)
408 {
409 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN");
410 }
411 
412 ATF_TC_BODY(scalbnl_nan, tc)
413 {
414 #ifndef __vax__
415 #ifndef __HAVE_LONG_DOUBLE
416 	atf_tc_skip("Requires long double support");
417 #else
418 	const long double x = 0.0L / 0.0L;
419 	long double y;
420 	size_t i;
421 
422 	if (isnan(x) == 0) {
423 		atf_tc_expect_fail("PR lib/45362");
424 		atf_tc_fail("(0.0L / 0.0L) != NaN");
425 	}
426 
427 	for (i = 0; i < __arraycount(exps); i++) {
428 		y = scalbnl(x, exps[i]);
429 		ATF_CHECK(isnan(y) != 0);
430 	}
431 #endif
432 #endif
433 }
434 
435 ATF_TC(scalbnl_inf_neg);
436 ATF_TC_HEAD(scalbnl_inf_neg, tc)
437 {
438 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf");
439 }
440 
441 ATF_TC_BODY(scalbnl_inf_neg, tc)
442 {
443 #ifndef __vax__
444 #ifndef __HAVE_LONG_DOUBLE
445 	atf_tc_skip("Requires long double support");
446 #else
447 	const long double x = -1.0L / 0.0L;
448 	size_t i;
449 
450 	for (i = 0; i < __arraycount(exps); i++)
451 		ATF_CHECK(scalbnl(x, exps[i]) == x);
452 #endif
453 #endif
454 }
455 
456 ATF_TC(scalbnl_inf_pos);
457 ATF_TC_HEAD(scalbnl_inf_pos, tc)
458 {
459 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf");
460 }
461 
462 ATF_TC_BODY(scalbnl_inf_pos, tc)
463 {
464 #ifndef __vax__
465 #ifndef __HAVE_LONG_DOUBLE
466 	atf_tc_skip("Requires long double support");
467 #else
468 	const long double x = 1.0L / 0.0L;
469 	size_t i;
470 
471 	for (i = 0; i < __arraycount(exps); i++)
472 		ATF_CHECK(scalbnl(x, exps[i]) == x);
473 #endif
474 #endif
475 }
476 
477 ATF_TC(scalbnl_zero_neg);
478 ATF_TC_HEAD(scalbnl_zero_neg, tc)
479 {
480 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0");
481 }
482 
483 ATF_TC_BODY(scalbnl_zero_neg, tc)
484 {
485 #ifndef __vax__
486 #ifndef __HAVE_LONG_DOUBLE
487 	atf_tc_skip("Requires long double support");
488 #else
489 	const long double x = -0.0L;
490 	long double y;
491 	size_t i;
492 
493 	ATF_REQUIRE(signbit(x) != 0);
494 
495 	for (i = 0; i < __arraycount(exps); i++) {
496 		y = scalbnl(x, exps[i]);
497 		ATF_CHECK(x == y);
498 		ATF_CHECK(signbit(y) != 0);
499 	}
500 #endif
501 #endif
502 }
503 
504 ATF_TC(scalbnl_zero_pos);
505 ATF_TC_HEAD(scalbnl_zero_pos, tc)
506 {
507 	atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0");
508 }
509 
510 ATF_TC_BODY(scalbnl_zero_pos, tc)
511 {
512 #ifndef __vax__
513 #ifndef __HAVE_LONG_DOUBLE
514 	atf_tc_skip("Requires long double support");
515 #else
516 	const long double x = 0.0L;
517 	long double y;
518 	size_t i;
519 
520 	ATF_REQUIRE(signbit(x) == 0);
521 
522 	for (i = 0; i < __arraycount(exps); i++) {
523 		y = scalbnl(x, exps[i]);
524 		ATF_CHECK(x == y);
525 		ATF_CHECK(signbit(y) == 0);
526 	}
527 #endif
528 #endif
529 }
530 
531 ATF_TP_ADD_TCS(tp)
532 {
533 
534 	ATF_TP_ADD_TC(tp, scalbn_val);
535 	ATF_TP_ADD_TC(tp, scalbn_nan);
536 	ATF_TP_ADD_TC(tp, scalbn_inf_neg);
537 	ATF_TP_ADD_TC(tp, scalbn_inf_pos);
538 	ATF_TP_ADD_TC(tp, scalbn_ldexp);
539 	ATF_TP_ADD_TC(tp, scalbn_zero_neg);
540 	ATF_TP_ADD_TC(tp, scalbn_zero_pos);
541 
542 	ATF_TP_ADD_TC(tp, scalbnf_val);
543 	ATF_TP_ADD_TC(tp, scalbnf_nan);
544 	ATF_TP_ADD_TC(tp, scalbnf_inf_neg);
545 	ATF_TP_ADD_TC(tp, scalbnf_inf_pos);
546 	ATF_TP_ADD_TC(tp, scalbnf_ldexpf);
547 	ATF_TP_ADD_TC(tp, scalbnf_zero_neg);
548 	ATF_TP_ADD_TC(tp, scalbnf_zero_pos);
549 
550 	ATF_TP_ADD_TC(tp, scalbnl_val);
551 	ATF_TP_ADD_TC(tp, scalbnl_nan);
552 	ATF_TP_ADD_TC(tp, scalbnl_inf_neg);
553 	ATF_TP_ADD_TC(tp, scalbnl_inf_pos);
554 /*	ATF_TP_ADD_TC(tp, scalbnl_ldexp);	*/
555 	ATF_TP_ADD_TC(tp, scalbnl_zero_neg);
556 	ATF_TP_ADD_TC(tp, scalbnl_zero_pos);
557 
558 	return atf_no_error();
559 }
560