1 /* $NetBSD: t_log.c,v 1.19 2024/07/17 14:52:13 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_log.c,v 1.19 2024/07/17 14:52:13 riastradh Exp $");
33 
34 #include <sys/types.h>
35 
36 #include <atf-c.h>
37 
38 #include <errno.h>
39 #include <float.h>
40 #include <math.h>
41 #include <stdio.h>
42 #include <string.h>
43 
44 #define   CHECK_EQ(i, f, x, y)                                                                  \
45           ATF_CHECK_EQ_MSG(f(x), y,                                                   \
46               "[%u] %s(%a=%.17g)=%a=%.17g, expected %a=%.17g",                        \
47               (i), #f, (double)(x), (double)(x), f(x), f(x),                          \
48               (double)(y), (double)(y))
49 
50 #define   CHECKL_EQ(i, f, x, y)                                                                 \
51           ATF_CHECK_EQ_MSG(f(x), y,                                                   \
52               "[%u] %s(%La=%.34Lg)=%La=%.34Lg, expected %La=%.34Lg",        \
53               (i), #f, (long double)(x), (long double)(x), f(x), f(x),                \
54               (long double)(y), (long double)(y))
55 
56 #ifdef NAN
57 
58 #define   CHECK_NAN(i, f, x)                                                          \
59           ATF_CHECK_MSG(isnan(f(x)),                                                  \
60               "[%u] %s(%a=%.17g)=%a=%.17g, expected NaN",                             \
61               (i), #f, (x), (x), f(x), f(x))
62 
63 #define   CHECKL_NAN(i, f, x)                                                         \
64           ATF_CHECK_MSG(isnan(f(x)),                                                  \
65               "[%u] %s(%La=%.34Lg)=%La=%.34Lg, expected NaN",                         \
66               (i), #f, (long double)(x), (long double)(x), f(x), f(x))
67 
68 #else  /* !defined(NAN) */
69 
70 #define   CHECK_NAN(i, f, x) do                                                                 \
71 {                                                                                               \
72           int _checknan_error;                                                                  \
73           double _checknan_result;                                                    \
74           errno = 0;                                                                            \
75           _checknan_result = f(x);                                                    \
76           _checknan_error = errno;                                                    \
77           ATF_CHECK_EQ_MSG(errno, EDOM,                                               \
78               "[%u] %s(%a=%.17g)=%a=%.17g errno=%d, expected EDOM=%d",                \
79               (i), #f, (double)(x), (double)(x),                                      \
80               _checknan_result, _checknan_result,                                     \
81               _checknan_error, EDOM);                                                 \
82 } while (0)
83 
84 #define   CHECKL_NAN(i, f, x) do                                                                \
85 {                                                                                               \
86           int _checknan_error;                                                                  \
87           long double _checknan_result;                                               \
88           errno = 0;                                                                            \
89           _checknan_result = f(x);                                                    \
90           _checknan_error = errno;                                                    \
91           ATF_CHECK_EQ_MSG(errno, EDOM,                                               \
92               "[%u] %s(%La=%.34Lg)=%La=%.34Lg errno=%d, expected EDOM=%d",      \
93               (i), #f, (long double)(x), (long double)(x),                  \
94               _checknan_result, _checknan_result,                                     \
95               _checknan_error, EDOM);                                                 \
96 } while (0)
97 
98 #endif    /* NAN */
99 
100 static const float logf_invalid[] = {
101 #ifdef NAN
102           NAN,
103 #endif
104           -HUGE_VALF,
105           -FLT_MAX,
106           -10,
107           -1,
108           -FLT_EPSILON,
109           -FLT_MIN,
110 #ifdef FLT_DENORM_MIN
111           -FLT_DENORM_MIN,
112 #endif
113 };
114 
115 static const double log_invalid[] = {
116 #ifdef NAN
117           NAN,
118 #endif
119           -HUGE_VAL,
120           -DBL_MAX,
121           -10,
122           -1,
123           -DBL_EPSILON,
124           -DBL_MIN,
125 #ifdef DBL_DENORM_MIN
126           -DBL_DENORM_MIN,
127 #endif
128 };
129 
130 static const long double logl_invalid[] = {
131 #ifdef NAN
132           NAN,
133 #endif
134           -HUGE_VALL,
135           -LDBL_MAX,
136           -10,
137           -1,
138           -LDBL_EPSILON,
139           -LDBL_MIN,
140 #ifdef LDBL_DENORM_MIN
141           -LDBL_DENORM_MIN,
142 #endif
143 };
144 
145 static const float log1pf_invalid[] = {
146 #ifdef NAN
147           NAN,
148 #endif
149           -HUGE_VALF,
150           -FLT_MAX,
151           -10,
152           -1 - FLT_EPSILON,
153 };
154 
155 static const double log1p_invalid[] = {
156 #ifdef NAN
157           NAN,
158 #endif
159           -HUGE_VAL,
160           -DBL_MAX,
161           -10,
162           -1 - DBL_EPSILON,
163 };
164 
165 static const long double log1pl_invalid[] = {
166 #ifdef NAN
167           NAN,
168 #endif
169           -HUGE_VALL,
170           -LDBL_MAX,
171           -10,
172           -1 - LDBL_EPSILON,
173 };
174 
175 /*
176  * log10(3)
177  */
178 static const struct {
179           float x, y;
180 } log10f_exact[] = {
181           { 1, 0 },
182           { 10, 1 },
183           { 100, 2 },
184 };
185 
186 ATF_TC(log10_invalid);
ATF_TC_HEAD(log10_invalid,tc)187 ATF_TC_HEAD(log10_invalid, tc)
188 {
189           atf_tc_set_md_var(tc, "descr", "Test log10/f/l on invalid inputs");
190 }
ATF_TC_BODY(log10_invalid,tc)191 ATF_TC_BODY(log10_invalid, tc)
192 {
193           unsigned i;
194 
195           for (i = 0; i < __arraycount(logf_invalid); i++) {
196                     CHECK_NAN(i, log10f, logf_invalid[i]);
197                     CHECK_NAN(i, log10, logf_invalid[i]);
198                     CHECKL_NAN(i, log10l, logf_invalid[i]);
199           }
200 
201           for (i = 0; i < __arraycount(log_invalid); i++) {
202                     CHECK_NAN(i, log10, log_invalid[i]);
203                     CHECKL_NAN(i, log10l, log_invalid[i]);
204           }
205 
206           for (i = 0; i < __arraycount(logl_invalid); i++) {
207                     CHECKL_NAN(i, log10l, logl_invalid[i]);
208           }
209 }
210 
211 ATF_TC(log10_zero);
ATF_TC_HEAD(log10_zero,tc)212 ATF_TC_HEAD(log10_zero, tc)
213 {
214           atf_tc_set_md_var(tc, "descr", "Test log10/f/l on zero");
215 }
ATF_TC_BODY(log10_zero,tc)216 ATF_TC_BODY(log10_zero, tc)
217 {
218 
219           CHECK_EQ(0, log10f, +0., -HUGE_VALF);
220           CHECK_EQ(0, log10, +0., -HUGE_VAL);
221           CHECKL_EQ(0, log10l, +0., -HUGE_VALL);
222 
223           CHECK_EQ(1, log10f, -0., -HUGE_VALF);
224           CHECK_EQ(1, log10, -0., -HUGE_VAL);
225           CHECKL_EQ(1, log10l, -0., -HUGE_VALL);
226 }
227 
228 ATF_TC(log10_exact);
ATF_TC_HEAD(log10_exact,tc)229 ATF_TC_HEAD(log10_exact, tc)
230 {
231           atf_tc_set_md_var(tc, "descr", "Test log10/f/l exact cases");
232 }
ATF_TC_BODY(log10_exact,tc)233 ATF_TC_BODY(log10_exact, tc)
234 {
235           unsigned i;
236 
237           ATF_CHECK_EQ(signbit(log10f(1)), 0);
238           ATF_CHECK_EQ(signbit(log10(1)), 0);
239           ATF_CHECK_EQ(signbit(log10l(1)), 0);
240 
241           for (i = 0; i < __arraycount(log10f_exact); i++) {
242                     const float x = log10f_exact[i].x;
243                     const float y = log10f_exact[i].y;
244 
245                     CHECK_EQ(i, log10f, x, y);
246                     CHECK_EQ(i, log10, x, y);
247                     CHECKL_EQ(i, log10l, x, y);
248           }
249 }
250 
251 ATF_TC(log10_approx);
ATF_TC_HEAD(log10_approx,tc)252 ATF_TC_HEAD(log10_approx, tc)
253 {
254           atf_tc_set_md_var(tc, "descr", "Test log10/f/l approximate cases");
255 }
ATF_TC_BODY(log10_approx,tc)256 ATF_TC_BODY(log10_approx, tc)
257 {
258           volatile long double e =
259               2.7182818284590452353602874713526624977572470937L;
260           volatile long double e2 =
261               7.3890560989306502272304274605750078131803155705519L;
262           volatile long double log10e =
263               0.43429448190325182765112891891660508229439700580367L;
264           volatile long double log10e2 =
265               2*0.43429448190325182765112891891660508229439700580367L;
266 
267           ATF_CHECK_MSG((fabsf((log10f(e) - (float)log10e)/(float)log10e) <
268                     2*FLT_EPSILON),
269               "log10f(e)=%a=%.8g expected %a=%.8g",
270               log10f(e), log10f(e), (float)log10e, (float)log10e);
271           ATF_CHECK_MSG((fabs((log10(e) - (double)log10e)/(double)log10e) <
272                     2*DBL_EPSILON),
273               "log10(e)=%a=%.17g expected %a=%.17g",
274               log10(e), log10(e), (double)log10e, (double)log10e);
275           ATF_CHECK_MSG((fabsl((log10l(e) - log10e)/log10e) < 2*LDBL_EPSILON),
276               "log10l(e)=%La=%.34Lg expected %La=%.34Lg",
277               log10l(e), log10l(e), log10e, log10e);
278 
279           ATF_CHECK_MSG((fabsf((log10f(e2) - (float)log10e2)/(float)log10e2) <
280                     2*FLT_EPSILON),
281               "log10f(e^2)=%a=%.8g expected %a=%.8g",
282               log10f(e2), log10f(e2), (float)log10e2, (float)log10e2);
283           ATF_CHECK_MSG((fabs((log10(e2) - (double)log10e2)/(double)log10e2) <
284                     2*DBL_EPSILON),
285               "log10(e^2)=%a=%.17g expected %a=%.17g",
286               log10(e2), log10(e2), (double)log10e2, (double)log10e2);
287           ATF_CHECK_MSG((fabsl((log10l(e2) - log10e2)/log10e2) < 2*LDBL_EPSILON),
288               "log10l(e^2)=%La=%.34Lg expected %La=%.34Lg",
289               log10l(e2), log10l(e2), log10e2, log10e2);
290 }
291 
292 ATF_TC(log10_inf);
ATF_TC_HEAD(log10_inf,tc)293 ATF_TC_HEAD(log10_inf, tc)
294 {
295           atf_tc_set_md_var(tc, "descr", "Test log10/f/l on +infinity");
296 }
ATF_TC_BODY(log10_inf,tc)297 ATF_TC_BODY(log10_inf, tc)
298 {
299 
300           if (!isinf(INFINITY))
301                     atf_tc_skip("no infinities on this architecture");
302 
303           CHECK_EQ(0, log10f, INFINITY, INFINITY);
304           CHECK_EQ(0, log10, INFINITY, INFINITY);
305           CHECKL_EQ(0, log10l, INFINITY, INFINITY);
306 }
307 
308 /*
309  * log1p(3)
310  */
311 
312 ATF_TC(log1p_invalid);
ATF_TC_HEAD(log1p_invalid,tc)313 ATF_TC_HEAD(log1p_invalid, tc)
314 {
315           atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on invalid inputs");
316 }
ATF_TC_BODY(log1p_invalid,tc)317 ATF_TC_BODY(log1p_invalid, tc)
318 {
319           unsigned i;
320 
321           for (i = 0; i < __arraycount(log1pf_invalid); i++) {
322                     CHECK_NAN(i, log1pf, log1pf_invalid[i]);
323                     CHECK_NAN(i, log1p, log1pf_invalid[i]);
324                     CHECKL_NAN(i, log1pl, log1pf_invalid[i]);
325           }
326 
327           for (i = 0; i < __arraycount(log1p_invalid); i++) {
328                     CHECK_NAN(i, log1p, log1p_invalid[i]);
329                     CHECKL_NAN(i, log1pl, log1p_invalid[i]);
330           }
331 
332           for (i = 0; i < __arraycount(log1pl_invalid); i++) {
333                     CHECKL_NAN(i, log1pl, log1pl_invalid[i]);
334           }
335 }
336 
337 ATF_TC(log1p_neg_one);
ATF_TC_HEAD(log1p_neg_one,tc)338 ATF_TC_HEAD(log1p_neg_one, tc)
339 {
340           atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on -1");
341 }
ATF_TC_BODY(log1p_neg_one,tc)342 ATF_TC_BODY(log1p_neg_one, tc)
343 {
344 
345           CHECK_EQ(0, log1pf, -1., -HUGE_VALF);
346           CHECK_EQ(0, log1p, -1., -HUGE_VAL);
347           CHECKL_EQ(0, log1pl, -1., -HUGE_VALL);
348 }
349 
350 ATF_TC(log1p_exact);
ATF_TC_HEAD(log1p_exact,tc)351 ATF_TC_HEAD(log1p_exact, tc)
352 {
353           atf_tc_set_md_var(tc, "descr", "Test log1p/f/l exact cases");
354 }
ATF_TC_BODY(log1p_exact,tc)355 ATF_TC_BODY(log1p_exact, tc)
356 {
357 
358           CHECK_EQ(0, log1pf, -FLT_MIN, -FLT_MIN);
359           CHECK_EQ(0, log1p, -DBL_MIN, -DBL_MIN);
360           CHECKL_EQ(01, log1pl, -LDBL_MIN, -LDBL_MIN);
361 
362           CHECK_EQ(1, log1pf, -0., 0);
363           CHECK_EQ(1, log1p, -0., 0);
364           CHECKL_EQ(1, log1pl, -0., 0);
365 
366           CHECK_EQ(2, log1pf, +0., 0);
367           CHECK_EQ(2, log1p, +0., 0);
368           CHECKL_EQ(2, log1pl, +0., 0);
369 
370 #ifdef __i386__
371           atf_tc_expect_fail("PR port-i386/58434: single-float functions"
372               " sometimes return surprisingly much precision");
373 #endif
374           CHECK_EQ(3, log1pf, 1, logf(2));
375 #ifdef __i386__
376           atf_tc_expect_pass();
377 #endif
378           CHECK_EQ(3, log1p, 1, log(2));
379           CHECKL_EQ(3, log1pl, 1, logl(2));
380 }
381 
382 ATF_TC(log1p_approx);
ATF_TC_HEAD(log1p_approx,tc)383 ATF_TC_HEAD(log1p_approx, tc)
384 {
385           atf_tc_set_md_var(tc, "descr", "Test log1p/f/l approximate cases");
386 }
ATF_TC_BODY(log1p_approx,tc)387 ATF_TC_BODY(log1p_approx, tc)
388 {
389           volatile long double em1 =    /* exp(1) - 1 */
390               1.7182818284590452353602874713526624977572470937L;
391           volatile long double e2m1 =   /* exp(2) - 1 */
392               6.3890560989306502272304274605750078131803155705519L;
393 
394           /*
395            * Approximation is close enough that equality of the rounded
396            * output had better hold.
397            */
398 #ifdef FLT_DENORM_MIN
399           CHECK_EQ(0, log1pf, -FLT_DENORM_MIN, -FLT_DENORM_MIN);
400 #endif
401 #ifdef DBL_DENORM_MIN
402           CHECK_EQ(0, log1p, -DBL_DENORM_MIN, -DBL_DENORM_MIN);
403 #endif
404 #ifdef LDBL_DENORM_MIN
405           CHECKL_EQ(0, log1pl, -LDBL_DENORM_MIN, -LDBL_DENORM_MIN);
406 #endif
407 
408           ATF_CHECK_MSG(fabsf((log1pf(em1) - 1)/1) < 2*FLT_EPSILON,
409               "log1pf(e)=%a=%.8g", log1pf(em1), log1pf(em1));
410           ATF_CHECK_MSG(fabs((log1p(em1) - 1)/1) < 2*DBL_EPSILON,
411               "log1p(e)=%a=%.17g", log1p(em1), log1p(em1));
412           ATF_CHECK_MSG(fabsl((log1pl(em1) - 1)/1) < 2*LDBL_EPSILON,
413               "log1pl(e)=%La=%.34Lg", log1pl(em1), log1pl(em1));
414 
415           ATF_CHECK_MSG(fabsf((log1pf(e2m1) - 2)/2) < 2*FLT_EPSILON,
416               "log1pf(e^2)=%a=%.8g", log1pf(em1), log1pf(em1));
417           ATF_CHECK_MSG(fabs((log1p(e2m1) - 2)/2) < 2*DBL_EPSILON,
418               "log1p(e^2)=%a=%.17g", log1p(em1), log1p(em1));
419           ATF_CHECK_MSG(fabsl((log1pl(e2m1) - 2)/2) < 2*LDBL_EPSILON,
420               "log1pl(e^2)=%La=%.34Lg", log1pl(em1), log1pl(em1));
421 }
422 
423 ATF_TC(log1p_inf);
ATF_TC_HEAD(log1p_inf,tc)424 ATF_TC_HEAD(log1p_inf, tc)
425 {
426           atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on +infinity");
427 }
ATF_TC_BODY(log1p_inf,tc)428 ATF_TC_BODY(log1p_inf, tc)
429 {
430 
431           if (!isinf(INFINITY))
432                     atf_tc_skip("no infinities on this architecture");
433 
434           CHECK_EQ(0, log1pf, INFINITY, INFINITY);
435           CHECK_EQ(0, log1p, INFINITY, INFINITY);
436           CHECKL_EQ(0, log1pl, INFINITY, INFINITY);
437 }
438 
439 /*
440  * log2(3)
441  */
442 static const struct {
443           float x, y;
444 } log2f_exact[] = {
445 #ifdef FLT_DENORM_MIN
446           { FLT_DENORM_MIN, FLT_MIN_EXP - FLT_MANT_DIG },
447 #endif
448           { FLT_MIN, FLT_MIN_EXP - 1 },
449           { 0.25, -2 },
450           { 0.5, -1 },
451           { 1, 0 },
452           { 2, 1 },
453           { 4, 2 },
454           { 8, 3 },
455           { 1 << FLT_MANT_DIG, FLT_MANT_DIG },
456           { (float)(1 << FLT_MANT_DIG) * (1 << FLT_MANT_DIG),
457             2*FLT_MANT_DIG },
458 };
459 static const struct {
460           double x, y;
461 } log2_exact[] = {
462 #ifdef DBL_DENORM_MIN
463           { DBL_DENORM_MIN, DBL_MIN_EXP - DBL_MANT_DIG },
464 #endif
465           { DBL_MIN, DBL_MIN_EXP - 1 },
466           { (uint64_t)1 << DBL_MANT_DIG, DBL_MANT_DIG },
467           { ((double)((uint64_t)1 << DBL_MANT_DIG) *
468                         ((uint64_t)1 << DBL_MANT_DIG)),
469             2*DBL_MANT_DIG },
470 };
471 
472 static const struct {
473           long double x, y;
474 } log2l_exact[] = {
475 #ifdef LDBL_DENORM_MIN
476           { LDBL_DENORM_MIN, LDBL_MIN_EXP - LDBL_MANT_DIG },
477 #endif
478           { LDBL_MIN, LDBL_MIN_EXP - 1 },
479           { ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
480                         ((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))),
481             LDBL_MANT_DIG },
482           { (((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
483                               ((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))) *
484                         ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
485                               ((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2)))),
486             2*LDBL_MANT_DIG },
487 };
488 
489 ATF_TC(log2_invalid);
ATF_TC_HEAD(log2_invalid,tc)490 ATF_TC_HEAD(log2_invalid, tc)
491 {
492           atf_tc_set_md_var(tc, "descr", "Test log2/f/l on invalid inputs");
493 }
ATF_TC_BODY(log2_invalid,tc)494 ATF_TC_BODY(log2_invalid, tc)
495 {
496           unsigned i;
497 
498           for (i = 0; i < __arraycount(logf_invalid); i++) {
499                     CHECK_NAN(i, log2f, logf_invalid[i]);
500                     CHECK_NAN(i, log2, logf_invalid[i]);
501                     CHECKL_NAN(i, log2l, logf_invalid[i]);
502           }
503 
504           for (i = 0; i < __arraycount(log_invalid); i++) {
505                     CHECK_NAN(i, log2, log_invalid[i]);
506                     CHECKL_NAN(i, log2l, log_invalid[i]);
507           }
508 
509           for (i = 0; i < __arraycount(logl_invalid); i++) {
510                     CHECKL_NAN(i, log2l, logl_invalid[i]);
511           }
512 }
513 
514 ATF_TC(log2_zero);
ATF_TC_HEAD(log2_zero,tc)515 ATF_TC_HEAD(log2_zero, tc)
516 {
517           atf_tc_set_md_var(tc, "descr", "Test log2/f/l on zero");
518 }
ATF_TC_BODY(log2_zero,tc)519 ATF_TC_BODY(log2_zero, tc)
520 {
521 
522           CHECK_EQ(0, log2f, +0., -HUGE_VALF);
523           CHECK_EQ(0, log2, +0., -HUGE_VAL);
524           CHECKL_EQ(0, log2l, +0., -HUGE_VALL);
525 
526           CHECK_EQ(1, log2f, -0., -HUGE_VALF);
527           CHECK_EQ(1, log2, -0., -HUGE_VAL);
528           CHECKL_EQ(1, log2l, -0., -HUGE_VALL);
529 }
530 
531 ATF_TC(log2_exact);
ATF_TC_HEAD(log2_exact,tc)532 ATF_TC_HEAD(log2_exact, tc)
533 {
534           atf_tc_set_md_var(tc, "descr", "Test log2/f/l exact cases");
535 }
ATF_TC_BODY(log2_exact,tc)536 ATF_TC_BODY(log2_exact, tc)
537 {
538           unsigned i;
539 
540           ATF_CHECK_EQ(signbit(log2f(1)), 0);
541           ATF_CHECK_EQ(signbit(log2(1)), 0);
542           ATF_CHECK_EQ(signbit(log2l(1)), 0);
543 
544           for (i = 0; i < __arraycount(log2f_exact); i++) {
545                     const float x = log2f_exact[i].x;
546                     const float y = log2f_exact[i].y;
547 
548                     CHECK_EQ(i, log2f, x, y);
549                     CHECK_EQ(i, log2, x, y);
550                     CHECKL_EQ(i, log2l, x, y);
551           }
552 
553           for (i = 0; i < __arraycount(log2_exact); i++) {
554                     const double x = log2_exact[i].x;
555                     const double y = log2_exact[i].y;
556 
557                     CHECK_EQ(i, log2, x, y);
558                     CHECKL_EQ(i, log2l, x, y);
559           }
560 
561           for (i = 0; i < __arraycount(log2l_exact); i++) {
562                     const long double x = log2l_exact[i].x;
563                     const long double y = log2l_exact[i].y;
564 
565                     CHECKL_EQ(i, log2l, x, y);
566           }
567 }
568 
569 ATF_TC(log2_approx);
ATF_TC_HEAD(log2_approx,tc)570 ATF_TC_HEAD(log2_approx, tc)
571 {
572           atf_tc_set_md_var(tc, "descr", "Test log2/f/l approximate cases");
573 }
ATF_TC_BODY(log2_approx,tc)574 ATF_TC_BODY(log2_approx, tc)
575 {
576           volatile long double e =
577               2.7182818284590452353602874713526624977572470937L;
578           volatile long double e2 =
579               7.3890560989306502272304274605750078131803155705519L;
580           volatile long double log2e =
581               1.442695040888963407359924681001892137426645954153L;
582           volatile long double log2e2 =
583               2*1.442695040888963407359924681001892137426645954153L;
584 
585           ATF_CHECK_MSG((fabsf((log2f(e) - (float)log2e)/(float)log2e) <
586                     2*FLT_EPSILON),
587               "log2f(e)=%a=%.8g expected %a=%.8g",
588               log2f(e), log2f(e), (float)log2e, (float)log2e);
589           ATF_CHECK_MSG((fabs((log2(e) - (double)log2e)/(double)log2e) <
590                     2*DBL_EPSILON),
591               "log2(e)=%a=%.17g expected %a=%.17g",
592               log2(e), log2(e), (double)log2e, (double)log2e);
593           ATF_CHECK_MSG((fabsl((log2l(e) - log2e)/log2e) < 2*LDBL_EPSILON),
594               "log2l(e)=%La=%.34Lg expected %La=%.34Lg",
595               log2l(e), log2l(e), log2e, log2e);
596 
597           ATF_CHECK_MSG((fabsf((log2f(e2) - (float)log2e2)/(float)log2e2) <
598                     2*FLT_EPSILON),
599               "log2f(e^2)=%a=%.8g expected %a=%.8g",
600               log2f(e2), log2f(e2), (float)log2e2, (float)log2e2);
601           ATF_CHECK_MSG((fabs((log2(e2) - (double)log2e2)/(double)log2e2) <
602                     2*DBL_EPSILON),
603               "log2(e^2)=%a=%.17g expected %a=%.17g",
604               log2(e2), log2(e2), (double)log2e2, (double)log2e2);
605           ATF_CHECK_MSG((fabsl((log2l(e2) - log2e2)/log2e2) < 2*LDBL_EPSILON),
606               "log2l(e^2)=%La=%.34Lg expected %La=%.34Lg",
607               log2l(e2), log2l(e2), log2e2, log2e2);
608 }
609 
610 ATF_TC(log2_inf);
ATF_TC_HEAD(log2_inf,tc)611 ATF_TC_HEAD(log2_inf, tc)
612 {
613           atf_tc_set_md_var(tc, "descr", "Test log2/f/l on +infinity");
614 }
ATF_TC_BODY(log2_inf,tc)615 ATF_TC_BODY(log2_inf, tc)
616 {
617 
618           if (!isinf(INFINITY))
619                     atf_tc_skip("no infinities on this architecture");
620 
621           CHECK_EQ(0, log2f, INFINITY, INFINITY);
622           CHECK_EQ(0, log2, INFINITY, INFINITY);
623           CHECKL_EQ(0, log2l, INFINITY, INFINITY);
624 }
625 
626 /*
627  * log(3)
628  */
629 
630 ATF_TC(log_invalid);
ATF_TC_HEAD(log_invalid,tc)631 ATF_TC_HEAD(log_invalid, tc)
632 {
633           atf_tc_set_md_var(tc, "descr", "Test log/f/l on invalid inputs");
634 }
ATF_TC_BODY(log_invalid,tc)635 ATF_TC_BODY(log_invalid, tc)
636 {
637           unsigned i;
638 
639           for (i = 0; i < __arraycount(logf_invalid); i++) {
640                     CHECK_NAN(i, logf, logf_invalid[i]);
641                     CHECK_NAN(i, log, logf_invalid[i]);
642                     CHECKL_NAN(i, logl, logf_invalid[i]);
643           }
644 
645           for (i = 0; i < __arraycount(log_invalid); i++) {
646                     CHECK_NAN(i, log, log_invalid[i]);
647                     CHECKL_NAN(i, logl, log_invalid[i]);
648           }
649 
650           for (i = 0; i < __arraycount(logl_invalid); i++) {
651                     CHECKL_NAN(i, logl, logl_invalid[i]);
652           }
653 }
654 
655 ATF_TC(log_zero);
ATF_TC_HEAD(log_zero,tc)656 ATF_TC_HEAD(log_zero, tc)
657 {
658           atf_tc_set_md_var(tc, "descr", "Test log/f/l on zero");
659 }
ATF_TC_BODY(log_zero,tc)660 ATF_TC_BODY(log_zero, tc)
661 {
662 
663           CHECK_EQ(0, logf, +0., -HUGE_VALF);
664           CHECK_EQ(0, log, +0., -HUGE_VAL);
665           CHECKL_EQ(0, logl, +0., -HUGE_VALL);
666 
667           CHECK_EQ(1, logf, -0., -HUGE_VALF);
668           CHECK_EQ(1, log, -0., -HUGE_VAL);
669           CHECKL_EQ(1, logl, -0., -HUGE_VALL);
670 }
671 
672 ATF_TC(log_exact);
ATF_TC_HEAD(log_exact,tc)673 ATF_TC_HEAD(log_exact, tc)
674 {
675           atf_tc_set_md_var(tc, "descr", "Test log/f/l exact cases");
676 }
ATF_TC_BODY(log_exact,tc)677 ATF_TC_BODY(log_exact, tc)
678 {
679 
680           CHECK_EQ(0, logf, 1, 0);
681           CHECK_EQ(0, log, 1, 0);
682           CHECKL_EQ(0, logl, 1, 0);
683 
684           ATF_CHECK_EQ(signbit(logf(1)), 0);
685           ATF_CHECK_EQ(signbit(log(1)), 0);
686           ATF_CHECK_EQ(signbit(logl(1)), 0);
687 }
688 
689 ATF_TC(log_approx);
ATF_TC_HEAD(log_approx,tc)690 ATF_TC_HEAD(log_approx, tc)
691 {
692           atf_tc_set_md_var(tc, "descr", "Test log/f/l approximate cases");
693 }
ATF_TC_BODY(log_approx,tc)694 ATF_TC_BODY(log_approx, tc)
695 {
696           volatile long double e =
697               2.7182818284590452353602874713526624977572470937L;
698           volatile long double e2 =
699               7.3890560989306502272304274605750078131803155705519L;
700           volatile long double log_2 =
701               0.69314718055994530941723212145817656807550013436025L;
702           volatile long double log_10 =
703               2.30258509299404568401799145468436420760110148862875L;
704 
705           ATF_CHECK_MSG(fabsf((logf(2) - log_2)/log_2) < 2*FLT_EPSILON,
706               "logf(2)=%a=%.8g expected %a=%.8g",
707               logf(2), logf(2), (float)log_2, (float)log_2);
708           ATF_CHECK_MSG(fabs((log(2) - log_2)/log_2) < 2*DBL_EPSILON,
709               "log(2)=%a=%.17g expected %a=%.17g",
710               log(2), log(2), (double)log_2, (double)log_2);
711           ATF_CHECK_MSG(fabsl((logl(2) - log_2)/log_2) < 2*LDBL_EPSILON,
712               "logl(2)=%La=%.34Lg expected %La=%.34Lg",
713               logl(2), logl(2), log_2, log_2);
714 
715           ATF_CHECK_MSG(fabsf((logf(e) - 1)/1) < 2*FLT_EPSILON,
716               "logf(e)=%a=%.8g", logf(e), logf(e));
717           ATF_CHECK_MSG(fabs((log(e) - 1)/1) < 2*DBL_EPSILON,
718               "log(e)=%a=%.17g", log(e), log(e));
719           ATF_CHECK_MSG(fabsl((logl(e) - 1)/1) < 2*LDBL_EPSILON,
720               "logl(e)=%La=%.34Lg", logl(e), logl(e));
721 
722           ATF_CHECK_MSG(fabsf((logf(e2) - 2)/2) < 2*FLT_EPSILON,
723               "logf(e)=%a=%.8g", logf(e2), logf(e2));
724           ATF_CHECK_MSG(fabs((log(e2) - 2)/2) < 2*DBL_EPSILON,
725               "log(e)=%a=%.17g", log(e2), log(e2));
726           ATF_CHECK_MSG(fabsl((logl(e2) - 2)/2) < 2*LDBL_EPSILON,
727               "logl(e)=%La=%.34Lg", logl(e2), logl(e2));
728 
729           ATF_CHECK_MSG(fabsf((logf(10) - log_10)/log_10) < 2*FLT_EPSILON,
730               "logf(10)=%a=%.8g expected %a=%.8g",
731               logf(10), logf(10), (float)log_10, (float)log_10);
732           ATF_CHECK_MSG(fabs((log(10) - log_10)/log_10) < 2*DBL_EPSILON,
733               "log(10)=%a=%.17g expected %a=%.17g",
734               log(10), log(10), (double)log_10, (double)log_10);
735           ATF_CHECK_MSG(fabsl((logl(10) - log_10)/log_10) < 2*LDBL_EPSILON,
736               "logl(10)=%La=%.34Lg expected %La=%.34Lg",
737               logl(10), logl(10), log_10, log_10);
738 }
739 
740 ATF_TC(log_inf);
ATF_TC_HEAD(log_inf,tc)741 ATF_TC_HEAD(log_inf, tc)
742 {
743           atf_tc_set_md_var(tc, "descr", "Test log/f/l on +infinity");
744 }
ATF_TC_BODY(log_inf,tc)745 ATF_TC_BODY(log_inf, tc)
746 {
747 
748           if (!isinf(INFINITY))
749                     atf_tc_skip("no infinities on this architecture");
750 
751           CHECK_EQ(0, logf, INFINITY, INFINITY);
752           CHECK_EQ(0, log, INFINITY, INFINITY);
753           CHECKL_EQ(0, logl, INFINITY, INFINITY);
754 }
755 
ATF_TP_ADD_TCS(tp)756 ATF_TP_ADD_TCS(tp)
757 {
758 
759           ATF_TP_ADD_TC(tp, log10_invalid);
760           ATF_TP_ADD_TC(tp, log10_zero);
761           ATF_TP_ADD_TC(tp, log10_exact);
762           ATF_TP_ADD_TC(tp, log10_approx);
763           ATF_TP_ADD_TC(tp, log10_inf);
764 
765           ATF_TP_ADD_TC(tp, log1p_invalid);
766           ATF_TP_ADD_TC(tp, log1p_neg_one);
767           ATF_TP_ADD_TC(tp, log1p_exact);
768           ATF_TP_ADD_TC(tp, log1p_approx);
769           ATF_TP_ADD_TC(tp, log1p_inf);
770 
771           ATF_TP_ADD_TC(tp, log2_invalid);
772           ATF_TP_ADD_TC(tp, log2_zero);
773           ATF_TP_ADD_TC(tp, log2_exact);
774           ATF_TP_ADD_TC(tp, log2_approx);
775           ATF_TP_ADD_TC(tp, log2_inf);
776 
777           ATF_TP_ADD_TC(tp, log_invalid);
778           ATF_TP_ADD_TC(tp, log_zero);
779           ATF_TP_ADD_TC(tp, log_exact);
780           ATF_TP_ADD_TC(tp, log_approx);
781           ATF_TP_ADD_TC(tp, log_inf);
782 
783           return atf_no_error();
784 }
785