xref: /netbsd-src/tests/lib/libm/t_ldexp.c (revision 48fb7bfab72acd4281a53bbee5ccf3f809019e75)
1 /* $NetBSD: t_ldexp.c,v 1.11 2014/02/09 21:26:07 jmmv 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_ldexp.c,v 1.11 2014/02/09 21:26:07 jmmv Exp $");
33 
34 #include <sys/param.h>
35 
36 #include <atf-c.h>
37 #include <atf-c/config.h>
38 
39 #include <math.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <string.h>
43 
44 #define SKIP	9999
45 #define FORMAT  "%23.23lg"
46 
47 static const int exps[] = { 0, 1, -1, 100, -100 };
48 
49 struct ldexp_test {
50 	double	    x;
51 	int	    exp1;
52 	int	    exp2;
53 	const char *result;
54 };
55 
56 struct ldexp_test ldexp_basic[] = {
57 	{ 1.0,	5,	SKIP,	"                     32" },
58 	{ 1.0,	1022,	SKIP,	"4.4942328371557897693233e+307" },
59 	{ 1.0,	1023,	-1,	"4.4942328371557897693233e+307" },
60 	{ 1.0,	1023,	SKIP,	"8.9884656743115795386465e+307" },
61 	{ 1.0,	1022,	1,	"8.9884656743115795386465e+307" },
62 	{ 1.0,	-1022,	2045,	"8.9884656743115795386465e+307" },
63 	{ 1.0,	-5,	SKIP,	"                0.03125" },
64 	{ 1.0,	-1021,	SKIP,	"4.4501477170144027661805e-308" },
65 	{ 1.0,	-1022,	1,	"4.4501477170144027661805e-308" },
66 	{ 1.0,	-1022,	SKIP,	"2.2250738585072013830902e-308" },
67 	{ 1.0,	-1021,	-1,	"2.2250738585072013830902e-308" },
68 	{ 1.0,	1023,	-2045,	"2.2250738585072013830902e-308" },
69 	{ 1.0,	1023,	-1023,	"                      1" },
70 	{ 1.0,	-1022,	1022,	"                      1" },
71 	{ 0,	0,	0,	NULL }
72 };
73 
74 struct ldexp_test ldexp_zero[] = {
75 	{ 0.0,	-1,	SKIP,	"                      0" },
76 	{ 0.0,	0,	SKIP,	"                      0" },
77 	{ 0.0,	1,	SKIP,	"                      0" },
78 	{ 0.0,	1024,	SKIP,	"                      0" },
79 	{ 0.0,	1025,	SKIP,	"                      0" },
80 	{ 0.0,	-1023,	SKIP,	"                      0" },
81 	{ 0.0,	-1024,	SKIP,	"                      0" },
82 	{ 0,	0,	0,	NULL }
83 };
84 
85 struct ldexp_test ldexp_infinity[] = {
86 	{ 1.0,	1024,	-1,	"                    inf" },
87 	{ 1.0,	1024,	0,	"                    inf" },
88 	{ 1.0,	1024,	1,	"                    inf" },
89 	{ -1.0,	1024,	-1,	"                   -inf" },
90 	{ -1.0,	1024,	0,	"                   -inf" },
91 	{ -1.0,	1024,	1,	"                   -inf" },
92 	{ 0,	0,	0,	NULL }
93 };
94 
95 struct ldexp_test ldexp_overflow[] = {
96 	{ 1.0,	1024,	SKIP,	"                    inf" },
97 	{ 1.0,	1023,	1,	"                    inf" },
98 	{ 1.0,	-1022,	2046,	"                    inf" },
99 	{ 1.0,	1025,	SKIP,	"                    inf" },
100 	{ -1.0,	1024,	SKIP,	"                   -inf" },
101 	{ -1.0,	1023,	1,	"                   -inf" },
102 	{ -1.0,	-1022,	2046,	"                   -inf" },
103 	{ -1.0,	1025,	SKIP,	"                   -inf" },
104 	{ 0,	0,	0,	NULL }
105 };
106 
107 struct ldexp_test ldexp_denormal[] = {
108 	{ 1.0,	-1023,	SKIP,	"1.1125369292536006915451e-308" },
109 	{ 1.0,	-1022,	-1,	"1.1125369292536006915451e-308" },
110 	{ 1.0,	1023,	-2046,	"1.1125369292536006915451e-308" },
111 	{ 1.0,	-1024,	SKIP,	"5.5626846462680034577256e-309" },
112 	{ 1.0,	-1074,	SKIP,	"4.9406564584124654417657e-324" },
113 	{ -1.0,	-1023,	SKIP,	"-1.1125369292536006915451e-308" },
114 	{ -1.0,	-1022,	-1,	"-1.1125369292536006915451e-308" },
115 	{ -1.0,	1023,	-2046,	"-1.1125369292536006915451e-308" },
116 	{ -1.0,	-1024,	SKIP,	"-5.5626846462680034577256e-309" },
117 	{ -1.0,	-1074,	SKIP,	"-4.9406564584124654417657e-324" },
118 	{ 0,	0,	0,	NULL }
119 };
120 
121 struct ldexp_test ldexp_underflow[] = {
122 	{ 1.0,	-1075,	SKIP,	"                      0" },
123 	{ 1.0,	-1074,	-1,	"                      0" },
124 	{ 1.0,	1023,	-2098,	"                      0" },
125 	{ 1.0,	-1076,	SKIP,	"                      0" },
126 	{ -1.0,	-1075,	SKIP,	"                     -0" },
127 	{ -1.0,	-1074,	-1,	"                     -0" },
128 	{ -1.0,	1023,	-2098,	"                     -0" },
129 	{ -1.0,	-1076,	SKIP,	"                     -0" },
130 	{ 0,	0,	0,	NULL }
131 };
132 
133 struct ldexp_test ldexp_denormal_large[] = {
134 	{ 1.0,	-1028,	1024,	"                 0.0625" },
135 	{ 1.0,	-1028,	1025,	"                  0.125" },
136 	{ 1.0,	-1028,	1026,	"                   0.25" },
137 	{ 1.0,	-1028,	1027,	"                    0.5" },
138 	{ 1.0,	-1028,	1028,	"                      1" },
139 	{ 1.0,	-1028,	1029,	"                      2" },
140 	{ 1.0,	-1028,	1030,	"                      4" },
141 	{ 1.0,	-1028,	1040,	"                   4096" },
142 	{ 1.0,	-1028,	1050,	"                4194304" },
143 	{ 1.0,	-1028,	1060,	"             4294967296" },
144 	{ 1.0,	-1028,	1100,	" 4722366482869645213696" },
145 	{ 1.0,	-1028,	1200,	"5.9863107065073783529623e+51" },
146 	{ 1.0,	-1028,	1300,	"7.5885503602567541832791e+81" },
147 	{ 1.0,	-1028,	1400,	"9.6196304190416209014353e+111" },
148 	{ 1.0,	-1028,	1500,	"1.2194330274671844653834e+142" },
149 	{ 1.0,	-1028,	1600,	"1.5458150092069033378781e+172" },
150 	{ 1.0,	-1028,	1700,	"1.9595533242629369747791e+202" },
151 	{ 1.0,	-1028,	1800,	"2.4840289476811342962384e+232" },
152 	{ 1.0,	-1028,	1900,	"3.1488807865122869393369e+262" },
153 	{ 1.0,	-1028,	2000,	"3.9916806190694396233127e+292" },
154 	{ 1.0,	-1028,	2046,	"2.808895523222368605827e+306" },
155 	{ 1.0,	-1028,	2047,	"5.6177910464447372116541e+306" },
156 	{ 1.0,	-1028,	2048,	"1.1235582092889474423308e+307" },
157 	{ 1.0,	-1028,	2049,	"2.2471164185778948846616e+307" },
158 	{ 1.0,	-1028,	2050,	"4.4942328371557897693233e+307" },
159 	{ 1.0,	-1028,	2051,	"8.9884656743115795386465e+307" },
160 	{ 0,	0,	0,	NULL }
161 };
162 
163 static void
164 run_test(struct ldexp_test *table)
165 {
166 	char outbuf[64];
167 	size_t i;
168 	double v;
169 
170 	for (i = 0; table->result != NULL; table++, i++) {
171 
172 		v = ldexp(table->x, table->exp1);
173 
174 		if (table->exp2 == SKIP)
175 			continue;
176 
177 		v = ldexp(v, table->exp2);
178 
179 		(void)snprintf(outbuf, sizeof(outbuf), FORMAT, v);
180 
181 		ATF_CHECK_STREQ_MSG(table->result, outbuf,
182 			    "Entry %zu:\n\tExp: \"%s\"\n\tAct: \"%s\"",
183 			    i, table->result, outbuf);
184 	}
185 }
186 
187 /*
188  * ldexp(3)
189  */
190 ATF_TC(ldexp_exp2);
191 ATF_TC_HEAD(ldexp_exp2, tc)
192 {
193 	atf_tc_set_md_var(tc, "descr", "Test ldexp(x, n) == x * exp2(n)");
194 }
195 
196 ATF_TC_BODY(ldexp_exp2, tc)
197 {
198 #ifndef __vax__
199 	const double n[] = { 1, 2, 3, 10, 50, 100 };
200 	const double eps = 1.0e-40;
201 	const double x = 12.0;
202 	double y;
203 	size_t i;
204 
205 	for (i = 0; i < __arraycount(n); i++) {
206 
207 		y = ldexp(x, n[i]);
208 
209 		if (fabs(y - (x * exp2(n[i]))) > eps) {
210 			atf_tc_fail_nonfatal("ldexp(%0.01f, %0.01f) "
211 			    "!= %0.01f * exp2(%0.01f)", x, n[i], x, n[i]);
212 		}
213 	}
214 #endif
215 }
216 
217 ATF_TC(ldexp_nan);
218 ATF_TC_HEAD(ldexp_nan, tc)
219 {
220 	atf_tc_set_md_var(tc, "descr", "Test ldexp(NaN) == NaN");
221 }
222 
223 ATF_TC_BODY(ldexp_nan, tc)
224 {
225 #ifndef __vax__
226 	const double x = 0.0L / 0.0L;
227 	double y;
228 	size_t i;
229 
230 	ATF_REQUIRE(isnan(x) != 0);
231 
232 	for (i = 0; i < __arraycount(exps); i++) {
233 		y = ldexp(x, exps[i]);
234 		ATF_CHECK(isnan(y) != 0);
235 	}
236 #endif
237 }
238 
239 ATF_TC(ldexp_inf_neg);
240 ATF_TC_HEAD(ldexp_inf_neg, tc)
241 {
242 	atf_tc_set_md_var(tc, "descr", "Test ldexp(-Inf) == -Inf");
243 }
244 
245 ATF_TC_BODY(ldexp_inf_neg, tc)
246 {
247 #ifndef __vax__
248 	const double x = -1.0L / 0.0L;
249 	size_t i;
250 
251 	for (i = 0; i < __arraycount(exps); i++)
252 		ATF_CHECK(ldexp(x, exps[i]) == x);
253 #endif
254 }
255 
256 ATF_TC(ldexp_inf_pos);
257 ATF_TC_HEAD(ldexp_inf_pos, tc)
258 {
259 	atf_tc_set_md_var(tc, "descr", "Test ldexp(+Inf) == +Inf");
260 }
261 
262 ATF_TC_BODY(ldexp_inf_pos, tc)
263 {
264 #ifndef __vax__
265 	const double x = 1.0L / 0.0L;
266 	size_t i;
267 
268 	for (i = 0; i < __arraycount(exps); i++)
269 		ATF_CHECK(ldexp(x, exps[i]) == x);
270 #endif
271 }
272 
273 ATF_TC(ldexp_zero_neg);
274 ATF_TC_HEAD(ldexp_zero_neg, tc)
275 {
276 	atf_tc_set_md_var(tc, "descr", "Test ldexp(-0.0) == -0.0");
277 }
278 
279 ATF_TC_BODY(ldexp_zero_neg, tc)
280 {
281 #ifndef __vax__
282 	const double x = -0.0L;
283 	double y;
284 	size_t i;
285 
286 	ATF_REQUIRE(signbit(x) != 0);
287 
288 	for (i = 0; i < __arraycount(exps); i++) {
289 		y = ldexp(x, exps[i]);
290 		ATF_CHECK(x == y);
291 		ATF_CHECK(signbit(y) != 0);
292 	}
293 #endif
294 }
295 
296 ATF_TC(ldexp_zero_pos);
297 ATF_TC_HEAD(ldexp_zero_pos, tc)
298 {
299 	atf_tc_set_md_var(tc, "descr", "Test ldexp(+0.0) == +0.0");
300 }
301 
302 ATF_TC_BODY(ldexp_zero_pos, tc)
303 {
304 #ifndef __vax__
305 	const double x = 0.0L;
306 	double y;
307 	size_t i;
308 
309 	ATF_REQUIRE(signbit(x) == 0);
310 
311 	for (i = 0; i < __arraycount(exps); i++) {
312 		y = ldexp(x, exps[i]);
313 		ATF_CHECK(x == y);
314 		ATF_CHECK(signbit(y) == 0);
315 	}
316 #endif
317 }
318 
319 /*
320  * ldexpf(3)
321  */
322 
323 ATF_TC(ldexpf_exp2f);
324 ATF_TC_HEAD(ldexpf_exp2f, tc)
325 {
326 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(x, n) == x * exp2f(n)");
327 }
328 
329 ATF_TC_BODY(ldexpf_exp2f, tc)
330 {
331 #ifndef __vax__
332 	const float n[] = { 1, 2, 3, 10, 50, 100 };
333 	const float eps = 1.0e-9;
334 	const float x = 12.0;
335 	float y;
336 	size_t i;
337 
338 	for (i = 0; i < __arraycount(n); i++) {
339 
340 		y = ldexpf(x, n[i]);
341 
342 		if (fabsf(y - (x * exp2f(n[i]))) > eps) {
343 			atf_tc_fail_nonfatal("ldexpf(%0.01f, %0.01f) "
344 			    "!= %0.01f * exp2f(%0.01f)", x, n[i], x, n[i]);
345 		}
346 	}
347 #endif
348 }
349 
350 ATF_TC(ldexpf_nan);
351 ATF_TC_HEAD(ldexpf_nan, tc)
352 {
353 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(NaN) == NaN");
354 }
355 
356 ATF_TC_BODY(ldexpf_nan, tc)
357 {
358 #ifndef __vax__
359 	const float x = 0.0L / 0.0L;
360 	float y;
361 	size_t i;
362 
363 	ATF_REQUIRE(isnan(x) != 0);
364 
365 	for (i = 0; i < __arraycount(exps); i++) {
366 		y = ldexpf(x, exps[i]);
367 		ATF_CHECK(isnan(y) != 0);
368 	}
369 #endif
370 }
371 
372 ATF_TC(ldexpf_inf_neg);
373 ATF_TC_HEAD(ldexpf_inf_neg, tc)
374 {
375 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(-Inf) == -Inf");
376 }
377 
378 ATF_TC_BODY(ldexpf_inf_neg, tc)
379 {
380 #ifndef __vax__
381 	const float x = -1.0L / 0.0L;
382 	size_t i;
383 
384 	for (i = 0; i < __arraycount(exps); i++)
385 		ATF_CHECK(ldexpf(x, exps[i]) == x);
386 #endif
387 }
388 
389 ATF_TC(ldexpf_inf_pos);
390 ATF_TC_HEAD(ldexpf_inf_pos, tc)
391 {
392 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(+Inf) == +Inf");
393 }
394 
395 ATF_TC_BODY(ldexpf_inf_pos, tc)
396 {
397 #ifndef __vax__
398 	const float x = 1.0L / 0.0L;
399 	size_t i;
400 
401 	for (i = 0; i < __arraycount(exps); i++)
402 		ATF_CHECK(ldexpf(x, exps[i]) == x);
403 #endif
404 }
405 
406 ATF_TC(ldexpf_zero_neg);
407 ATF_TC_HEAD(ldexpf_zero_neg, tc)
408 {
409 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(-0.0) == -0.0");
410 }
411 
412 ATF_TC_BODY(ldexpf_zero_neg, tc)
413 {
414 #ifndef __vax__
415 	const float x = -0.0L;
416 	float y;
417 	size_t i;
418 
419 	ATF_REQUIRE(signbit(x) != 0);
420 
421 	for (i = 0; i < __arraycount(exps); i++) {
422 		y = ldexpf(x, exps[i]);
423 		ATF_CHECK(x == y);
424 		ATF_CHECK(signbit(y) != 0);
425 	}
426 #endif
427 }
428 
429 ATF_TC(ldexpf_zero_pos);
430 ATF_TC_HEAD(ldexpf_zero_pos, tc)
431 {
432 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(+0.0) == +0.0");
433 }
434 
435 ATF_TC_BODY(ldexpf_zero_pos, tc)
436 {
437 #ifndef __vax__
438 	const float x = 0.0L;
439 	float y;
440 	size_t i;
441 
442 	ATF_REQUIRE(signbit(x) == 0);
443 
444 	for (i = 0; i < __arraycount(exps); i++) {
445 		y = ldexpf(x, exps[i]);
446 		ATF_CHECK(x == y);
447 		ATF_CHECK(signbit(y) == 0);
448 	}
449 #endif
450 }
451 
452 #define TEST(name, desc)						\
453 	ATF_TC(name);							\
454 	ATF_TC_HEAD(name, tc)						\
455 	{								\
456 									\
457 		atf_tc_set_md_var(tc, "descr",				\
458 		    "Test ldexp(3) for " ___STRING(desc));		\
459 	}								\
460 	ATF_TC_BODY(name, tc)						\
461 	{								\
462 		if (strcmp("vax", MACHINE_ARCH) == 0)			\
463 			atf_tc_skip("Test not valid for " MACHINE_ARCH); \
464 		run_test(name);						\
465 	}
466 
467 TEST(ldexp_basic, basics)
468 TEST(ldexp_zero, zero)
469 TEST(ldexp_infinity, infinity)
470 TEST(ldexp_overflow, overflow)
471 TEST(ldexp_denormal, denormal)
472 TEST(ldexp_denormal_large, large)
473 TEST(ldexp_underflow, underflow)
474 
475 ATF_TP_ADD_TCS(tp)
476 {
477 
478 	ATF_TP_ADD_TC(tp, ldexp_basic);
479 	ATF_TP_ADD_TC(tp, ldexp_zero);
480 	ATF_TP_ADD_TC(tp, ldexp_infinity);
481 	ATF_TP_ADD_TC(tp, ldexp_overflow);
482 	ATF_TP_ADD_TC(tp, ldexp_denormal);
483 	ATF_TP_ADD_TC(tp, ldexp_underflow);
484 	ATF_TP_ADD_TC(tp, ldexp_denormal_large);
485 
486 	ATF_TP_ADD_TC(tp, ldexp_exp2);
487 	ATF_TP_ADD_TC(tp, ldexp_nan);
488 	ATF_TP_ADD_TC(tp, ldexp_inf_neg);
489 	ATF_TP_ADD_TC(tp, ldexp_inf_pos);
490 	ATF_TP_ADD_TC(tp, ldexp_zero_neg);
491 	ATF_TP_ADD_TC(tp, ldexp_zero_pos);
492 
493 	ATF_TP_ADD_TC(tp, ldexpf_exp2f);
494 	ATF_TP_ADD_TC(tp, ldexpf_nan);
495 	ATF_TP_ADD_TC(tp, ldexpf_inf_neg);
496 	ATF_TP_ADD_TC(tp, ldexpf_inf_pos);
497 	ATF_TP_ADD_TC(tp, ldexpf_zero_neg);
498 	ATF_TP_ADD_TC(tp, ldexpf_zero_pos);
499 
500 	return atf_no_error();
501 }
502