t_scalbn.c revision 276478
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 41static const int exps[] = { 0, 1, -1, 100, -100 }; 42 43/* tests here do not require specific precision, so we just use double */ 44struct testcase { 45 int exp; 46 double inval; 47 double result; 48 int error; 49}; 50struct 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 */ 70ATF_TC(scalbn_val); 71ATF_TC_HEAD(scalbn_val, tc) 72{ 73 atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values"); 74} 75 76ATF_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 97ATF_TC(scalbn_nan); 98ATF_TC_HEAD(scalbn_nan, tc) 99{ 100 atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN"); 101} 102 103ATF_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 117ATF_TC(scalbn_inf_neg); 118ATF_TC_HEAD(scalbn_inf_neg, tc) 119{ 120 atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf"); 121} 122 123ATF_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 132ATF_TC(scalbn_inf_pos); 133ATF_TC_HEAD(scalbn_inf_pos, tc) 134{ 135 atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf"); 136} 137 138ATF_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 147ATF_TC(scalbn_ldexp); 148ATF_TC_HEAD(scalbn_ldexp, tc) 149{ 150 atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)"); 151} 152 153ATF_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 169ATF_TC(scalbn_zero_neg); 170ATF_TC_HEAD(scalbn_zero_neg, tc) 171{ 172 atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0"); 173} 174 175ATF_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 190ATF_TC(scalbn_zero_pos); 191ATF_TC_HEAD(scalbn_zero_pos, tc) 192{ 193 atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0"); 194} 195 196ATF_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 */ 214ATF_TC(scalbnf_val); 215ATF_TC_HEAD(scalbnf_val, tc) 216{ 217 atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values"); 218} 219 220ATF_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 rv = scalbnf(tests[i].inval, tests[i].exp); 229 ATF_CHECK_EQ_MSG(errno, tests[i].error, 230 "test %zu: errno %d instead of %d", i, errno, 231 tests[i].error); 232 ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON, 233 "test %zu: return value %g instead of %g (difference %g)", 234 i, rv, tests[i].result, tests[i].result-rv); 235 } 236} 237 238ATF_TC(scalbnf_nan); 239ATF_TC_HEAD(scalbnf_nan, tc) 240{ 241 atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN"); 242} 243 244ATF_TC_BODY(scalbnf_nan, tc) 245{ 246 const float x = 0.0L / 0.0L; 247 float y; 248 size_t i; 249 250 ATF_REQUIRE(isnan(x) != 0); 251 252 for (i = 0; i < __arraycount(exps); i++) { 253 y = scalbnf(x, exps[i]); 254 ATF_CHECK(isnan(y) != 0); 255 } 256} 257 258ATF_TC(scalbnf_inf_neg); 259ATF_TC_HEAD(scalbnf_inf_neg, tc) 260{ 261 atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf"); 262} 263 264ATF_TC_BODY(scalbnf_inf_neg, tc) 265{ 266 const float x = -1.0L / 0.0L; 267 size_t i; 268 269 for (i = 0; i < __arraycount(exps); i++) 270 ATF_CHECK(scalbnf(x, exps[i]) == x); 271} 272 273ATF_TC(scalbnf_inf_pos); 274ATF_TC_HEAD(scalbnf_inf_pos, tc) 275{ 276 atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf"); 277} 278 279ATF_TC_BODY(scalbnf_inf_pos, tc) 280{ 281 const float x = 1.0L / 0.0L; 282 size_t i; 283 284 for (i = 0; i < __arraycount(exps); i++) 285 ATF_CHECK(scalbnf(x, exps[i]) == x); 286} 287 288ATF_TC(scalbnf_ldexpf); 289ATF_TC_HEAD(scalbnf_ldexpf, tc) 290{ 291 atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)"); 292} 293 294ATF_TC_BODY(scalbnf_ldexpf, tc) 295{ 296#if FLT_RADIX == 2 297 const float x = 2.91288191221812821; 298 float y; 299 size_t i; 300 301 for (i = 0; i < __arraycount(exps); i++) { 302 y = scalbnf(x, exps[i]); 303 ATF_CHECK_MSG(y == ldexpf(x, exps[i]), 304 "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)", 305 i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i])); 306 } 307#endif 308} 309 310ATF_TC(scalbnf_zero_neg); 311ATF_TC_HEAD(scalbnf_zero_neg, tc) 312{ 313 atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0"); 314} 315 316ATF_TC_BODY(scalbnf_zero_neg, tc) 317{ 318 const float x = -0.0L; 319 float y; 320 size_t i; 321 322 ATF_REQUIRE(signbit(x) != 0); 323 324 for (i = 0; i < __arraycount(exps); i++) { 325 y = scalbnf(x, exps[i]); 326 ATF_CHECK(x == y); 327 ATF_CHECK(signbit(y) != 0); 328 } 329} 330 331ATF_TC(scalbnf_zero_pos); 332ATF_TC_HEAD(scalbnf_zero_pos, tc) 333{ 334 atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0"); 335} 336 337ATF_TC_BODY(scalbnf_zero_pos, tc) 338{ 339 const float x = 0.0L; 340 float y; 341 size_t i; 342 343 ATF_REQUIRE(signbit(x) == 0); 344 345 for (i = 0; i < __arraycount(exps); i++) { 346 y = scalbnf(x, exps[i]); 347 ATF_CHECK(x == y); 348 ATF_CHECK(signbit(y) == 0); 349 } 350} 351 352/* 353 * scalbnl(3) 354 */ 355ATF_TC(scalbnl_val); 356ATF_TC_HEAD(scalbnl_val, tc) 357{ 358 atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values"); 359} 360 361ATF_TC_BODY(scalbnl_val, tc) 362{ 363#ifndef __HAVE_LONG_DOUBLE 364 atf_tc_skip("Requires long double support"); 365#else 366 const struct testcase *tests = test_vals; 367 const size_t tcnt = __arraycount(test_vals); 368 size_t i; 369 long double rv; 370 371 for (i = 0; i < tcnt; i++) { 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 383ATF_TC(scalbnl_nan); 384ATF_TC_HEAD(scalbnl_nan, tc) 385{ 386 atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN"); 387} 388 389ATF_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 410ATF_TC(scalbnl_inf_neg); 411ATF_TC_HEAD(scalbnl_inf_neg, tc) 412{ 413 atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf"); 414} 415 416ATF_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 429ATF_TC(scalbnl_inf_pos); 430ATF_TC_HEAD(scalbnl_inf_pos, tc) 431{ 432 atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf"); 433} 434 435ATF_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 448ATF_TC(scalbnl_zero_neg); 449ATF_TC_HEAD(scalbnl_zero_neg, tc) 450{ 451 atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0"); 452} 453 454ATF_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 473ATF_TC(scalbnl_zero_pos); 474ATF_TC_HEAD(scalbnl_zero_pos, tc) 475{ 476 atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0"); 477} 478 479ATF_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 498ATF_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