xref: /netbsd-src/tests/lib/libm/t_log.c (revision 9dc0bb4cc688e21ede7c5dc70e8e7f007735d600)
1 /* $NetBSD: t_log.c,v 1.17 2024/07/16 03:14:16 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.17 2024/07/16 03:14:16 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 #if __HAVE_LONG_DOUBLE + 0 == 128
242 	/*
243 	 * Not sure if it's the same issue, but probably!
244 	 *
245 	 * log10l(x) != y: [1] log10l(0x1.4p+3=10)=0x1.ffffffffcf54a625cf632f6e120dp-1=0.99999999997786775, expected 0x1p+0=1
246 	 * log10l(x) != y: [2] log10l(0x1.9p+6=100)=0x1.ffffc6bdc46c7020e9b1f5a2930ep+0=1.9999965871142409, expected 0x1p+1=2
247 	 */
248 	atf_tc_expect_fail("PR lib/58337: logl() crashes on arm64");
249 #endif
250 
251 	for (i = 0; i < __arraycount(log10f_exact); i++) {
252 		const float x = log10f_exact[i].x;
253 		const float y = log10f_exact[i].y;
254 
255 		CHECK_EQ(i, log10f, x, y);
256 		CHECK_EQ(i, log10, x, y);
257 		CHECKL_EQ(i, log10l, x, y);
258 	}
259 }
260 
261 ATF_TC(log10_approx);
262 ATF_TC_HEAD(log10_approx, tc)
263 {
264 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l approximate cases");
265 }
266 ATF_TC_BODY(log10_approx, tc)
267 {
268 	volatile long double e =
269 	    2.7182818284590452353602874713526624977572470937L;
270 	volatile long double e2 =
271 	    7.3890560989306502272304274605750078131803155705519L;
272 	volatile long double log10e =
273 	    0.43429448190325182765112891891660508229439700580367L;
274 	volatile long double log10e2 =
275 	    2*0.43429448190325182765112891891660508229439700580367L;
276 
277 #if __HAVE_LONG_DOUBLE + 0 == 128
278 	atf_tc_expect_fail("PR lib/58337: logl() crashes on arm64");
279 #endif
280 
281 	ATF_CHECK_MSG((fabsf((log10f(e) - (float)log10e)/(float)log10e) <
282 		2*FLT_EPSILON),
283 	    "log10f(e)=%a=%.8g expected %a=%.8g",
284 	    log10f(e), log10f(e), (float)log10e, (float)log10e);
285 	ATF_CHECK_MSG((fabs((log10(e) - (double)log10e)/(double)log10e) <
286 		2*DBL_EPSILON),
287 	    "log10(e)=%a=%.17g expected %a=%.17g",
288 	    log10(e), log10(e), (double)log10e, (double)log10e);
289 	ATF_CHECK_MSG((fabsl((log10l(e) - log10e)/log10e) < 2*LDBL_EPSILON),
290 	    "log10l(e)=%La=%.34Lg expected %La=%.34Lg",
291 	    log10l(e), log10l(e), log10e, log10e);
292 
293 	ATF_CHECK_MSG((fabsf((log10f(e2) - (float)log10e2)/(float)log10e2) <
294 		2*FLT_EPSILON),
295 	    "log10f(e^2)=%a=%.8g expected %a=%.8g",
296 	    log10f(e2), log10f(e2), (float)log10e2, (float)log10e2);
297 	ATF_CHECK_MSG((fabs((log10(e2) - (double)log10e2)/(double)log10e2) <
298 		2*DBL_EPSILON),
299 	    "log10(e^2)=%a=%.17g expected %a=%.17g",
300 	    log10(e2), log10(e2), (double)log10e2, (double)log10e2);
301 	ATF_CHECK_MSG((fabsl((log10l(e2) - log10e2)/log10e2) < 2*LDBL_EPSILON),
302 	    "log10l(e^2)=%La=%.34Lg expected %La=%.34Lg",
303 	    log10l(e2), log10l(e2), log10e2, log10e2);
304 }
305 
306 ATF_TC(log10_inf);
307 ATF_TC_HEAD(log10_inf, tc)
308 {
309 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l on +infinity");
310 }
311 ATF_TC_BODY(log10_inf, tc)
312 {
313 
314 	if (!isinf(INFINITY))
315 		atf_tc_skip("no infinities on this architecture");
316 
317 	CHECK_EQ(0, log10f, INFINITY, INFINITY);
318 	CHECK_EQ(0, log10, INFINITY, INFINITY);
319 	CHECKL_EQ(0, log10l, INFINITY, INFINITY);
320 }
321 
322 /*
323  * log1p(3)
324  */
325 
326 ATF_TC(log1p_invalid);
327 ATF_TC_HEAD(log1p_invalid, tc)
328 {
329 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on invalid inputs");
330 }
331 ATF_TC_BODY(log1p_invalid, tc)
332 {
333 	unsigned i;
334 
335 	for (i = 0; i < __arraycount(log1pf_invalid); i++) {
336 		CHECK_NAN(i, log1pf, log1pf_invalid[i]);
337 		CHECK_NAN(i, log1p, log1pf_invalid[i]);
338 		CHECKL_NAN(i, log1pl, log1pf_invalid[i]);
339 	}
340 
341 	for (i = 0; i < __arraycount(log1p_invalid); i++) {
342 		CHECK_NAN(i, log1p, log1p_invalid[i]);
343 		CHECKL_NAN(i, log1pl, log1p_invalid[i]);
344 	}
345 
346 	for (i = 0; i < __arraycount(log1pl_invalid); i++) {
347 		CHECKL_NAN(i, log1pl, log1pl_invalid[i]);
348 	}
349 }
350 
351 ATF_TC(log1p_neg_one);
352 ATF_TC_HEAD(log1p_neg_one, tc)
353 {
354 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on -1");
355 }
356 ATF_TC_BODY(log1p_neg_one, tc)
357 {
358 
359 	CHECK_EQ(0, log1pf, -1., -HUGE_VALF);
360 	CHECK_EQ(0, log1p, -1., -HUGE_VAL);
361 	CHECKL_EQ(0, log1pl, -1., -HUGE_VALL);
362 }
363 
364 ATF_TC(log1p_exact);
365 ATF_TC_HEAD(log1p_exact, tc)
366 {
367 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l exact cases");
368 }
369 ATF_TC_BODY(log1p_exact, tc)
370 {
371 
372 	CHECK_EQ(0, log1pf, -FLT_MIN, -FLT_MIN);
373 	CHECK_EQ(0, log1p, -DBL_MIN, -DBL_MIN);
374 	CHECKL_EQ(01, log1pl, -LDBL_MIN, -LDBL_MIN);
375 
376 	CHECK_EQ(1, log1pf, -0., 0);
377 	CHECK_EQ(1, log1p, -0., 0);
378 	CHECKL_EQ(1, log1pl, -0., 0);
379 
380 	CHECK_EQ(2, log1pf, +0., 0);
381 	CHECK_EQ(2, log1p, +0., 0);
382 	CHECKL_EQ(2, log1pl, +0., 0);
383 
384 	CHECK_EQ(3, log1pf, 1, logf(2));
385 	CHECK_EQ(3, log1p, 1, log(2));
386 	CHECKL_EQ(3, log1pl, 1, logl(2));
387 }
388 
389 ATF_TC(log1p_approx);
390 ATF_TC_HEAD(log1p_approx, tc)
391 {
392 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l approximate cases");
393 }
394 ATF_TC_BODY(log1p_approx, tc)
395 {
396 	volatile long double em1 =	/* exp(1) - 1 */
397 	    1.7182818284590452353602874713526624977572470937L;
398 	volatile long double e2m1 =	/* exp(2) - 1 */
399 	    6.3890560989306502272304274605750078131803155705519L;
400 
401 #if __HAVE_LONG_DOUBLE + 0 == 128
402 	atf_tc_expect_fail("PR lib/58337: logl() crashes on arm64");
403 #endif
404 
405 	/*
406 	 * Approximation is close enough that equality of the rounded
407 	 * output had better hold.
408 	 */
409 #ifdef FLT_DENORM_MIN
410 	CHECK_EQ(0, log1pf, -FLT_DENORM_MIN, -FLT_DENORM_MIN);
411 #endif
412 #ifdef DBL_DENORM_MIN
413 	CHECK_EQ(0, log1p, -DBL_DENORM_MIN, -DBL_DENORM_MIN);
414 #endif
415 #ifdef LDBL_DENORM_MIN
416 	CHECKL_EQ(0, log1pl, -LDBL_DENORM_MIN, -LDBL_DENORM_MIN);
417 #endif
418 
419 	ATF_CHECK_MSG(fabsf((log1pf(em1) - 1)/1) < 2*FLT_EPSILON,
420 	    "log1pf(e)=%a=%.8g", log1pf(em1), log1pf(em1));
421 	ATF_CHECK_MSG(fabs((log1p(em1) - 1)/1) < 2*DBL_EPSILON,
422 	    "log1p(e)=%a=%.17g", log1p(em1), log1p(em1));
423 	ATF_CHECK_MSG(fabsl((log1pl(em1) - 1)/1) < 2*LDBL_EPSILON,
424 	    "log1pl(e)=%La=%.34Lg", log1pl(em1), log1pl(em1));
425 
426 	ATF_CHECK_MSG(fabsf((log1pf(e2m1) - 2)/2) < 2*FLT_EPSILON,
427 	    "log1pf(e^2)=%a=%.8g", log1pf(em1), log1pf(em1));
428 	ATF_CHECK_MSG(fabs((log1p(e2m1) - 2)/2) < 2*DBL_EPSILON,
429 	    "log1p(e^2)=%a=%.17g", log1p(em1), log1p(em1));
430 	ATF_CHECK_MSG(fabsl((log1pl(e2m1) - 2)/2) < 2*LDBL_EPSILON,
431 	    "log1pl(e^2)=%La=%.34Lg", log1pl(em1), log1pl(em1));
432 }
433 
434 ATF_TC(log1p_inf);
435 ATF_TC_HEAD(log1p_inf, tc)
436 {
437 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on +infinity");
438 }
439 ATF_TC_BODY(log1p_inf, tc)
440 {
441 
442 	if (!isinf(INFINITY))
443 		atf_tc_skip("no infinities on this architecture");
444 
445 	CHECK_EQ(0, log1pf, INFINITY, INFINITY);
446 	CHECK_EQ(0, log1p, INFINITY, INFINITY);
447 	CHECKL_EQ(0, log1pl, INFINITY, INFINITY);
448 }
449 
450 /*
451  * log2(3)
452  */
453 static const struct {
454 	float x, y;
455 } log2f_exact[] = {
456 #ifdef FLT_DENORM_MIN
457 	{ FLT_DENORM_MIN, FLT_MIN_EXP - FLT_MANT_DIG },
458 #endif
459 	{ FLT_MIN, FLT_MIN_EXP - 1 },
460 	{ 0.25, -2 },
461 	{ 0.5, -1 },
462 	{ 1, 0 },
463 	{ 2, 1 },
464 	{ 4, 2 },
465 	{ 8, 3 },
466 	{ 1 << FLT_MANT_DIG, FLT_MANT_DIG },
467 	{ (float)(1 << FLT_MANT_DIG) * (1 << FLT_MANT_DIG),
468 	  2*FLT_MANT_DIG },
469 };
470 static const struct {
471 	double x, y;
472 } log2_exact[] = {
473 #ifdef DBL_DENORM_MIN
474 	{ DBL_DENORM_MIN, DBL_MIN_EXP - DBL_MANT_DIG },
475 #endif
476 	{ DBL_MIN, DBL_MIN_EXP - 1 },
477 	{ (uint64_t)1 << DBL_MANT_DIG, DBL_MANT_DIG },
478 	{ ((double)((uint64_t)1 << DBL_MANT_DIG) *
479 		    ((uint64_t)1 << DBL_MANT_DIG)),
480 	  2*DBL_MANT_DIG },
481 };
482 
483 static const struct {
484 	long double x, y;
485 } log2l_exact[] = {
486 #ifdef LDBL_DENORM_MIN
487 	{ LDBL_DENORM_MIN, LDBL_MIN_EXP - LDBL_MANT_DIG },
488 #endif
489 	{ LDBL_MIN, LDBL_MIN_EXP - 1 },
490 	{ ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
491 		    ((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))),
492 	  LDBL_MANT_DIG },
493 	{ (((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
494 			((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))) *
495 		    ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
496 			((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2)))),
497 	  2*LDBL_MANT_DIG },
498 };
499 
500 ATF_TC(log2_invalid);
501 ATF_TC_HEAD(log2_invalid, tc)
502 {
503 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on invalid inputs");
504 }
505 ATF_TC_BODY(log2_invalid, tc)
506 {
507 	unsigned i;
508 
509 	for (i = 0; i < __arraycount(logf_invalid); i++) {
510 		CHECK_NAN(i, log2f, logf_invalid[i]);
511 		CHECK_NAN(i, log2, logf_invalid[i]);
512 		CHECKL_NAN(i, log2l, logf_invalid[i]);
513 	}
514 
515 	for (i = 0; i < __arraycount(log_invalid); i++) {
516 		CHECK_NAN(i, log2, log_invalid[i]);
517 		CHECKL_NAN(i, log2l, log_invalid[i]);
518 	}
519 
520 	for (i = 0; i < __arraycount(logl_invalid); i++) {
521 		CHECKL_NAN(i, log2l, logl_invalid[i]);
522 	}
523 }
524 
525 ATF_TC(log2_zero);
526 ATF_TC_HEAD(log2_zero, tc)
527 {
528 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on zero");
529 }
530 ATF_TC_BODY(log2_zero, tc)
531 {
532 
533 	CHECK_EQ(0, log2f, +0., -HUGE_VALF);
534 	CHECK_EQ(0, log2, +0., -HUGE_VAL);
535 	CHECKL_EQ(0, log2l, +0., -HUGE_VALL);
536 
537 	CHECK_EQ(1, log2f, -0., -HUGE_VALF);
538 	CHECK_EQ(1, log2, -0., -HUGE_VAL);
539 	CHECKL_EQ(1, log2l, -0., -HUGE_VALL);
540 }
541 
542 ATF_TC(log2_exact);
543 ATF_TC_HEAD(log2_exact, tc)
544 {
545 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l exact cases");
546 }
547 ATF_TC_BODY(log2_exact, tc)
548 {
549 	unsigned i;
550 
551 	ATF_CHECK_EQ(signbit(log2f(1)), 0);
552 	ATF_CHECK_EQ(signbit(log2(1)), 0);
553 	ATF_CHECK_EQ(signbit(log2l(1)), 0);
554 
555 	for (i = 0; i < __arraycount(log2f_exact); i++) {
556 		const float x = log2f_exact[i].x;
557 		const float y = log2f_exact[i].y;
558 
559 		CHECK_EQ(i, log2f, x, y);
560 		CHECK_EQ(i, log2, x, y);
561 		CHECKL_EQ(i, log2l, x, y);
562 	}
563 
564 	for (i = 0; i < __arraycount(log2_exact); i++) {
565 		const double x = log2_exact[i].x;
566 		const double y = log2_exact[i].y;
567 
568 		CHECK_EQ(i, log2, x, y);
569 		CHECKL_EQ(i, log2l, x, y);
570 	}
571 
572 	for (i = 0; i < __arraycount(log2l_exact); i++) {
573 		const long double x = log2l_exact[i].x;
574 		const long double y = log2l_exact[i].y;
575 
576 		CHECKL_EQ(i, log2l, x, y);
577 	}
578 }
579 
580 ATF_TC(log2_approx);
581 ATF_TC_HEAD(log2_approx, tc)
582 {
583 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l approximate cases");
584 }
585 ATF_TC_BODY(log2_approx, tc)
586 {
587 	volatile long double e =
588 	    2.7182818284590452353602874713526624977572470937L;
589 	volatile long double e2 =
590 	    7.3890560989306502272304274605750078131803155705519L;
591 	volatile long double log2e =
592 	    1.442695040888963407359924681001892137426645954153L;
593 	volatile long double log2e2 =
594 	    2*1.442695040888963407359924681001892137426645954153L;
595 
596 #if __HAVE_LONG_DOUBLE + 0 == 128
597 	atf_tc_expect_fail("PR lib/58337: logl() crashes on arm64");
598 #endif
599 
600 	ATF_CHECK_MSG((fabsf((log2f(e) - (float)log2e)/(float)log2e) <
601 		2*FLT_EPSILON),
602 	    "log2f(e)=%a=%.8g expected %a=%.8g",
603 	    log2f(e), log2f(e), (float)log2e, (float)log2e);
604 	ATF_CHECK_MSG((fabs((log2(e) - (double)log2e)/(double)log2e) <
605 		2*DBL_EPSILON),
606 	    "log2(e)=%a=%.17g expected %a=%.17g",
607 	    log2(e), log2(e), (double)log2e, (double)log2e);
608 	ATF_CHECK_MSG((fabsl((log2l(e) - log2e)/log2e) < 2*LDBL_EPSILON),
609 	    "log2l(e)=%La=%.34Lg expected %La=%.34Lg",
610 	    log2l(e), log2l(e), log2e, log2e);
611 
612 	ATF_CHECK_MSG((fabsf((log2f(e2) - (float)log2e2)/(float)log2e2) <
613 		2*FLT_EPSILON),
614 	    "log2f(e^2)=%a=%.8g expected %a=%.8g",
615 	    log2f(e2), log2f(e2), (float)log2e2, (float)log2e2);
616 	ATF_CHECK_MSG((fabs((log2(e2) - (double)log2e2)/(double)log2e2) <
617 		2*DBL_EPSILON),
618 	    "log2(e^2)=%a=%.17g expected %a=%.17g",
619 	    log2(e2), log2(e2), (double)log2e2, (double)log2e2);
620 	ATF_CHECK_MSG((fabsl((log2l(e2) - log2e2)/log2e2) < 2*LDBL_EPSILON),
621 	    "log2l(e^2)=%La=%.34Lg expected %La=%.34Lg",
622 	    log2l(e2), log2l(e2), log2e2, log2e2);
623 }
624 
625 ATF_TC(log2_inf);
626 ATF_TC_HEAD(log2_inf, tc)
627 {
628 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on +infinity");
629 }
630 ATF_TC_BODY(log2_inf, tc)
631 {
632 
633 	if (!isinf(INFINITY))
634 		atf_tc_skip("no infinities on this architecture");
635 
636 	CHECK_EQ(0, log2f, INFINITY, INFINITY);
637 	CHECK_EQ(0, log2, INFINITY, INFINITY);
638 	CHECKL_EQ(0, log2l, INFINITY, INFINITY);
639 }
640 
641 /*
642  * log(3)
643  */
644 
645 ATF_TC(log_invalid);
646 ATF_TC_HEAD(log_invalid, tc)
647 {
648 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on invalid inputs");
649 }
650 ATF_TC_BODY(log_invalid, tc)
651 {
652 	unsigned i;
653 
654 	for (i = 0; i < __arraycount(logf_invalid); i++) {
655 		CHECK_NAN(i, logf, logf_invalid[i]);
656 		CHECK_NAN(i, log, logf_invalid[i]);
657 		CHECKL_NAN(i, logl, logf_invalid[i]);
658 	}
659 
660 	for (i = 0; i < __arraycount(log_invalid); i++) {
661 		CHECK_NAN(i, log, log_invalid[i]);
662 		CHECKL_NAN(i, logl, log_invalid[i]);
663 	}
664 
665 	for (i = 0; i < __arraycount(logl_invalid); i++) {
666 		CHECKL_NAN(i, logl, logl_invalid[i]);
667 	}
668 }
669 
670 ATF_TC(log_zero);
671 ATF_TC_HEAD(log_zero, tc)
672 {
673 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on zero");
674 }
675 ATF_TC_BODY(log_zero, tc)
676 {
677 
678 	CHECK_EQ(0, logf, +0., -HUGE_VALF);
679 	CHECK_EQ(0, log, +0., -HUGE_VAL);
680 	CHECKL_EQ(0, logl, +0., -HUGE_VALL);
681 
682 	CHECK_EQ(1, logf, -0., -HUGE_VALF);
683 	CHECK_EQ(1, log, -0., -HUGE_VAL);
684 	CHECKL_EQ(1, logl, -0., -HUGE_VALL);
685 }
686 
687 ATF_TC(log_exact);
688 ATF_TC_HEAD(log_exact, tc)
689 {
690 	atf_tc_set_md_var(tc, "descr", "Test log/f/l exact cases");
691 }
692 ATF_TC_BODY(log_exact, tc)
693 {
694 
695 	CHECK_EQ(0, logf, 1, 0);
696 	CHECK_EQ(0, log, 1, 0);
697 	CHECKL_EQ(0, logl, 1, 0);
698 
699 	ATF_CHECK_EQ(signbit(logf(1)), 0);
700 	ATF_CHECK_EQ(signbit(log(1)), 0);
701 	ATF_CHECK_EQ(signbit(logl(1)), 0);
702 }
703 
704 ATF_TC(log_approx);
705 ATF_TC_HEAD(log_approx, tc)
706 {
707 	atf_tc_set_md_var(tc, "descr", "Test log/f/l approximate cases");
708 }
709 ATF_TC_BODY(log_approx, tc)
710 {
711 	volatile long double e =
712 	    2.7182818284590452353602874713526624977572470937L;
713 	volatile long double e2 =
714 	    7.3890560989306502272304274605750078131803155705519L;
715 	volatile long double log_2 =
716 	    0.69314718055994530941723212145817656807550013436025L;
717 	volatile long double log_10 =
718 	    2.30258509299404568401799145468436420760110148862875L;
719 
720 #if __HAVE_LONG_DOUBLE + 0 == 128
721 	atf_tc_expect_fail("PR lib/58337: logl() crashes on arm64");
722 #endif
723 
724 	ATF_CHECK_MSG(fabsf((logf(2) - log_2)/log_2) < 2*FLT_EPSILON,
725 	    "logf(2)=%a=%.8g expected %a=%.8g",
726 	    logf(2), logf(2), (float)log_2, (float)log_2);
727 	ATF_CHECK_MSG(fabs((log(2) - log_2)/log_2) < 2*DBL_EPSILON,
728 	    "log(2)=%a=%.17g expected %a=%.17g",
729 	    log(2), log(2), (double)log_2, (double)log_2);
730 	ATF_CHECK_MSG(fabsl((logl(2) - log_2)/log_2) < 2*LDBL_EPSILON,
731 	    "logl(2)=%La=%.34Lg expected %La=%.34Lg",
732 	    logl(2), logl(2), log_2, log_2);
733 
734 	ATF_CHECK_MSG(fabsf((logf(e) - 1)/1) < 2*FLT_EPSILON,
735 	    "logf(e)=%a=%.8g", logf(e), logf(e));
736 	ATF_CHECK_MSG(fabs((log(e) - 1)/1) < 2*DBL_EPSILON,
737 	    "log(e)=%a=%.17g", log(e), log(e));
738 	ATF_CHECK_MSG(fabsl((logl(e) - 1)/1) < 2*LDBL_EPSILON,
739 	    "logl(e)=%La=%.34Lg", logl(e), logl(e));
740 
741 	ATF_CHECK_MSG(fabsf((logf(e2) - 2)/2) < 2*FLT_EPSILON,
742 	    "logf(e)=%a=%.8g", logf(e2), logf(e2));
743 	ATF_CHECK_MSG(fabs((log(e2) - 2)/2) < 2*DBL_EPSILON,
744 	    "log(e)=%a=%.17g", log(e2), log(e2));
745 	ATF_CHECK_MSG(fabsl((logl(e2) - 2)/2) < 2*LDBL_EPSILON,
746 	    "logl(e)=%La=%.34Lg", logl(e2), logl(e2));
747 
748 	ATF_CHECK_MSG(fabsf((logf(10) - log_10)/log_10) < 2*FLT_EPSILON,
749 	    "logf(10)=%a=%.8g expected %a=%.8g",
750 	    logf(10), logf(10), (float)log_10, (float)log_10);
751 	ATF_CHECK_MSG(fabs((log(10) - log_10)/log_10) < 2*DBL_EPSILON,
752 	    "log(10)=%a=%.17g expected %a=%.17g",
753 	    log(10), log(10), (double)log_10, (double)log_10);
754 	ATF_CHECK_MSG(fabsl((logl(10) - log_10)/log_10) < 2*LDBL_EPSILON,
755 	    "logl(10)=%La=%.34Lg expected %La=%.34Lg",
756 	    logl(10), logl(10), log_10, log_10);
757 }
758 
759 ATF_TC(log_inf);
760 ATF_TC_HEAD(log_inf, tc)
761 {
762 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on +infinity");
763 }
764 ATF_TC_BODY(log_inf, tc)
765 {
766 
767 	if (!isinf(INFINITY))
768 		atf_tc_skip("no infinities on this architecture");
769 
770 	CHECK_EQ(0, logf, INFINITY, INFINITY);
771 	CHECK_EQ(0, log, INFINITY, INFINITY);
772 	CHECKL_EQ(0, logl, INFINITY, INFINITY);
773 }
774 
775 ATF_TP_ADD_TCS(tp)
776 {
777 
778 	ATF_TP_ADD_TC(tp, log10_invalid);
779 	ATF_TP_ADD_TC(tp, log10_zero);
780 	ATF_TP_ADD_TC(tp, log10_exact);
781 	ATF_TP_ADD_TC(tp, log10_approx);
782 	ATF_TP_ADD_TC(tp, log10_inf);
783 
784 	ATF_TP_ADD_TC(tp, log1p_invalid);
785 	ATF_TP_ADD_TC(tp, log1p_neg_one);
786 	ATF_TP_ADD_TC(tp, log1p_exact);
787 	ATF_TP_ADD_TC(tp, log1p_approx);
788 	ATF_TP_ADD_TC(tp, log1p_inf);
789 
790 	ATF_TP_ADD_TC(tp, log2_invalid);
791 	ATF_TP_ADD_TC(tp, log2_zero);
792 	ATF_TP_ADD_TC(tp, log2_exact);
793 	ATF_TP_ADD_TC(tp, log2_approx);
794 	ATF_TP_ADD_TC(tp, log2_inf);
795 
796 	ATF_TP_ADD_TC(tp, log_invalid);
797 	ATF_TP_ADD_TC(tp, log_zero);
798 	ATF_TP_ADD_TC(tp, log_exact);
799 	ATF_TP_ADD_TC(tp, log_approx);
800 	ATF_TP_ADD_TC(tp, log_inf);
801 
802 	return atf_no_error();
803 }
804