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