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