1 /* $NetBSD: t_ldexp.c,v 1.17 2018/11/07 03:59:36 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_ldexp.c,v 1.17 2018/11/07 03:59:36 riastradh Exp $");
33 
34 #include <sys/param.h>
35 
36 #include <atf-c.h>
37 
38 #include <float.h>
39 #include <limits.h>
40 #include <math.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           { 2.0,    INT_MAX,SKIP,       "                    inf" },
101           { -1.0,   1024,     SKIP,     "                   -inf" },
102           { -1.0,   1023,     1,        "                   -inf" },
103           { -1.0,   -1022,    2046,     "                   -inf" },
104           { -1.0,   1025,     SKIP,     "                   -inf" },
105           { -2.0, INT_MAX,SKIP,         "                   -inf" },
106           { 0,      0,        0,        NULL }
107 };
108 
109 struct ldexp_test ldexp_denormal[] = {
110           { 1.0,    -1023,    SKIP,     "1.1125369292536006915451e-308" },
111           { 1.0,    -1022,    -1,       "1.1125369292536006915451e-308" },
112           { 1.0,    1023,     -2046,    "1.1125369292536006915451e-308" },
113           { 1.0,    -1024,    SKIP,     "5.5626846462680034577256e-309" },
114           { 1.0,    -1074,    SKIP,     "4.9406564584124654417657e-324" },
115           { -1.0,   -1023,    SKIP,     "-1.1125369292536006915451e-308" },
116           { -1.0,   -1022,    -1,       "-1.1125369292536006915451e-308" },
117           { -1.0,   1023,     -2046,    "-1.1125369292536006915451e-308" },
118           { -1.0,   -1024,    SKIP,     "-5.5626846462680034577256e-309" },
119           { -1.0,   -1074,    SKIP,     "-4.9406564584124654417657e-324" },
120           { 0,      0,        0,        NULL }
121 };
122 
123 struct ldexp_test ldexp_underflow[] = {
124           { 1.0,    -1075,    SKIP,     "                      0" },
125           { 1.0,    -1074,    -1,       "                      0" },
126           { 1.0,    1023,     -2098,    "                      0" },
127           { 1.0,    -1076,    SKIP,     "                      0" },
128           { -1.0,   -1075,    SKIP,     "                     -0" },
129           { -1.0,   -1074,    -1,       "                     -0" },
130           { -1.0,   1023,     -2098,    "                     -0" },
131           { -1.0,   -1076,    SKIP,     "                     -0" },
132           { 0,      0,        0,        NULL }
133 };
134 
135 struct ldexp_test ldexp_denormal_large[] = {
136           { 1.0,    -1028,    1024,     "                 0.0625" },
137           { 1.0,    -1028,    1025,     "                  0.125" },
138           { 1.0,    -1028,    1026,     "                   0.25" },
139           { 1.0,    -1028,    1027,     "                    0.5" },
140           { 1.0,    -1028,    1028,     "                      1" },
141           { 1.0,    -1028,    1029,     "                      2" },
142           { 1.0,    -1028,    1030,     "                      4" },
143           { 1.0,    -1028,    1040,     "                   4096" },
144           { 1.0,    -1028,    1050,     "                4194304" },
145           { 1.0,    -1028,    1060,     "             4294967296" },
146           { 1.0,    -1028,    1100,     " 4722366482869645213696" },
147           { 1.0,    -1028,    1200,     "5.9863107065073783529623e+51" },
148           { 1.0,    -1028,    1300,     "7.5885503602567541832791e+81" },
149           { 1.0,    -1028,    1400,     "9.6196304190416209014353e+111" },
150           { 1.0,    -1028,    1500,     "1.2194330274671844653834e+142" },
151           { 1.0,    -1028,    1600,     "1.5458150092069033378781e+172" },
152           { 1.0,    -1028,    1700,     "1.9595533242629369747791e+202" },
153           { 1.0,    -1028,    1800,     "2.4840289476811342962384e+232" },
154           { 1.0,    -1028,    1900,     "3.1488807865122869393369e+262" },
155           { 1.0,    -1028,    2000,     "3.9916806190694396233127e+292" },
156           { 1.0,    -1028,    2046,     "2.808895523222368605827e+306" },
157           { 1.0,    -1028,    2047,     "5.6177910464447372116541e+306" },
158           { 1.0,    -1028,    2048,     "1.1235582092889474423308e+307" },
159           { 1.0,    -1028,    2049,     "2.2471164185778948846616e+307" },
160           { 1.0,    -1028,    2050,     "4.4942328371557897693233e+307" },
161           { 1.0,    -1028,    2051,     "8.9884656743115795386465e+307" },
162           { 0,      0,        0,        NULL }
163 };
164 
165 static void
run_test(struct ldexp_test * table)166 run_test(struct ldexp_test *table)
167 {
168           char outbuf[64];
169           size_t i;
170           double v;
171 
172           for (i = 0; table->result != NULL; table++, i++) {
173 
174                     v = ldexp(table->x, table->exp1);
175 
176                     if (table->exp2 != SKIP)
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);
ATF_TC_HEAD(ldexp_exp2,tc)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 
ATF_TC_BODY(ldexp_exp2,tc)196 ATF_TC_BODY(ldexp_exp2, tc)
197 {
198           const double n[] = { 1, 2, 3, 10, 50, 100 };
199           const double eps = DBL_EPSILON;
200           const double x = 12.0;
201           size_t i;
202 
203           for (i = 0; i < __arraycount(n); i++) {
204                     double y = ldexp(x, n[i]);
205 
206                     if (!(fabs((y - (x * exp2(n[i])))/y) <= eps)) {
207                               atf_tc_fail_nonfatal("ldexp(%.17g, %.17g) = %.17g "
208                                   "!= %.17g * exp2(%.17g) = %.17g",
209                                   x, n[i], y, x, n[i], (x * exp2(n[i])));
210                     }
211           }
212 }
213 
214 ATF_TC(ldexp_nan);
ATF_TC_HEAD(ldexp_nan,tc)215 ATF_TC_HEAD(ldexp_nan, tc)
216 {
217           atf_tc_set_md_var(tc, "descr", "Test ldexp(NaN) == NaN");
218 }
219 
ATF_TC_BODY(ldexp_nan,tc)220 ATF_TC_BODY(ldexp_nan, tc)
221 {
222           const double x = 0.0L / 0.0L;
223           double y;
224           size_t i;
225 
226           ATF_REQUIRE(isnan(x) != 0);
227 
228           for (i = 0; i < __arraycount(exps); i++) {
229                     y = ldexp(x, exps[i]);
230                     ATF_CHECK(isnan(y) != 0);
231           }
232 }
233 
234 ATF_TC(ldexp_inf_neg);
ATF_TC_HEAD(ldexp_inf_neg,tc)235 ATF_TC_HEAD(ldexp_inf_neg, tc)
236 {
237           atf_tc_set_md_var(tc, "descr", "Test ldexp(-Inf) == -Inf");
238 }
239 
ATF_TC_BODY(ldexp_inf_neg,tc)240 ATF_TC_BODY(ldexp_inf_neg, tc)
241 {
242           const double x = -1.0L / 0.0L;
243           size_t i;
244 
245           for (i = 0; i < __arraycount(exps); i++)
246                     ATF_CHECK(ldexp(x, exps[i]) == x);
247 }
248 
249 ATF_TC(ldexp_inf_pos);
ATF_TC_HEAD(ldexp_inf_pos,tc)250 ATF_TC_HEAD(ldexp_inf_pos, tc)
251 {
252           atf_tc_set_md_var(tc, "descr", "Test ldexp(+Inf) == +Inf");
253 }
254 
ATF_TC_BODY(ldexp_inf_pos,tc)255 ATF_TC_BODY(ldexp_inf_pos, tc)
256 {
257           const double x = 1.0L / 0.0L;
258           size_t i;
259 
260           for (i = 0; i < __arraycount(exps); i++)
261                     ATF_CHECK(ldexp(x, exps[i]) == x);
262 }
263 
264 ATF_TC(ldexp_zero_neg);
ATF_TC_HEAD(ldexp_zero_neg,tc)265 ATF_TC_HEAD(ldexp_zero_neg, tc)
266 {
267           atf_tc_set_md_var(tc, "descr", "Test ldexp(-0.0) == -0.0");
268 }
269 
ATF_TC_BODY(ldexp_zero_neg,tc)270 ATF_TC_BODY(ldexp_zero_neg, tc)
271 {
272           const double x = -0.0L;
273           double y;
274           size_t i;
275 
276           ATF_REQUIRE(signbit(x) != 0);
277 
278           for (i = 0; i < __arraycount(exps); i++) {
279                     y = ldexp(x, exps[i]);
280                     ATF_CHECK(x == y);
281                     ATF_CHECK(signbit(y) != 0);
282           }
283 }
284 
285 ATF_TC(ldexp_zero_pos);
ATF_TC_HEAD(ldexp_zero_pos,tc)286 ATF_TC_HEAD(ldexp_zero_pos, tc)
287 {
288           atf_tc_set_md_var(tc, "descr", "Test ldexp(+0.0) == +0.0");
289 }
290 
ATF_TC_BODY(ldexp_zero_pos,tc)291 ATF_TC_BODY(ldexp_zero_pos, tc)
292 {
293           const double x = 0.0L;
294           double y;
295           size_t i;
296 
297           ATF_REQUIRE(signbit(x) == 0);
298 
299           for (i = 0; i < __arraycount(exps); i++) {
300                     y = ldexp(x, exps[i]);
301                     ATF_CHECK(x == y);
302                     ATF_CHECK(signbit(y) == 0);
303           }
304 }
305 
306 /*
307  * ldexpf(3)
308  */
309 
310 ATF_TC(ldexpf_exp2f);
ATF_TC_HEAD(ldexpf_exp2f,tc)311 ATF_TC_HEAD(ldexpf_exp2f, tc)
312 {
313           atf_tc_set_md_var(tc, "descr", "Test ldexpf(x, n) == x * exp2f(n)");
314 }
315 
ATF_TC_BODY(ldexpf_exp2f,tc)316 ATF_TC_BODY(ldexpf_exp2f, tc)
317 {
318           const float n[] = { 1, 2, 3, 10, 50, 100 };
319           const float eps = FLT_EPSILON;
320           const float x = 12.0;
321           size_t i;
322 
323           for (i = 0; i < __arraycount(n); i++) {
324                     float y = ldexpf(x, n[i]);
325 
326                     if (!(fabsf((y - (x * exp2f(n[i])))/y) <= eps)) {
327                               atf_tc_fail_nonfatal("ldexpf(%.17g, %.17g) = %.17g "
328                                   "!= %.17g * exp2f(%.17g) = %.17g",
329                                   x, n[i], y, x, n[i], (x * exp2f(n[i])));
330                     }
331           }
332 }
333 
334 ATF_TC(ldexpf_nan);
ATF_TC_HEAD(ldexpf_nan,tc)335 ATF_TC_HEAD(ldexpf_nan, tc)
336 {
337           atf_tc_set_md_var(tc, "descr", "Test ldexpf(NaN) == NaN");
338 }
339 
ATF_TC_BODY(ldexpf_nan,tc)340 ATF_TC_BODY(ldexpf_nan, tc)
341 {
342           const float x = 0.0L / 0.0L;
343           float y;
344           size_t i;
345 
346           ATF_REQUIRE(isnan(x) != 0);
347 
348           for (i = 0; i < __arraycount(exps); i++) {
349                     y = ldexpf(x, exps[i]);
350                     ATF_CHECK(isnan(y) != 0);
351           }
352 }
353 
354 ATF_TC(ldexpf_inf_neg);
ATF_TC_HEAD(ldexpf_inf_neg,tc)355 ATF_TC_HEAD(ldexpf_inf_neg, tc)
356 {
357           atf_tc_set_md_var(tc, "descr", "Test ldexpf(-Inf) == -Inf");
358 }
359 
ATF_TC_BODY(ldexpf_inf_neg,tc)360 ATF_TC_BODY(ldexpf_inf_neg, tc)
361 {
362           const float x = -1.0L / 0.0L;
363           size_t i;
364 
365           for (i = 0; i < __arraycount(exps); i++)
366                     ATF_CHECK(ldexpf(x, exps[i]) == x);
367 }
368 
369 ATF_TC(ldexpf_inf_pos);
ATF_TC_HEAD(ldexpf_inf_pos,tc)370 ATF_TC_HEAD(ldexpf_inf_pos, tc)
371 {
372           atf_tc_set_md_var(tc, "descr", "Test ldexpf(+Inf) == +Inf");
373 }
374 
ATF_TC_BODY(ldexpf_inf_pos,tc)375 ATF_TC_BODY(ldexpf_inf_pos, tc)
376 {
377           const float x = 1.0L / 0.0L;
378           size_t i;
379 
380           for (i = 0; i < __arraycount(exps); i++)
381                     ATF_CHECK(ldexpf(x, exps[i]) == x);
382 }
383 
384 ATF_TC(ldexpf_zero_neg);
ATF_TC_HEAD(ldexpf_zero_neg,tc)385 ATF_TC_HEAD(ldexpf_zero_neg, tc)
386 {
387           atf_tc_set_md_var(tc, "descr", "Test ldexpf(-0.0) == -0.0");
388 }
389 
ATF_TC_BODY(ldexpf_zero_neg,tc)390 ATF_TC_BODY(ldexpf_zero_neg, tc)
391 {
392           const float x = -0.0L;
393           float y;
394           size_t i;
395 
396           ATF_REQUIRE(signbit(x) != 0);
397 
398           for (i = 0; i < __arraycount(exps); i++) {
399                     y = ldexpf(x, exps[i]);
400                     ATF_CHECK(x == y);
401                     ATF_CHECK(signbit(y) != 0);
402           }
403 }
404 
405 ATF_TC(ldexpf_zero_pos);
ATF_TC_HEAD(ldexpf_zero_pos,tc)406 ATF_TC_HEAD(ldexpf_zero_pos, tc)
407 {
408           atf_tc_set_md_var(tc, "descr", "Test ldexpf(+0.0) == +0.0");
409 }
410 
ATF_TC_BODY(ldexpf_zero_pos,tc)411 ATF_TC_BODY(ldexpf_zero_pos, tc)
412 {
413           const float x = 0.0L;
414           float y;
415           size_t i;
416 
417           ATF_REQUIRE(signbit(x) == 0);
418 
419           for (i = 0; i < __arraycount(exps); i++) {
420                     y = ldexpf(x, exps[i]);
421                     ATF_CHECK(x == y);
422                     ATF_CHECK(signbit(y) == 0);
423           }
424 }
425 
426 #define TEST(name, desc)                                                        \
427           ATF_TC(name);                                                                   \
428           ATF_TC_HEAD(name, tc)                                                           \
429           {                                                                               \
430                                                                                           \
431                     atf_tc_set_md_var(tc, "descr",                                        \
432                         "Test ldexp(3) for " ___STRING(desc));                  \
433           }                                                                               \
434           ATF_TC_BODY(name, tc)                                                           \
435           {                                                                               \
436                     if (strcmp("vax", MACHINE_ARCH) == 0)                       \
437                               atf_tc_skip("Test not valid for " MACHINE_ARCH); \
438                     run_test(name);                                                       \
439           }
440 
TEST(ldexp_basic,basics)441 TEST(ldexp_basic, basics)
442 TEST(ldexp_zero, zero)
443 TEST(ldexp_infinity, infinity)
444 TEST(ldexp_overflow, overflow)
445 TEST(ldexp_denormal, denormal)
446 TEST(ldexp_denormal_large, large)
447 TEST(ldexp_underflow, underflow)
448 
449 ATF_TP_ADD_TCS(tp)
450 {
451 
452           ATF_TP_ADD_TC(tp, ldexp_basic);
453           ATF_TP_ADD_TC(tp, ldexp_zero);
454           ATF_TP_ADD_TC(tp, ldexp_infinity);
455           ATF_TP_ADD_TC(tp, ldexp_overflow);
456           ATF_TP_ADD_TC(tp, ldexp_denormal);
457           ATF_TP_ADD_TC(tp, ldexp_underflow);
458           ATF_TP_ADD_TC(tp, ldexp_denormal_large);
459 
460           ATF_TP_ADD_TC(tp, ldexp_exp2);
461           ATF_TP_ADD_TC(tp, ldexp_nan);
462           ATF_TP_ADD_TC(tp, ldexp_inf_neg);
463           ATF_TP_ADD_TC(tp, ldexp_inf_pos);
464           ATF_TP_ADD_TC(tp, ldexp_zero_neg);
465           ATF_TP_ADD_TC(tp, ldexp_zero_pos);
466 
467           ATF_TP_ADD_TC(tp, ldexpf_exp2f);
468           ATF_TP_ADD_TC(tp, ldexpf_nan);
469           ATF_TP_ADD_TC(tp, ldexpf_inf_neg);
470           ATF_TP_ADD_TC(tp, ldexpf_inf_pos);
471           ATF_TP_ADD_TC(tp, ldexpf_zero_neg);
472           ATF_TP_ADD_TC(tp, ldexpf_zero_pos);
473 
474           return atf_no_error();
475 }
476