Home | History | Annotate | Line # | Download | only in stdlib
t_strtod.c revision 1.32
      1 /*	$NetBSD: t_strtod.c,v 1.32 2014/11/04 00:20:19 justin 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 
     32 /* Public domain, Otto Moerbeek <otto (at) drijf.net>, 2006. */
     33 
     34 #include <sys/cdefs.h>
     35 __RCSID("$NetBSD: t_strtod.c,v 1.32 2014/11/04 00:20:19 justin Exp $");
     36 
     37 #include <errno.h>
     38 #include <math.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 
     43 #include <atf-c.h>
     44 
     45 #if defined(__i386__) || defined(__amd64__) || defined(__sparc__)
     46 #include <fenv.h>
     47 #endif
     48 
     49 #if !defined(__vax__)
     50 static const char * const inf_strings[] =
     51     { "Inf", "INF", "-Inf", "-INF", "Infinity", "+Infinity",
     52       "INFINITY", "-INFINITY", "InFiNiTy", "+InFiNiTy" };
     53 const char *nan_string = "NaN(x)y";
     54 #endif
     55 
     56 ATF_TC(strtod_basic);
     57 ATF_TC_HEAD(strtod_basic, tc)
     58 {
     59 	atf_tc_set_md_var(tc, "descr", "A basic test of strtod(3)");
     60 }
     61 
     62 ATF_TC_BODY(strtod_basic, tc)
     63 {
     64 	static const size_t n = 1024 * 1000;
     65 
     66 	for (size_t i = 1; i < n; i = i + 1024) {
     67 		char buf[512];
     68 		(void)snprintf(buf, sizeof(buf), "%zu.%zu", i, i + 1);
     69 
     70 		errno = 0;
     71 		double d = strtod(buf, NULL);
     72 
     73 		ATF_REQUIRE(d > 0.0);
     74 		ATF_REQUIRE(errno == 0);
     75 	}
     76 }
     77 
     78 ATF_TC(strtod_hex);
     79 ATF_TC_HEAD(strtod_hex, tc)
     80 {
     81 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with hexadecimals");
     82 }
     83 
     84 #ifdef __vax__
     85 #define SMALL_NUM       1.0e-38
     86 #else
     87 #define SMALL_NUM       1.0e-40
     88 #endif
     89 
     90 ATF_TC_BODY(strtod_hex, tc)
     91 {
     92 	const char *str;
     93 	char *end;
     94 	volatile double d;
     95 
     96 	str = "-0x0";
     97 	d = strtod(str, &end);	/* -0.0 */
     98 
     99 	ATF_REQUIRE(end == str + 4);
    100 	ATF_REQUIRE(signbit(d) != 0);
    101 	ATF_REQUIRE(fabs(d) < SMALL_NUM);
    102 
    103 	str = "-0x";
    104 	d = strtod(str, &end);	/* -0.0 */
    105 
    106 	ATF_REQUIRE(end == str + 2);
    107 	ATF_REQUIRE(signbit(d) != 0);
    108 	ATF_REQUIRE(fabs(d) < SMALL_NUM);
    109 }
    110 
    111 ATF_TC(strtod_inf);
    112 ATF_TC_HEAD(strtod_inf, tc)
    113 {
    114 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with INF (PR lib/33262)");
    115 }
    116 
    117 ATF_TC_BODY(strtod_inf, tc)
    118 {
    119 #ifndef __vax__
    120 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    121 		volatile double d = strtod(inf_strings[i], NULL);
    122 		ATF_REQUIRE(isinf(d) != 0);
    123 	}
    124 #else
    125 	atf_tc_skip("vax not supported");
    126 #endif
    127 }
    128 
    129 ATF_TC(strtof_inf);
    130 ATF_TC_HEAD(strtof_inf, tc)
    131 {
    132 	atf_tc_set_md_var(tc, "descr", "A strtof(3) with INF (PR lib/33262)");
    133 }
    134 
    135 ATF_TC_BODY(strtof_inf, tc)
    136 {
    137 #ifndef __vax__
    138 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    139 		volatile float f = strtof(inf_strings[i], NULL);
    140 		ATF_REQUIRE(isinf(f) != 0);
    141 	}
    142 #else
    143 	atf_tc_skip("vax not supported");
    144 #endif
    145 }
    146 
    147 ATF_TC(strtold_inf);
    148 ATF_TC_HEAD(strtold_inf, tc)
    149 {
    150 	atf_tc_set_md_var(tc, "descr", "A strtold(3) with INF (PR lib/33262)");
    151 }
    152 
    153 ATF_TC_BODY(strtold_inf, tc)
    154 {
    155 #ifndef __vax__
    156 #   ifdef __HAVE_LONG_DOUBLE
    157 
    158 	for (size_t i = 0; i < __arraycount(inf_strings); i++) {
    159 		volatile long double ld = strtold(inf_strings[i], NULL);
    160 		ATF_REQUIRE(isinf(ld) != 0);
    161 	}
    162 #   else
    163 	atf_tc_skip("Requires long double support");
    164 #   endif
    165 #else
    166 	atf_tc_skip("vax not supported");
    167 #endif
    168 }
    169 
    170 ATF_TC(strtod_nan);
    171 ATF_TC_HEAD(strtod_nan, tc)
    172 {
    173 	atf_tc_set_md_var(tc, "descr", "A strtod(3) with NaN");
    174 }
    175 
    176 ATF_TC_BODY(strtod_nan, tc)
    177 {
    178 #ifndef __vax__
    179 	char *end;
    180 
    181 	volatile double d = strtod(nan_string, &end);
    182 	ATF_REQUIRE(isnan(d) != 0);
    183 	ATF_REQUIRE(strcmp(end, "y") == 0);
    184 #else
    185 	atf_tc_skip("vax not supported");
    186 #endif
    187 }
    188 
    189 ATF_TC(strtof_nan);
    190 ATF_TC_HEAD(strtof_nan, tc)
    191 {
    192 	atf_tc_set_md_var(tc, "descr", "A strtof(3) with NaN");
    193 }
    194 
    195 ATF_TC_BODY(strtof_nan, tc)
    196 {
    197 #ifndef __vax__
    198 	char *end;
    199 
    200 	volatile float f = strtof(nan_string, &end);
    201 	ATF_REQUIRE(isnanf(f) != 0);
    202 	ATF_REQUIRE(strcmp(end, "y") == 0);
    203 #else
    204 	atf_tc_skip("vax not supported");
    205 #endif
    206 }
    207 
    208 ATF_TC(strtold_nan);
    209 ATF_TC_HEAD(strtold_nan, tc)
    210 {
    211 	atf_tc_set_md_var(tc, "descr", "A strtold(3) with NaN (PR lib/45020)");
    212 }
    213 
    214 ATF_TC_BODY(strtold_nan, tc)
    215 {
    216 #ifndef __vax__
    217 #   ifdef __HAVE_LONG_DOUBLE
    218 
    219 	char *end;
    220 
    221 	volatile long double ld = strtold(nan_string, &end);
    222 	ATF_REQUIRE(isnan(ld) != 0);
    223 	ATF_REQUIRE(__isnanl(ld) != 0);
    224 	ATF_REQUIRE(strcmp(end, "y") == 0);
    225 #   else
    226 	atf_tc_skip("Requires long double support");
    227 #   endif
    228 #else
    229 	atf_tc_skip("vax not supported");
    230 #endif
    231 }
    232 
    233 ATF_TC(strtod_round);
    234 ATF_TC_HEAD(strtod_round, tc)
    235 {
    236 	atf_tc_set_md_var(tc, "descr", "Test rouding in strtod(3)");
    237 }
    238 
    239 ATF_TC_BODY(strtod_round, tc)
    240 {
    241 #if defined(__i386__) || defined(__amd64__) || defined(__sparc__)
    242 
    243 	/*
    244 	 * Test that strtod(3) honors the current rounding mode.
    245 	 * The used value is somewhere near 1 + DBL_EPSILON + FLT_EPSILON.
    246 	 */
    247 	const char *val =
    248 	    "1.00000011920928977282585492503130808472633361816406";
    249 
    250 	(void)fesetround(FE_UPWARD);
    251 
    252 	volatile double d1 = strtod(val, NULL);
    253 
    254 	(void)fesetround(FE_DOWNWARD);
    255 
    256 	volatile double d2 = strtod(val, NULL);
    257 
    258 	if (fabs(d1 - d2) > 0.0)
    259 		return;
    260 	else {
    261 		atf_tc_expect_fail("PR misc/44767");
    262 		atf_tc_fail("strtod(3) did not honor fesetround(3)");
    263 	}
    264 #else
    265 	atf_tc_skip("Requires one of i386, amd64 or sparc");
    266 #endif
    267 }
    268 
    269 ATF_TC(strtod_underflow);
    270 ATF_TC_HEAD(strtod_underflow, tc)
    271 {
    272 	atf_tc_set_md_var(tc, "descr", "Test underflow in strtod(3)");
    273 }
    274 
    275 ATF_TC_BODY(strtod_underflow, tc)
    276 {
    277 
    278 	const char *tmp =
    279 	    "0.0000000000000000000000000000000000000000000000000000"
    280 	    "000000000000000000000000000000000000000000000000000000"
    281 	    "000000000000000000000000000000000000000000000000000000"
    282 	    "000000000000000000000000000000000000000000000000000000"
    283 	    "000000000000000000000000000000000000000000000000000000"
    284 	    "000000000000000000000000000000000000000000000000000000"
    285 	    "000000000000000000000000000000000000000000000000000000"
    286 	    "000000000000000002";
    287 
    288 	errno = 0;
    289 	volatile double d = strtod(tmp, NULL);
    290 
    291 	if (d != 0 || errno != ERANGE)
    292 		atf_tc_fail("strtod(3) did not detect underflow");
    293 }
    294 
    295 /*
    296  * Bug found by Geza Herman.
    297  * See
    298  * http://www.exploringbinary.com/a-bug-in-the-bigcomp-function-of-david-gays-strtod/
    299  */
    300 ATF_TC(strtod_gherman_bug);
    301 ATF_TC_HEAD(strtod_gherman_bug, tc)
    302 {
    303 	atf_tc_set_md_var(tc, "descr", "Test a bug found by Geza Herman");
    304 }
    305 
    306 ATF_TC_BODY(strtod_gherman_bug, tc)
    307 {
    308 
    309 	const char *str =
    310 	    "1.8254370818746402660437411213933955878019332885742187";
    311 
    312 	errno = 0;
    313 	volatile double d = strtod(str, NULL);
    314 
    315 	ATF_CHECK(d == 0x1.d34fd8378ea83p+0);
    316 }
    317 
    318 ATF_TP_ADD_TCS(tp)
    319 {
    320 
    321 	ATF_TP_ADD_TC(tp, strtod_basic);
    322 	ATF_TP_ADD_TC(tp, strtod_hex);
    323 	ATF_TP_ADD_TC(tp, strtod_inf);
    324 	ATF_TP_ADD_TC(tp, strtof_inf);
    325 	ATF_TP_ADD_TC(tp, strtold_inf);
    326 	ATF_TP_ADD_TC(tp, strtod_nan);
    327 	ATF_TP_ADD_TC(tp, strtof_nan);
    328 	ATF_TP_ADD_TC(tp, strtold_nan);
    329 	ATF_TP_ADD_TC(tp, strtod_round);
    330 	ATF_TP_ADD_TC(tp, strtod_underflow);
    331 	ATF_TP_ADD_TC(tp, strtod_gherman_bug);
    332 
    333 	return atf_no_error();
    334 }
    335