Home | History | Annotate | Line # | Download | only in libm
t_log.c revision 1.16
      1 /* $NetBSD: t_log.c,v 1.16 2024/07/15 06:19:17 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.16 2024/07/15 06:19:17 riastradh Exp $");
     33 
     34 #include <atf-c.h>
     35 
     36 #include <errno.h>
     37 #include <float.h>
     38 #include <math.h>
     39 #include <stdio.h>
     40 #include <string.h>
     41 
     42 #define	CHECK_EQ(i, f, x, y)						      \
     43 	ATF_CHECK_EQ_MSG(f(x), y,					      \
     44 	    "[%u] %s(%a=%.17g)=%a=%.17g, expected %a=%.17g",		      \
     45 	    (i), #f, (double)(x), (double)(x), f(x), f(x),		      \
     46 	    (double)(y), (double)(y))
     47 
     48 #define	CHECKL_EQ(i, f, x, y)						      \
     49 	ATF_CHECK_EQ_MSG(f(x), y,					      \
     50 	    "[%u] %s(%La=%.17Lg)=%La=%.17Lg, expected %La=%.17Lg",	      \
     51 	    (i), #f, (long double)(x), (long double)(x), f(x), f(x),	      \
     52 	    (long double)(y), (long double)(y))
     53 
     54 #ifdef NAN
     55 
     56 #define	CHECK_NAN(i, f, x)						      \
     57 	ATF_CHECK_MSG(isnan(f(x)),					      \
     58 	    "[%u] %s(%a=%.17g)=%a=%.17g, expected NaN",			      \
     59 	    (i), #f, (x), (x), f(x), f(x))
     60 
     61 #define	CHECKL_NAN(i, f, x)						      \
     62 	ATF_CHECK_MSG(isnan(f(x)),					      \
     63 	    "[%u] %s(%La=%.17Lg)=%La=%.17Lg, expected NaN",		      \
     64 	    (i), #f, (long double)(x), (long double)(x), f(x), f(x))
     65 
     66 #else  /* !defined(NAN) */
     67 
     68 #define	CHECK_NAN(i, f, x) do						      \
     69 {									      \
     70 	int _checknan_error;						      \
     71 	double _checknan_result;					      \
     72 	errno = 0;							      \
     73 	_checknan_result = f(x);					      \
     74 	_checknan_error = errno;					      \
     75 	ATF_CHECK_EQ_MSG(errno, EDOM,					      \
     76 	    "[%u] %s(%a=%.17g)=%a=%.17g errno=%d, expected EDOM=%d",	      \
     77 	    (i), #f, (double)(x), (double)(x),				      \
     78 	    _checknan_result, _checknan_result,				      \
     79 	    _checknan_error, EDOM);					      \
     80 } while (0)
     81 
     82 #define	CHECKL_NAN(i, f, x) do						      \
     83 {									      \
     84 	int _checknan_error;						      \
     85 	long double _checknan_result;					      \
     86 	errno = 0;							      \
     87 	_checknan_result = f(x);					      \
     88 	_checknan_error = errno;					      \
     89 	ATF_CHECK_EQ_MSG(errno, EDOM,					      \
     90 	    "[%u] %s(%La=%.17Lg)=%La=%.17Lg errno=%d, expected EDOM=%d",      \
     91 	    (i), #f, (long double)(x), (long double)(x),		      \
     92 	    _checknan_result, _checknan_result,				      \
     93 	    _checknan_error, EDOM);					      \
     94 } while (0)
     95 
     96 #endif	/* NAN */
     97 
     98 static const float logf_invalid[] = {
     99 #ifdef NAN
    100 	NAN,
    101 #endif
    102 	-HUGE_VALF,
    103 	-FLT_MAX,
    104 	-10,
    105 	-1,
    106 	-FLT_EPSILON,
    107 	-FLT_MIN,
    108 #ifdef FLT_DENORM_MIN
    109 	-FLT_DENORM_MIN,
    110 #endif
    111 };
    112 
    113 static const double log_invalid[] = {
    114 #ifdef NAN
    115 	NAN,
    116 #endif
    117 	-HUGE_VAL,
    118 	-DBL_MAX,
    119 	-10,
    120 	-1,
    121 	-DBL_EPSILON,
    122 	-DBL_MIN,
    123 #ifdef DBL_DENORM_MIN
    124 	-DBL_DENORM_MIN,
    125 #endif
    126 };
    127 
    128 static const long double logl_invalid[] = {
    129 #ifdef NAN
    130 	NAN,
    131 #endif
    132 	-HUGE_VALL,
    133 	-LDBL_MAX,
    134 	-10,
    135 	-1,
    136 	-LDBL_EPSILON,
    137 	-LDBL_MIN,
    138 #ifdef LDBL_DENORM_MIN
    139 	-LDBL_DENORM_MIN,
    140 #endif
    141 };
    142 
    143 static const float log1pf_invalid[] = {
    144 #ifdef NAN
    145 	NAN,
    146 #endif
    147 	-HUGE_VALF,
    148 	-FLT_MAX,
    149 	-10,
    150 	-1 - FLT_EPSILON,
    151 };
    152 
    153 static const double log1p_invalid[] = {
    154 #ifdef NAN
    155 	NAN,
    156 #endif
    157 	-HUGE_VAL,
    158 	-DBL_MAX,
    159 	-10,
    160 	-1 - DBL_EPSILON,
    161 };
    162 
    163 static const long double log1pl_invalid[] = {
    164 #ifdef NAN
    165 	NAN,
    166 #endif
    167 	-HUGE_VALL,
    168 	-LDBL_MAX,
    169 	-10,
    170 	-1 - LDBL_EPSILON,
    171 };
    172 
    173 /*
    174  * log10(3)
    175  */
    176 static const struct {
    177 	float x, y;
    178 } log10f_exact[] = {
    179 	{ 1, 0 },
    180 	{ 10, 1 },
    181 	{ 100, 2 },
    182 };
    183 
    184 ATF_TC(log10_invalid);
    185 ATF_TC_HEAD(log10_invalid, tc)
    186 {
    187 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l on invalid inputs");
    188 }
    189 ATF_TC_BODY(log10_invalid, tc)
    190 {
    191 	unsigned i;
    192 
    193 	for (i = 0; i < __arraycount(logf_invalid); i++) {
    194 		CHECK_NAN(i, log10f, logf_invalid[i]);
    195 		CHECK_NAN(i, log10, logf_invalid[i]);
    196 		CHECKL_NAN(i, log10l, logf_invalid[i]);
    197 	}
    198 
    199 	for (i = 0; i < __arraycount(log_invalid); i++) {
    200 		CHECK_NAN(i, log10, log_invalid[i]);
    201 		CHECKL_NAN(i, log10l, log_invalid[i]);
    202 	}
    203 
    204 	for (i = 0; i < __arraycount(logl_invalid); i++) {
    205 		CHECKL_NAN(i, log10l, logl_invalid[i]);
    206 	}
    207 }
    208 
    209 ATF_TC(log10_zero);
    210 ATF_TC_HEAD(log10_zero, tc)
    211 {
    212 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l on zero");
    213 }
    214 ATF_TC_BODY(log10_zero, tc)
    215 {
    216 
    217 	CHECK_EQ(0, log10f, +0., -HUGE_VALF);
    218 	CHECK_EQ(0, log10, +0., -HUGE_VAL);
    219 	CHECKL_EQ(0, log10l, +0., -HUGE_VALL);
    220 
    221 	CHECK_EQ(1, log10f, -0., -HUGE_VALF);
    222 	CHECK_EQ(1, log10, -0., -HUGE_VAL);
    223 	CHECKL_EQ(1, log10l, -0., -HUGE_VALL);
    224 }
    225 
    226 ATF_TC(log10_exact);
    227 ATF_TC_HEAD(log10_exact, tc)
    228 {
    229 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l exact cases");
    230 }
    231 ATF_TC_BODY(log10_exact, tc)
    232 {
    233 	unsigned i;
    234 
    235 	ATF_CHECK_EQ(signbit(log10f(1)), 0);
    236 	ATF_CHECK_EQ(signbit(log10(1)), 0);
    237 	ATF_CHECK_EQ(signbit(log10l(1)), 0);
    238 
    239 	for (i = 0; i < __arraycount(log10f_exact); i++) {
    240 		const float x = log10f_exact[i].x;
    241 		const float y = log10f_exact[i].y;
    242 
    243 		CHECK_EQ(i, log10f, x, y);
    244 		CHECK_EQ(i, log10, x, y);
    245 		CHECKL_EQ(i, log10l, x, y);
    246 	}
    247 }
    248 
    249 ATF_TC(log10_inf);
    250 ATF_TC_HEAD(log10_inf, tc)
    251 {
    252 	atf_tc_set_md_var(tc, "descr", "Test log10/f/l on +infinity");
    253 }
    254 ATF_TC_BODY(log10_inf, tc)
    255 {
    256 
    257 	if (!isinf(INFINITY))
    258 		atf_tc_skip("no infinities on this architecture");
    259 
    260 	CHECK_EQ(0, log10f, INFINITY, INFINITY);
    261 	CHECK_EQ(0, log10, INFINITY, INFINITY);
    262 	CHECKL_EQ(0, log10l, INFINITY, INFINITY);
    263 }
    264 
    265 /*
    266  * log1p(3)
    267  */
    268 
    269 ATF_TC(log1p_invalid);
    270 ATF_TC_HEAD(log1p_invalid, tc)
    271 {
    272 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on invalid inputs");
    273 }
    274 ATF_TC_BODY(log1p_invalid, tc)
    275 {
    276 	unsigned i;
    277 
    278 	for (i = 0; i < __arraycount(log1pf_invalid); i++) {
    279 		CHECK_NAN(i, log1pf, log1pf_invalid[i]);
    280 		CHECK_NAN(i, log1p, log1pf_invalid[i]);
    281 		CHECKL_NAN(i, log1pl, log1pf_invalid[i]);
    282 	}
    283 
    284 	for (i = 0; i < __arraycount(log1p_invalid); i++) {
    285 		CHECK_NAN(i, log1p, log1p_invalid[i]);
    286 		CHECKL_NAN(i, log1pl, log1p_invalid[i]);
    287 	}
    288 
    289 	for (i = 0; i < __arraycount(log1pl_invalid); i++) {
    290 		CHECKL_NAN(i, log1pl, log1pl_invalid[i]);
    291 	}
    292 }
    293 
    294 ATF_TC(log1p_neg_one);
    295 ATF_TC_HEAD(log1p_neg_one, tc)
    296 {
    297 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on -1");
    298 }
    299 ATF_TC_BODY(log1p_neg_one, tc)
    300 {
    301 
    302 	CHECK_EQ(0, log1pf, -1., -HUGE_VALF);
    303 	CHECK_EQ(0, log1p, -1., -HUGE_VAL);
    304 	CHECKL_EQ(0, log1pl, -1., -HUGE_VALL);
    305 }
    306 
    307 ATF_TC(log1p_exact);
    308 ATF_TC_HEAD(log1p_exact, tc)
    309 {
    310 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l exact cases");
    311 }
    312 ATF_TC_BODY(log1p_exact, tc)
    313 {
    314 
    315 	/*
    316 	 * Not _exact_, but the approximation is good enough.
    317 	 */
    318 #ifdef FLT_DENORM_MIN
    319 	CHECK_EQ(0, log1pf, -FLT_DENORM_MIN, -FLT_DENORM_MIN);
    320 #endif
    321 #ifdef DBL_DENORM_MIN
    322 	CHECK_EQ(0, log1p, -DBL_DENORM_MIN, -DBL_DENORM_MIN);
    323 #endif
    324 #ifdef LDBL_DENORM_MIN
    325 	CHECKL_EQ(0, log1pl, -LDBL_DENORM_MIN, -LDBL_DENORM_MIN);
    326 #endif
    327 
    328 	CHECK_EQ(1, log1pf, -FLT_MIN, -FLT_MIN);
    329 	CHECK_EQ(1, log1p, -DBL_MIN, -DBL_MIN);
    330 	CHECKL_EQ(1, log1pl, -LDBL_MIN, -LDBL_MIN);
    331 
    332 	CHECK_EQ(0, log1pf, -0., 0);
    333 	CHECK_EQ(0, log1p, -0., 0);
    334 	CHECKL_EQ(0, log1pl, -0., 0);
    335 
    336 	CHECK_EQ(1, log1pf, +0., 0);
    337 	CHECK_EQ(1, log1p, +0., 0);
    338 	CHECKL_EQ(1, log1pl, +0., 0);
    339 
    340 	CHECK_EQ(2, log1pf, 1, logf(2));
    341 	CHECK_EQ(2, log1p, 1, log(2));
    342 	CHECKL_EQ(2, log1pl, 1, logl(2));
    343 }
    344 
    345 ATF_TC(log1p_inf);
    346 ATF_TC_HEAD(log1p_inf, tc)
    347 {
    348 	atf_tc_set_md_var(tc, "descr", "Test log1p/f/l on +infinity");
    349 }
    350 ATF_TC_BODY(log1p_inf, tc)
    351 {
    352 
    353 	if (!isinf(INFINITY))
    354 		atf_tc_skip("no infinities on this architecture");
    355 
    356 	CHECK_EQ(0, log1pf, INFINITY, INFINITY);
    357 	CHECK_EQ(0, log1p, INFINITY, INFINITY);
    358 	CHECKL_EQ(0, log1pl, INFINITY, INFINITY);
    359 }
    360 
    361 /*
    362  * log2(3)
    363  */
    364 static const struct {
    365 	float x, y;
    366 } log2f_exact[] = {
    367 #ifdef FLT_DENORM_MIN
    368 	{ FLT_DENORM_MIN, FLT_MIN_EXP - FLT_MANT_DIG },
    369 #endif
    370 	{ FLT_MIN, FLT_MIN_EXP - 1 },
    371 	{ 0.25, -2 },
    372 	{ 0.5, -1 },
    373 	{ 1, 0 },
    374 	{ 2, 1 },
    375 	{ 4, 2 },
    376 	{ 8, 3 },
    377 	{ 1 << FLT_MANT_DIG, FLT_MANT_DIG },
    378 	{ (float)(1 << FLT_MANT_DIG) * (1 << FLT_MANT_DIG),
    379 	  2*FLT_MANT_DIG },
    380 };
    381 static const struct {
    382 	double x, y;
    383 } log2_exact[] = {
    384 #ifdef DBL_DENORM_MIN
    385 	{ DBL_DENORM_MIN, DBL_MIN_EXP - DBL_MANT_DIG },
    386 #endif
    387 	{ DBL_MIN, DBL_MIN_EXP - 1 },
    388 	{ (uint64_t)1 << DBL_MANT_DIG, DBL_MANT_DIG },
    389 	{ ((double)((uint64_t)1 << DBL_MANT_DIG) *
    390 		    ((uint64_t)1 << DBL_MANT_DIG)),
    391 	  2*DBL_MANT_DIG },
    392 };
    393 
    394 static const struct {
    395 	long double x, y;
    396 } log2l_exact[] = {
    397 #ifdef LDBL_DENORM_MIN
    398 	{ LDBL_DENORM_MIN, LDBL_MIN_EXP - LDBL_MANT_DIG },
    399 #endif
    400 	{ LDBL_MIN, LDBL_MIN_EXP - 1 },
    401 	{ ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
    402 		    ((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))),
    403 	  LDBL_MANT_DIG },
    404 	{ (((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
    405 			((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2))) *
    406 		    ((long double)((uint64_t)1 << (LDBL_MANT_DIG/2)) *
    407 			((uint64_t)1 << ((LDBL_MANT_DIG + 1)/2)))),
    408 	  2*LDBL_MANT_DIG },
    409 };
    410 
    411 ATF_TC(log2_invalid);
    412 ATF_TC_HEAD(log2_invalid, tc)
    413 {
    414 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on invalid inputs");
    415 }
    416 ATF_TC_BODY(log2_invalid, tc)
    417 {
    418 	unsigned i;
    419 
    420 	for (i = 0; i < __arraycount(logf_invalid); i++) {
    421 		CHECK_NAN(i, log2f, logf_invalid[i]);
    422 		CHECK_NAN(i, log2, logf_invalid[i]);
    423 		CHECKL_NAN(i, log2l, logf_invalid[i]);
    424 	}
    425 
    426 	for (i = 0; i < __arraycount(log_invalid); i++) {
    427 		CHECK_NAN(i, log2, log_invalid[i]);
    428 		CHECKL_NAN(i, log2l, log_invalid[i]);
    429 	}
    430 
    431 	for (i = 0; i < __arraycount(logl_invalid); i++) {
    432 		CHECKL_NAN(i, log2l, logl_invalid[i]);
    433 	}
    434 }
    435 
    436 ATF_TC(log2_zero);
    437 ATF_TC_HEAD(log2_zero, tc)
    438 {
    439 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on zero");
    440 }
    441 ATF_TC_BODY(log2_zero, tc)
    442 {
    443 
    444 	CHECK_EQ(0, log2f, +0., -HUGE_VALF);
    445 	CHECK_EQ(0, log2, +0., -HUGE_VAL);
    446 	CHECKL_EQ(0, log2l, +0., -HUGE_VALL);
    447 
    448 	CHECK_EQ(1, log2f, -0., -HUGE_VALF);
    449 	CHECK_EQ(1, log2, -0., -HUGE_VAL);
    450 	CHECKL_EQ(1, log2l, -0., -HUGE_VALL);
    451 }
    452 
    453 ATF_TC(log2_exact);
    454 ATF_TC_HEAD(log2_exact, tc)
    455 {
    456 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l exact cases");
    457 }
    458 ATF_TC_BODY(log2_exact, tc)
    459 {
    460 	unsigned i;
    461 
    462 	ATF_CHECK_EQ(signbit(log2f(1)), 0);
    463 	ATF_CHECK_EQ(signbit(log2(1)), 0);
    464 	ATF_CHECK_EQ(signbit(log2l(1)), 0);
    465 
    466 	for (i = 0; i < __arraycount(log2f_exact); i++) {
    467 		const float x = log2f_exact[i].x;
    468 		const float y = log2f_exact[i].y;
    469 
    470 		CHECK_EQ(i, log2f, x, y);
    471 		CHECK_EQ(i, log2, x, y);
    472 		CHECKL_EQ(i, log2l, x, y);
    473 	}
    474 
    475 	for (i = 0; i < __arraycount(log2_exact); i++) {
    476 		const double x = log2_exact[i].x;
    477 		const double y = log2_exact[i].y;
    478 
    479 		CHECK_EQ(i, log2, x, y);
    480 		CHECKL_EQ(i, log2l, x, y);
    481 	}
    482 
    483 	for (i = 0; i < __arraycount(log2l_exact); i++) {
    484 		const long double x = log2l_exact[i].x;
    485 		const long double y = log2l_exact[i].y;
    486 
    487 		CHECKL_EQ(i, log2l, x, y);
    488 	}
    489 }
    490 
    491 ATF_TC(log2_inf);
    492 ATF_TC_HEAD(log2_inf, tc)
    493 {
    494 	atf_tc_set_md_var(tc, "descr", "Test log2/f/l on +infinity");
    495 }
    496 ATF_TC_BODY(log2_inf, tc)
    497 {
    498 
    499 	if (!isinf(INFINITY))
    500 		atf_tc_skip("no infinities on this architecture");
    501 
    502 	CHECK_EQ(0, log2f, INFINITY, INFINITY);
    503 	CHECK_EQ(0, log2, INFINITY, INFINITY);
    504 	CHECKL_EQ(0, log2l, INFINITY, INFINITY);
    505 }
    506 
    507 /*
    508  * log(3)
    509  */
    510 
    511 ATF_TC(log_invalid);
    512 ATF_TC_HEAD(log_invalid, tc)
    513 {
    514 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on invalid inputs");
    515 }
    516 ATF_TC_BODY(log_invalid, tc)
    517 {
    518 	unsigned i;
    519 
    520 	for (i = 0; i < __arraycount(logf_invalid); i++) {
    521 		CHECK_NAN(i, logf, logf_invalid[i]);
    522 		CHECK_NAN(i, log, logf_invalid[i]);
    523 		CHECKL_NAN(i, logl, logf_invalid[i]);
    524 	}
    525 
    526 	for (i = 0; i < __arraycount(log_invalid); i++) {
    527 		CHECK_NAN(i, log, log_invalid[i]);
    528 		CHECKL_NAN(i, logl, log_invalid[i]);
    529 	}
    530 
    531 	for (i = 0; i < __arraycount(logl_invalid); i++) {
    532 		CHECKL_NAN(i, logl, logl_invalid[i]);
    533 	}
    534 }
    535 
    536 ATF_TC(log_zero);
    537 ATF_TC_HEAD(log_zero, tc)
    538 {
    539 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on zero");
    540 }
    541 ATF_TC_BODY(log_zero, tc)
    542 {
    543 
    544 	CHECK_EQ(0, logf, +0., -HUGE_VALF);
    545 	CHECK_EQ(0, log, +0., -HUGE_VAL);
    546 	CHECKL_EQ(0, logl, +0., -HUGE_VALL);
    547 
    548 	CHECK_EQ(1, logf, -0., -HUGE_VALF);
    549 	CHECK_EQ(1, log, -0., -HUGE_VAL);
    550 	CHECKL_EQ(1, logl, -0., -HUGE_VALL);
    551 }
    552 
    553 ATF_TC(log_normal);
    554 ATF_TC_HEAD(log_normal, tc)
    555 {
    556 	atf_tc_set_md_var(tc, "descr", "Test log/f/l normal cases");
    557 }
    558 ATF_TC_BODY(log_normal, tc)
    559 {
    560 	volatile long double e = M_E;
    561 
    562 	CHECK_EQ(0, logf, 1, 0);
    563 	CHECK_EQ(0, log, 1, 0);
    564 	CHECKL_EQ(0, logl, 1, 0);
    565 
    566 	ATF_CHECK_EQ(signbit(logf(1)), 0);
    567 	ATF_CHECK_EQ(signbit(log(1)), 0);
    568 	ATF_CHECK_EQ(signbit(logl(1)), 0);
    569 
    570 	ATF_CHECK_MSG(fabsf((logf(e) - 1)/1) < FLT_EPSILON,
    571 	    "logf(e)=%a=%.8g", logf(e), logf(e));
    572 	ATF_CHECK_MSG(fabs((log(e) - 1)/1) < DBL_EPSILON,
    573 	    "log(e)=%a=%.17g", log(e), log(e));
    574 	ATF_CHECK_MSG(fabsl((logl(e) - 1)/1) < LDBL_EPSILON,
    575 	    "logl(e)=%La=%.34Lg", logl(e), logl(e));
    576 }
    577 
    578 ATF_TC(log_inf);
    579 ATF_TC_HEAD(log_inf, tc)
    580 {
    581 	atf_tc_set_md_var(tc, "descr", "Test log/f/l on +infinity");
    582 }
    583 ATF_TC_BODY(log_inf, tc)
    584 {
    585 
    586 	if (!isinf(INFINITY))
    587 		atf_tc_skip("no infinities on this architecture");
    588 
    589 	CHECK_EQ(0, logf, INFINITY, INFINITY);
    590 	CHECK_EQ(0, log, INFINITY, INFINITY);
    591 	CHECKL_EQ(0, logl, INFINITY, INFINITY);
    592 }
    593 
    594 ATF_TP_ADD_TCS(tp)
    595 {
    596 
    597 	ATF_TP_ADD_TC(tp, log10_invalid);
    598 	ATF_TP_ADD_TC(tp, log10_zero);
    599 	ATF_TP_ADD_TC(tp, log10_exact);
    600 	ATF_TP_ADD_TC(tp, log10_inf);
    601 
    602 	ATF_TP_ADD_TC(tp, log1p_invalid);
    603 	ATF_TP_ADD_TC(tp, log1p_neg_one);
    604 	ATF_TP_ADD_TC(tp, log1p_exact);
    605 	ATF_TP_ADD_TC(tp, log1p_inf);
    606 
    607 	ATF_TP_ADD_TC(tp, log2_invalid);
    608 	ATF_TP_ADD_TC(tp, log2_zero);
    609 	ATF_TP_ADD_TC(tp, log2_exact);
    610 	ATF_TP_ADD_TC(tp, log2_inf);
    611 
    612 	ATF_TP_ADD_TC(tp, log_invalid);
    613 	ATF_TP_ADD_TC(tp, log_zero);
    614 	ATF_TP_ADD_TC(tp, log_normal);
    615 	ATF_TP_ADD_TC(tp, log_inf);
    616 
    617 	return atf_no_error();
    618 }
    619