Home | History | Annotate | Line # | Download | only in libm
t_ldexp.c revision 1.16
      1 /* $NetBSD: t_ldexp.c,v 1.16 2016/08/25 00:32:31 maya 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_ldexp.c,v 1.16 2016/08/25 00:32:31 maya Exp $");
     33 
     34 #include <sys/param.h>
     35 
     36 #include <atf-c.h>
     37 
     38 #include <math.h>
     39 #include <limits.h>
     40 #include <stdio.h>
     41 #include <string.h>
     42 
     43 #define SKIP	9999
     44 #define FORMAT  "%23.23lg"
     45 
     46 static const int exps[] = { 0, 1, -1, 100, -100 };
     47 
     48 struct ldexp_test {
     49 	double	    x;
     50 	int	    exp1;
     51 	int	    exp2;
     52 	const char *result;
     53 };
     54 
     55 struct ldexp_test ldexp_basic[] = {
     56 	{ 1.0,	5,	SKIP,	"                     32" },
     57 	{ 1.0,	1022,	SKIP,	"4.4942328371557897693233e+307" },
     58 	{ 1.0,	1023,	-1,	"4.4942328371557897693233e+307" },
     59 	{ 1.0,	1023,	SKIP,	"8.9884656743115795386465e+307" },
     60 	{ 1.0,	1022,	1,	"8.9884656743115795386465e+307" },
     61 	{ 1.0,	-1022,	2045,	"8.9884656743115795386465e+307" },
     62 	{ 1.0,	-5,	SKIP,	"                0.03125" },
     63 	{ 1.0,	-1021,	SKIP,	"4.4501477170144027661805e-308" },
     64 	{ 1.0,	-1022,	1,	"4.4501477170144027661805e-308" },
     65 	{ 1.0,	-1022,	SKIP,	"2.2250738585072013830902e-308" },
     66 	{ 1.0,	-1021,	-1,	"2.2250738585072013830902e-308" },
     67 	{ 1.0,	1023,	-2045,	"2.2250738585072013830902e-308" },
     68 	{ 1.0,	1023,	-1023,	"                      1" },
     69 	{ 1.0,	-1022,	1022,	"                      1" },
     70 	{ 0,	0,	0,	NULL }
     71 };
     72 
     73 struct ldexp_test ldexp_zero[] = {
     74 	{ 0.0,	-1,	SKIP,	"                      0" },
     75 	{ 0.0,	0,	SKIP,	"                      0" },
     76 	{ 0.0,	1,	SKIP,	"                      0" },
     77 	{ 0.0,	1024,	SKIP,	"                      0" },
     78 	{ 0.0,	1025,	SKIP,	"                      0" },
     79 	{ 0.0,	-1023,	SKIP,	"                      0" },
     80 	{ 0.0,	-1024,	SKIP,	"                      0" },
     81 	{ 0,	0,	0,	NULL }
     82 };
     83 
     84 struct ldexp_test ldexp_infinity[] = {
     85 	{ 1.0,	1024,	-1,	"                    inf" },
     86 	{ 1.0,	1024,	0,	"                    inf" },
     87 	{ 1.0,	1024,	1,	"                    inf" },
     88 	{ -1.0,	1024,	-1,	"                   -inf" },
     89 	{ -1.0,	1024,	0,	"                   -inf" },
     90 	{ -1.0,	1024,	1,	"                   -inf" },
     91 	{ 0,	0,	0,	NULL }
     92 };
     93 
     94 struct ldexp_test ldexp_overflow[] = {
     95 	{ 1.0,	1024,	SKIP,	"                    inf" },
     96 	{ 1.0,	1023,	1,	"                    inf" },
     97 	{ 1.0,	-1022,	2046,	"                    inf" },
     98 	{ 1.0,	1025,	SKIP,	"                    inf" },
     99 	{ 2.0,	INT_MAX,SKIP,	"                    inf" },
    100 	{ -1.0,	1024,	SKIP,	"                   -inf" },
    101 	{ -1.0,	1023,	1,	"                   -inf" },
    102 	{ -1.0,	-1022,	2046,	"                   -inf" },
    103 	{ -1.0,	1025,	SKIP,	"                   -inf" },
    104 	{ -2.0, INT_MAX,SKIP,	"                   -inf" },
    105 	{ 0,	0,	0,	NULL }
    106 };
    107 
    108 struct ldexp_test ldexp_denormal[] = {
    109 	{ 1.0,	-1023,	SKIP,	"1.1125369292536006915451e-308" },
    110 	{ 1.0,	-1022,	-1,	"1.1125369292536006915451e-308" },
    111 	{ 1.0,	1023,	-2046,	"1.1125369292536006915451e-308" },
    112 	{ 1.0,	-1024,	SKIP,	"5.5626846462680034577256e-309" },
    113 	{ 1.0,	-1074,	SKIP,	"4.9406564584124654417657e-324" },
    114 	{ -1.0,	-1023,	SKIP,	"-1.1125369292536006915451e-308" },
    115 	{ -1.0,	-1022,	-1,	"-1.1125369292536006915451e-308" },
    116 	{ -1.0,	1023,	-2046,	"-1.1125369292536006915451e-308" },
    117 	{ -1.0,	-1024,	SKIP,	"-5.5626846462680034577256e-309" },
    118 	{ -1.0,	-1074,	SKIP,	"-4.9406564584124654417657e-324" },
    119 	{ 0,	0,	0,	NULL }
    120 };
    121 
    122 struct ldexp_test ldexp_underflow[] = {
    123 	{ 1.0,	-1075,	SKIP,	"                      0" },
    124 	{ 1.0,	-1074,	-1,	"                      0" },
    125 	{ 1.0,	1023,	-2098,	"                      0" },
    126 	{ 1.0,	-1076,	SKIP,	"                      0" },
    127 	{ -1.0,	-1075,	SKIP,	"                     -0" },
    128 	{ -1.0,	-1074,	-1,	"                     -0" },
    129 	{ -1.0,	1023,	-2098,	"                     -0" },
    130 	{ -1.0,	-1076,	SKIP,	"                     -0" },
    131 	{ 0,	0,	0,	NULL }
    132 };
    133 
    134 struct ldexp_test ldexp_denormal_large[] = {
    135 	{ 1.0,	-1028,	1024,	"                 0.0625" },
    136 	{ 1.0,	-1028,	1025,	"                  0.125" },
    137 	{ 1.0,	-1028,	1026,	"                   0.25" },
    138 	{ 1.0,	-1028,	1027,	"                    0.5" },
    139 	{ 1.0,	-1028,	1028,	"                      1" },
    140 	{ 1.0,	-1028,	1029,	"                      2" },
    141 	{ 1.0,	-1028,	1030,	"                      4" },
    142 	{ 1.0,	-1028,	1040,	"                   4096" },
    143 	{ 1.0,	-1028,	1050,	"                4194304" },
    144 	{ 1.0,	-1028,	1060,	"             4294967296" },
    145 	{ 1.0,	-1028,	1100,	" 4722366482869645213696" },
    146 	{ 1.0,	-1028,	1200,	"5.9863107065073783529623e+51" },
    147 	{ 1.0,	-1028,	1300,	"7.5885503602567541832791e+81" },
    148 	{ 1.0,	-1028,	1400,	"9.6196304190416209014353e+111" },
    149 	{ 1.0,	-1028,	1500,	"1.2194330274671844653834e+142" },
    150 	{ 1.0,	-1028,	1600,	"1.5458150092069033378781e+172" },
    151 	{ 1.0,	-1028,	1700,	"1.9595533242629369747791e+202" },
    152 	{ 1.0,	-1028,	1800,	"2.4840289476811342962384e+232" },
    153 	{ 1.0,	-1028,	1900,	"3.1488807865122869393369e+262" },
    154 	{ 1.0,	-1028,	2000,	"3.9916806190694396233127e+292" },
    155 	{ 1.0,	-1028,	2046,	"2.808895523222368605827e+306" },
    156 	{ 1.0,	-1028,	2047,	"5.6177910464447372116541e+306" },
    157 	{ 1.0,	-1028,	2048,	"1.1235582092889474423308e+307" },
    158 	{ 1.0,	-1028,	2049,	"2.2471164185778948846616e+307" },
    159 	{ 1.0,	-1028,	2050,	"4.4942328371557897693233e+307" },
    160 	{ 1.0,	-1028,	2051,	"8.9884656743115795386465e+307" },
    161 	{ 0,	0,	0,	NULL }
    162 };
    163 
    164 static void
    165 run_test(struct ldexp_test *table)
    166 {
    167 	char outbuf[64];
    168 	size_t i;
    169 	double v;
    170 
    171 	for (i = 0; table->result != NULL; table++, i++) {
    172 
    173 		v = ldexp(table->x, table->exp1);
    174 
    175 		if (table->exp2 != SKIP)
    176 			v = ldexp(v, table->exp2);
    177 
    178 		(void)snprintf(outbuf, sizeof(outbuf), FORMAT, v);
    179 
    180 		ATF_CHECK_STREQ_MSG(table->result, outbuf,
    181 			    "Entry %zu:\n\tExp: \"%s\"\n\tAct: \"%s\"",
    182 			    i, table->result, outbuf);
    183 	}
    184 }
    185 
    186 /*
    187  * ldexp(3)
    188  */
    189 ATF_TC(ldexp_exp2);
    190 ATF_TC_HEAD(ldexp_exp2, tc)
    191 {
    192 	atf_tc_set_md_var(tc, "descr", "Test ldexp(x, n) == x * exp2(n)");
    193 }
    194 
    195 ATF_TC_BODY(ldexp_exp2, tc)
    196 {
    197 	const double n[] = { 1, 2, 3, 10, 50, 100 };
    198 #if __DBL_MIN_10_EXP__ <= -40
    199 	const double eps = 1.0e-40;
    200 #else
    201 	const double eps = __DBL_MIN__*4.0;
    202 #endif
    203 	const double x = 12.0;
    204 	double y;
    205 	size_t i;
    206 
    207 	for (i = 0; i < __arraycount(n); i++) {
    208 
    209 		y = ldexp(x, n[i]);
    210 
    211 		if (fabs(y - (x * exp2(n[i]))) > eps) {
    212 			atf_tc_fail_nonfatal("ldexp(%0.01f, %0.01f) "
    213 			    "!= %0.01f * exp2(%0.01f)", x, n[i], x, n[i]);
    214 		}
    215 	}
    216 }
    217 
    218 ATF_TC(ldexp_nan);
    219 ATF_TC_HEAD(ldexp_nan, tc)
    220 {
    221 	atf_tc_set_md_var(tc, "descr", "Test ldexp(NaN) == NaN");
    222 }
    223 
    224 ATF_TC_BODY(ldexp_nan, tc)
    225 {
    226 	const double x = 0.0L / 0.0L;
    227 	double y;
    228 	size_t i;
    229 
    230 	ATF_REQUIRE(isnan(x) != 0);
    231 
    232 	for (i = 0; i < __arraycount(exps); i++) {
    233 		y = ldexp(x, exps[i]);
    234 		ATF_CHECK(isnan(y) != 0);
    235 	}
    236 }
    237 
    238 ATF_TC(ldexp_inf_neg);
    239 ATF_TC_HEAD(ldexp_inf_neg, tc)
    240 {
    241 	atf_tc_set_md_var(tc, "descr", "Test ldexp(-Inf) == -Inf");
    242 }
    243 
    244 ATF_TC_BODY(ldexp_inf_neg, tc)
    245 {
    246 	const double x = -1.0L / 0.0L;
    247 	size_t i;
    248 
    249 	for (i = 0; i < __arraycount(exps); i++)
    250 		ATF_CHECK(ldexp(x, exps[i]) == x);
    251 }
    252 
    253 ATF_TC(ldexp_inf_pos);
    254 ATF_TC_HEAD(ldexp_inf_pos, tc)
    255 {
    256 	atf_tc_set_md_var(tc, "descr", "Test ldexp(+Inf) == +Inf");
    257 }
    258 
    259 ATF_TC_BODY(ldexp_inf_pos, tc)
    260 {
    261 	const double x = 1.0L / 0.0L;
    262 	size_t i;
    263 
    264 	for (i = 0; i < __arraycount(exps); i++)
    265 		ATF_CHECK(ldexp(x, exps[i]) == x);
    266 }
    267 
    268 ATF_TC(ldexp_zero_neg);
    269 ATF_TC_HEAD(ldexp_zero_neg, tc)
    270 {
    271 	atf_tc_set_md_var(tc, "descr", "Test ldexp(-0.0) == -0.0");
    272 }
    273 
    274 ATF_TC_BODY(ldexp_zero_neg, tc)
    275 {
    276 	const double x = -0.0L;
    277 	double y;
    278 	size_t i;
    279 
    280 	ATF_REQUIRE(signbit(x) != 0);
    281 
    282 	for (i = 0; i < __arraycount(exps); i++) {
    283 		y = ldexp(x, exps[i]);
    284 		ATF_CHECK(x == y);
    285 		ATF_CHECK(signbit(y) != 0);
    286 	}
    287 }
    288 
    289 ATF_TC(ldexp_zero_pos);
    290 ATF_TC_HEAD(ldexp_zero_pos, tc)
    291 {
    292 	atf_tc_set_md_var(tc, "descr", "Test ldexp(+0.0) == +0.0");
    293 }
    294 
    295 ATF_TC_BODY(ldexp_zero_pos, tc)
    296 {
    297 	const double x = 0.0L;
    298 	double y;
    299 	size_t i;
    300 
    301 	ATF_REQUIRE(signbit(x) == 0);
    302 
    303 	for (i = 0; i < __arraycount(exps); i++) {
    304 		y = ldexp(x, exps[i]);
    305 		ATF_CHECK(x == y);
    306 		ATF_CHECK(signbit(y) == 0);
    307 	}
    308 }
    309 
    310 /*
    311  * ldexpf(3)
    312  */
    313 
    314 ATF_TC(ldexpf_exp2f);
    315 ATF_TC_HEAD(ldexpf_exp2f, tc)
    316 {
    317 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(x, n) == x * exp2f(n)");
    318 }
    319 
    320 ATF_TC_BODY(ldexpf_exp2f, tc)
    321 {
    322 	const float n[] = { 1, 2, 3, 10, 50, 100 };
    323 	const float eps = 1.0e-9;
    324 	const float x = 12.0;
    325 	float y;
    326 	size_t i;
    327 
    328 	for (i = 0; i < __arraycount(n); i++) {
    329 
    330 		y = ldexpf(x, n[i]);
    331 
    332 		if (fabsf(y - (x * exp2f(n[i]))) > eps) {
    333 			atf_tc_fail_nonfatal("ldexpf(%0.01f, %0.01f) "
    334 			    "!= %0.01f * exp2f(%0.01f)", x, n[i], x, n[i]);
    335 		}
    336 	}
    337 }
    338 
    339 ATF_TC(ldexpf_nan);
    340 ATF_TC_HEAD(ldexpf_nan, tc)
    341 {
    342 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(NaN) == NaN");
    343 }
    344 
    345 ATF_TC_BODY(ldexpf_nan, tc)
    346 {
    347 	const float x = 0.0L / 0.0L;
    348 	float y;
    349 	size_t i;
    350 
    351 	ATF_REQUIRE(isnan(x) != 0);
    352 
    353 	for (i = 0; i < __arraycount(exps); i++) {
    354 		y = ldexpf(x, exps[i]);
    355 		ATF_CHECK(isnan(y) != 0);
    356 	}
    357 }
    358 
    359 ATF_TC(ldexpf_inf_neg);
    360 ATF_TC_HEAD(ldexpf_inf_neg, tc)
    361 {
    362 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(-Inf) == -Inf");
    363 }
    364 
    365 ATF_TC_BODY(ldexpf_inf_neg, tc)
    366 {
    367 	const float x = -1.0L / 0.0L;
    368 	size_t i;
    369 
    370 	for (i = 0; i < __arraycount(exps); i++)
    371 		ATF_CHECK(ldexpf(x, exps[i]) == x);
    372 }
    373 
    374 ATF_TC(ldexpf_inf_pos);
    375 ATF_TC_HEAD(ldexpf_inf_pos, tc)
    376 {
    377 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(+Inf) == +Inf");
    378 }
    379 
    380 ATF_TC_BODY(ldexpf_inf_pos, tc)
    381 {
    382 	const float x = 1.0L / 0.0L;
    383 	size_t i;
    384 
    385 	for (i = 0; i < __arraycount(exps); i++)
    386 		ATF_CHECK(ldexpf(x, exps[i]) == x);
    387 }
    388 
    389 ATF_TC(ldexpf_zero_neg);
    390 ATF_TC_HEAD(ldexpf_zero_neg, tc)
    391 {
    392 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(-0.0) == -0.0");
    393 }
    394 
    395 ATF_TC_BODY(ldexpf_zero_neg, tc)
    396 {
    397 	const float x = -0.0L;
    398 	float y;
    399 	size_t i;
    400 
    401 	ATF_REQUIRE(signbit(x) != 0);
    402 
    403 	for (i = 0; i < __arraycount(exps); i++) {
    404 		y = ldexpf(x, exps[i]);
    405 		ATF_CHECK(x == y);
    406 		ATF_CHECK(signbit(y) != 0);
    407 	}
    408 }
    409 
    410 ATF_TC(ldexpf_zero_pos);
    411 ATF_TC_HEAD(ldexpf_zero_pos, tc)
    412 {
    413 	atf_tc_set_md_var(tc, "descr", "Test ldexpf(+0.0) == +0.0");
    414 }
    415 
    416 ATF_TC_BODY(ldexpf_zero_pos, tc)
    417 {
    418 	const float x = 0.0L;
    419 	float y;
    420 	size_t i;
    421 
    422 	ATF_REQUIRE(signbit(x) == 0);
    423 
    424 	for (i = 0; i < __arraycount(exps); i++) {
    425 		y = ldexpf(x, exps[i]);
    426 		ATF_CHECK(x == y);
    427 		ATF_CHECK(signbit(y) == 0);
    428 	}
    429 }
    430 
    431 #define TEST(name, desc)						\
    432 	ATF_TC(name);							\
    433 	ATF_TC_HEAD(name, tc)						\
    434 	{								\
    435 									\
    436 		atf_tc_set_md_var(tc, "descr",				\
    437 		    "Test ldexp(3) for " ___STRING(desc));		\
    438 	}								\
    439 	ATF_TC_BODY(name, tc)						\
    440 	{								\
    441 		if (strcmp("vax", MACHINE_ARCH) == 0)			\
    442 			atf_tc_skip("Test not valid for " MACHINE_ARCH); \
    443 		run_test(name);						\
    444 	}
    445 
    446 TEST(ldexp_basic, basics)
    447 TEST(ldexp_zero, zero)
    448 TEST(ldexp_infinity, infinity)
    449 TEST(ldexp_overflow, overflow)
    450 TEST(ldexp_denormal, denormal)
    451 TEST(ldexp_denormal_large, large)
    452 TEST(ldexp_underflow, underflow)
    453 
    454 ATF_TP_ADD_TCS(tp)
    455 {
    456 
    457 	ATF_TP_ADD_TC(tp, ldexp_basic);
    458 	ATF_TP_ADD_TC(tp, ldexp_zero);
    459 	ATF_TP_ADD_TC(tp, ldexp_infinity);
    460 	ATF_TP_ADD_TC(tp, ldexp_overflow);
    461 	ATF_TP_ADD_TC(tp, ldexp_denormal);
    462 	ATF_TP_ADD_TC(tp, ldexp_underflow);
    463 	ATF_TP_ADD_TC(tp, ldexp_denormal_large);
    464 
    465 	ATF_TP_ADD_TC(tp, ldexp_exp2);
    466 	ATF_TP_ADD_TC(tp, ldexp_nan);
    467 	ATF_TP_ADD_TC(tp, ldexp_inf_neg);
    468 	ATF_TP_ADD_TC(tp, ldexp_inf_pos);
    469 	ATF_TP_ADD_TC(tp, ldexp_zero_neg);
    470 	ATF_TP_ADD_TC(tp, ldexp_zero_pos);
    471 
    472 	ATF_TP_ADD_TC(tp, ldexpf_exp2f);
    473 	ATF_TP_ADD_TC(tp, ldexpf_nan);
    474 	ATF_TP_ADD_TC(tp, ldexpf_inf_neg);
    475 	ATF_TP_ADD_TC(tp, ldexpf_inf_pos);
    476 	ATF_TP_ADD_TC(tp, ldexpf_zero_neg);
    477 	ATF_TP_ADD_TC(tp, ldexpf_zero_pos);
    478 
    479 	return atf_no_error();
    480 }
    481