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