t_log.c revision 1.19 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);
187 ATF_TC_HEAD(log10_invalid, tc)
188 {
189 atf_tc_set_md_var(tc, "descr", "Test log10/f/l on invalid inputs");
190 }
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);
212 ATF_TC_HEAD(log10_zero, tc)
213 {
214 atf_tc_set_md_var(tc, "descr", "Test log10/f/l on zero");
215 }
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);
229 ATF_TC_HEAD(log10_exact, tc)
230 {
231 atf_tc_set_md_var(tc, "descr", "Test log10/f/l exact cases");
232 }
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);
252 ATF_TC_HEAD(log10_approx, tc)
253 {
254 atf_tc_set_md_var(tc, "descr", "Test log10/f/l approximate cases");
255 }
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);
293 ATF_TC_HEAD(log10_inf, tc)
294 {
295 atf_tc_set_md_var(tc, "descr", "Test log10/f/l on +infinity");
296 }
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);
313 ATF_TC_HEAD(log1p_invalid, tc)
314 {
315 atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on invalid inputs");
316 }
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);
338 ATF_TC_HEAD(log1p_neg_one, tc)
339 {
340 atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on -1");
341 }
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);
351 ATF_TC_HEAD(log1p_exact, tc)
352 {
353 atf_tc_set_md_var(tc, "descr", "Test log1p/f/l exact cases");
354 }
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);
383 ATF_TC_HEAD(log1p_approx, tc)
384 {
385 atf_tc_set_md_var(tc, "descr", "Test log1p/f/l approximate cases");
386 }
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);
424 ATF_TC_HEAD(log1p_inf, tc)
425 {
426 atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on +infinity");
427 }
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);
490 ATF_TC_HEAD(log2_invalid, tc)
491 {
492 atf_tc_set_md_var(tc, "descr", "Test log2/f/l on invalid inputs");
493 }
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);
515 ATF_TC_HEAD(log2_zero, tc)
516 {
517 atf_tc_set_md_var(tc, "descr", "Test log2/f/l on zero");
518 }
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);
532 ATF_TC_HEAD(log2_exact, tc)
533 {
534 atf_tc_set_md_var(tc, "descr", "Test log2/f/l exact cases");
535 }
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);
570 ATF_TC_HEAD(log2_approx, tc)
571 {
572 atf_tc_set_md_var(tc, "descr", "Test log2/f/l approximate cases");
573 }
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);
611 ATF_TC_HEAD(log2_inf, tc)
612 {
613 atf_tc_set_md_var(tc, "descr", "Test log2/f/l on +infinity");
614 }
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);
631 ATF_TC_HEAD(log_invalid, tc)
632 {
633 atf_tc_set_md_var(tc, "descr", "Test log/f/l on invalid inputs");
634 }
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);
656 ATF_TC_HEAD(log_zero, tc)
657 {
658 atf_tc_set_md_var(tc, "descr", "Test log/f/l on zero");
659 }
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);
673 ATF_TC_HEAD(log_exact, tc)
674 {
675 atf_tc_set_md_var(tc, "descr", "Test log/f/l exact cases");
676 }
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);
690 ATF_TC_HEAD(log_approx, tc)
691 {
692 atf_tc_set_md_var(tc, "descr", "Test log/f/l approximate cases");
693 }
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);
741 ATF_TC_HEAD(log_inf, tc)
742 {
743 atf_tc_set_md_var(tc, "descr", "Test log/f/l on +infinity");
744 }
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
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