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