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