Home | History | Annotate | Line # | Download | only in libm
t_log.c revision 1.17
      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