1 /* $NetBSD: t_scalbn.c,v 1.10 2013/05/24 11:47:13 martin 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_scalbn.c,v 1.10 2013/05/24 11:47:13 martin Exp $"); 33 34 #include <math.h> 35 #include <limits.h> 36 #include <float.h> 37 #include <errno.h> 38 39 #include <atf-c.h> 40 41 static const int exps[] = { 0, 1, -1, 100, -100 }; 42 43 /* tests here do not require specific precision, so we just use double */ 44 struct testcase { 45 int exp; 46 double inval; 47 double result; 48 int error; 49 }; 50 struct testcase test_vals[] = { 51 { 0, 1.00085, 1.00085, 0 }, 52 { 0, 0.99755, 0.99755, 0 }, 53 { 0, -1.00085, -1.00085, 0 }, 54 { 0, -0.99755, -0.99755, 0 }, 55 { 1, 1.00085, 2.0* 1.00085, 0 }, 56 { 1, 0.99755, 2.0* 0.99755, 0 }, 57 { 1, -1.00085, 2.0* -1.00085, 0 }, 58 { 1, -0.99755, 2.0* -0.99755, 0 }, 59 60 /* 61 * We could add more corner test cases here, but we would have to 62 * add some ifdefs for the exact format and use a reliable 63 * generator program - bail for now and only do trivial stuff above. 64 */ 65 }; 66 67 /* 68 * scalbn(3) 69 */ 70 ATF_TC(scalbn_val); 71 ATF_TC_HEAD(scalbn_val, tc) 72 { 73 atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values"); 74 } 75 76 ATF_TC_BODY(scalbn_val, tc) 77 { 78 const struct testcase *tests = test_vals; 79 const size_t tcnt = __arraycount(test_vals); 80 size_t i; 81 double rv; 82 83 for (i = 0; i < tcnt; i++) { 84 rv = scalbn(tests[i].inval, tests[i].exp); 85 ATF_CHECK_EQ_MSG(errno, tests[i].error, 86 "test %zu: errno %d instead of %d", i, errno, 87 tests[i].error); 88 ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON, 89 "test %zu: return value %g instead of %g (difference %g)", 90 i, rv, tests[i].result, tests[i].result-rv); 91 } 92 } 93 94 ATF_TC(scalbn_nan); 95 ATF_TC_HEAD(scalbn_nan, tc) 96 { 97 atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN"); 98 } 99 100 ATF_TC_BODY(scalbn_nan, tc) 101 { 102 #ifndef __vax__ 103 const double x = 0.0L / 0.0L; 104 double y; 105 size_t i; 106 107 ATF_REQUIRE(isnan(x) != 0); 108 109 for (i = 0; i < __arraycount(exps); i++) { 110 y = scalbn(x, exps[i]); 111 ATF_CHECK(isnan(y) != 0); 112 } 113 #endif 114 } 115 116 ATF_TC(scalbn_inf_neg); 117 ATF_TC_HEAD(scalbn_inf_neg, tc) 118 { 119 atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf"); 120 } 121 122 ATF_TC_BODY(scalbn_inf_neg, tc) 123 { 124 #ifndef __vax__ 125 const double x = -1.0L / 0.0L; 126 size_t i; 127 128 for (i = 0; i < __arraycount(exps); i++) 129 ATF_CHECK(scalbn(x, exps[i]) == x); 130 #endif 131 } 132 133 ATF_TC(scalbn_inf_pos); 134 ATF_TC_HEAD(scalbn_inf_pos, tc) 135 { 136 atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf"); 137 } 138 139 ATF_TC_BODY(scalbn_inf_pos, tc) 140 { 141 #ifndef __vax__ 142 const double x = 1.0L / 0.0L; 143 size_t i; 144 145 for (i = 0; i < __arraycount(exps); i++) 146 ATF_CHECK(scalbn(x, exps[i]) == x); 147 #endif 148 } 149 150 ATF_TC(scalbn_ldexp); 151 ATF_TC_HEAD(scalbn_ldexp, tc) 152 { 153 atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)"); 154 } 155 156 ATF_TC_BODY(scalbn_ldexp, tc) 157 { 158 #ifndef __vax__ 159 #if FLT_RADIX == 2 160 const double x = 2.91288191221812821; 161 double y; 162 size_t i; 163 164 for (i = 0; i < __arraycount(exps); i++) { 165 y = scalbn(x, exps[i]); 166 ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, " 167 "y=%g, expected %g (diff: %g)", i, exps[i], y, 168 ldexp(x, exps[i]), y - ldexp(x, exps[i])); 169 } 170 #endif 171 #endif 172 } 173 174 ATF_TC(scalbn_zero_neg); 175 ATF_TC_HEAD(scalbn_zero_neg, tc) 176 { 177 atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0"); 178 } 179 180 ATF_TC_BODY(scalbn_zero_neg, tc) 181 { 182 #ifndef __vax__ 183 const double x = -0.0L; 184 double y; 185 size_t i; 186 187 ATF_REQUIRE(signbit(x) != 0); 188 189 for (i = 0; i < __arraycount(exps); i++) { 190 y = scalbn(x, exps[i]); 191 ATF_CHECK(x == y); 192 ATF_CHECK(signbit(y) != 0); 193 } 194 #endif 195 } 196 197 ATF_TC(scalbn_zero_pos); 198 ATF_TC_HEAD(scalbn_zero_pos, tc) 199 { 200 atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0"); 201 } 202 203 ATF_TC_BODY(scalbn_zero_pos, tc) 204 { 205 #ifndef __vax__ 206 const double x = 0.0L; 207 double y; 208 size_t i; 209 210 ATF_REQUIRE(signbit(x) == 0); 211 212 for (i = 0; i < __arraycount(exps); i++) { 213 y = scalbn(x, exps[i]); 214 ATF_CHECK(x == y); 215 ATF_CHECK(signbit(y) == 0); 216 } 217 #endif 218 } 219 220 /* 221 * scalbnf(3) 222 */ 223 ATF_TC(scalbnf_val); 224 ATF_TC_HEAD(scalbnf_val, tc) 225 { 226 atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values"); 227 } 228 229 ATF_TC_BODY(scalbnf_val, tc) 230 { 231 #ifndef __vax__ 232 const struct testcase *tests = test_vals; 233 const size_t tcnt = __arraycount(test_vals); 234 size_t i; 235 double rv; 236 237 for (i = 0; i < tcnt; i++) { 238 rv = scalbnf(tests[i].inval, tests[i].exp); 239 ATF_CHECK_EQ_MSG(errno, tests[i].error, 240 "test %zu: errno %d instead of %d", i, errno, 241 tests[i].error); 242 ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON, 243 "test %zu: return value %g instead of %g (difference %g)", 244 i, rv, tests[i].result, tests[i].result-rv); 245 } 246 #endif 247 } 248 249 ATF_TC(scalbnf_nan); 250 ATF_TC_HEAD(scalbnf_nan, tc) 251 { 252 atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN"); 253 } 254 255 ATF_TC_BODY(scalbnf_nan, tc) 256 { 257 #ifndef __vax__ 258 const float x = 0.0L / 0.0L; 259 float y; 260 size_t i; 261 262 ATF_REQUIRE(isnan(x) != 0); 263 264 for (i = 0; i < __arraycount(exps); i++) { 265 y = scalbnf(x, exps[i]); 266 ATF_CHECK(isnan(y) != 0); 267 } 268 #endif 269 } 270 271 ATF_TC(scalbnf_inf_neg); 272 ATF_TC_HEAD(scalbnf_inf_neg, tc) 273 { 274 atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf"); 275 } 276 277 ATF_TC_BODY(scalbnf_inf_neg, tc) 278 { 279 #ifndef __vax__ 280 const float x = -1.0L / 0.0L; 281 size_t i; 282 283 for (i = 0; i < __arraycount(exps); i++) 284 ATF_CHECK(scalbnf(x, exps[i]) == x); 285 #endif 286 } 287 288 ATF_TC(scalbnf_inf_pos); 289 ATF_TC_HEAD(scalbnf_inf_pos, tc) 290 { 291 atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf"); 292 } 293 294 ATF_TC_BODY(scalbnf_inf_pos, tc) 295 { 296 #ifndef __vax__ 297 const float x = 1.0L / 0.0L; 298 size_t i; 299 300 for (i = 0; i < __arraycount(exps); i++) 301 ATF_CHECK(scalbnf(x, exps[i]) == x); 302 #endif 303 } 304 305 ATF_TC(scalbnf_ldexpf); 306 ATF_TC_HEAD(scalbnf_ldexpf, tc) 307 { 308 atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)"); 309 } 310 311 ATF_TC_BODY(scalbnf_ldexpf, tc) 312 { 313 #ifndef __vax__ 314 #if FLT_RADIX == 2 315 const float x = 2.91288191221812821; 316 float y; 317 size_t i; 318 319 for (i = 0; i < __arraycount(exps); i++) { 320 y = scalbnf(x, exps[i]); 321 ATF_CHECK_MSG(y == ldexpf(x, exps[i]), 322 "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)", 323 i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i])); 324 } 325 #endif 326 #endif 327 } 328 329 ATF_TC(scalbnf_zero_neg); 330 ATF_TC_HEAD(scalbnf_zero_neg, tc) 331 { 332 atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0"); 333 } 334 335 ATF_TC_BODY(scalbnf_zero_neg, tc) 336 { 337 #ifndef __vax__ 338 const float x = -0.0L; 339 float y; 340 size_t i; 341 342 ATF_REQUIRE(signbit(x) != 0); 343 344 for (i = 0; i < __arraycount(exps); i++) { 345 y = scalbnf(x, exps[i]); 346 ATF_CHECK(x == y); 347 ATF_CHECK(signbit(y) != 0); 348 } 349 #endif 350 } 351 352 ATF_TC(scalbnf_zero_pos); 353 ATF_TC_HEAD(scalbnf_zero_pos, tc) 354 { 355 atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0"); 356 } 357 358 ATF_TC_BODY(scalbnf_zero_pos, tc) 359 { 360 #ifndef __vax__ 361 const float x = 0.0L; 362 float y; 363 size_t i; 364 365 ATF_REQUIRE(signbit(x) == 0); 366 367 for (i = 0; i < __arraycount(exps); i++) { 368 y = scalbnf(x, exps[i]); 369 ATF_CHECK(x == y); 370 ATF_CHECK(signbit(y) == 0); 371 } 372 #endif 373 } 374 375 /* 376 * scalbnl(3) 377 */ 378 ATF_TC(scalbnl_val); 379 ATF_TC_HEAD(scalbnl_val, tc) 380 { 381 atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values"); 382 } 383 384 ATF_TC_BODY(scalbnl_val, tc) 385 { 386 #ifndef __HAVE_LONG_DOUBLE 387 atf_tc_skip("Requires long double support"); 388 #else 389 const struct testcase *tests = test_vals; 390 const size_t tcnt = __arraycount(test_vals); 391 size_t i; 392 long double rv; 393 394 for (i = 0; i < tcnt; i++) { 395 rv = scalbnl(tests[i].inval, tests[i].exp); 396 ATF_CHECK_EQ_MSG(errno, tests[i].error, 397 "test %zu: errno %d instead of %d", i, errno, 398 tests[i].error); 399 ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON, 400 "test %zu: return value %Lg instead of %Lg (difference %Lg)", 401 i, rv, (long double)tests[i].result, (long double)tests[i].result-rv); 402 } 403 #endif 404 } 405 406 ATF_TC(scalbnl_nan); 407 ATF_TC_HEAD(scalbnl_nan, tc) 408 { 409 atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN"); 410 } 411 412 ATF_TC_BODY(scalbnl_nan, tc) 413 { 414 #ifndef __vax__ 415 #ifndef __HAVE_LONG_DOUBLE 416 atf_tc_skip("Requires long double support"); 417 #else 418 const long double x = 0.0L / 0.0L; 419 long double y; 420 size_t i; 421 422 if (isnan(x) == 0) { 423 atf_tc_expect_fail("PR lib/45362"); 424 atf_tc_fail("(0.0L / 0.0L) != NaN"); 425 } 426 427 for (i = 0; i < __arraycount(exps); i++) { 428 y = scalbnl(x, exps[i]); 429 ATF_CHECK(isnan(y) != 0); 430 } 431 #endif 432 #endif 433 } 434 435 ATF_TC(scalbnl_inf_neg); 436 ATF_TC_HEAD(scalbnl_inf_neg, tc) 437 { 438 atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf"); 439 } 440 441 ATF_TC_BODY(scalbnl_inf_neg, tc) 442 { 443 #ifndef __vax__ 444 #ifndef __HAVE_LONG_DOUBLE 445 atf_tc_skip("Requires long double support"); 446 #else 447 const long double x = -1.0L / 0.0L; 448 size_t i; 449 450 for (i = 0; i < __arraycount(exps); i++) 451 ATF_CHECK(scalbnl(x, exps[i]) == x); 452 #endif 453 #endif 454 } 455 456 ATF_TC(scalbnl_inf_pos); 457 ATF_TC_HEAD(scalbnl_inf_pos, tc) 458 { 459 atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf"); 460 } 461 462 ATF_TC_BODY(scalbnl_inf_pos, tc) 463 { 464 #ifndef __vax__ 465 #ifndef __HAVE_LONG_DOUBLE 466 atf_tc_skip("Requires long double support"); 467 #else 468 const long double x = 1.0L / 0.0L; 469 size_t i; 470 471 for (i = 0; i < __arraycount(exps); i++) 472 ATF_CHECK(scalbnl(x, exps[i]) == x); 473 #endif 474 #endif 475 } 476 477 ATF_TC(scalbnl_zero_neg); 478 ATF_TC_HEAD(scalbnl_zero_neg, tc) 479 { 480 atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0"); 481 } 482 483 ATF_TC_BODY(scalbnl_zero_neg, tc) 484 { 485 #ifndef __vax__ 486 #ifndef __HAVE_LONG_DOUBLE 487 atf_tc_skip("Requires long double support"); 488 #else 489 const long double x = -0.0L; 490 long double y; 491 size_t i; 492 493 ATF_REQUIRE(signbit(x) != 0); 494 495 for (i = 0; i < __arraycount(exps); i++) { 496 y = scalbnl(x, exps[i]); 497 ATF_CHECK(x == y); 498 ATF_CHECK(signbit(y) != 0); 499 } 500 #endif 501 #endif 502 } 503 504 ATF_TC(scalbnl_zero_pos); 505 ATF_TC_HEAD(scalbnl_zero_pos, tc) 506 { 507 atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0"); 508 } 509 510 ATF_TC_BODY(scalbnl_zero_pos, tc) 511 { 512 #ifndef __vax__ 513 #ifndef __HAVE_LONG_DOUBLE 514 atf_tc_skip("Requires long double support"); 515 #else 516 const long double x = 0.0L; 517 long double y; 518 size_t i; 519 520 ATF_REQUIRE(signbit(x) == 0); 521 522 for (i = 0; i < __arraycount(exps); i++) { 523 y = scalbnl(x, exps[i]); 524 ATF_CHECK(x == y); 525 ATF_CHECK(signbit(y) == 0); 526 } 527 #endif 528 #endif 529 } 530 531 ATF_TP_ADD_TCS(tp) 532 { 533 534 ATF_TP_ADD_TC(tp, scalbn_val); 535 ATF_TP_ADD_TC(tp, scalbn_nan); 536 ATF_TP_ADD_TC(tp, scalbn_inf_neg); 537 ATF_TP_ADD_TC(tp, scalbn_inf_pos); 538 ATF_TP_ADD_TC(tp, scalbn_ldexp); 539 ATF_TP_ADD_TC(tp, scalbn_zero_neg); 540 ATF_TP_ADD_TC(tp, scalbn_zero_pos); 541 542 ATF_TP_ADD_TC(tp, scalbnf_val); 543 ATF_TP_ADD_TC(tp, scalbnf_nan); 544 ATF_TP_ADD_TC(tp, scalbnf_inf_neg); 545 ATF_TP_ADD_TC(tp, scalbnf_inf_pos); 546 ATF_TP_ADD_TC(tp, scalbnf_ldexpf); 547 ATF_TP_ADD_TC(tp, scalbnf_zero_neg); 548 ATF_TP_ADD_TC(tp, scalbnf_zero_pos); 549 550 ATF_TP_ADD_TC(tp, scalbnl_val); 551 ATF_TP_ADD_TC(tp, scalbnl_nan); 552 ATF_TP_ADD_TC(tp, scalbnl_inf_neg); 553 ATF_TP_ADD_TC(tp, scalbnl_inf_pos); 554 /* ATF_TP_ADD_TC(tp, scalbnl_ldexp); */ 555 ATF_TP_ADD_TC(tp, scalbnl_zero_neg); 556 ATF_TP_ADD_TC(tp, scalbnl_zero_pos); 557 558 return atf_no_error(); 559 } 560