2 * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Test for scanf() floating point formats.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
43 #define eq(type, a, b) _eq(type##_EPSILON, (a), (b))
44 static int _eq(long double epsilon, long double a, long double b);
47 main(int argc, char *argv[])
58 assert(setlocale(LC_NUMERIC, ""));
61 * Various tests for normalized numbers
63 sscanf("3.141592", "%e", &f);
64 assert(eq(FLT, f, 3.141592));
66 sscanf("3.141592653589793", "%lf", &d);
67 assert(eq(DBL, d, 3.141592653589793));
69 sscanf("1.234568e+06", "%E", &f);
70 assert(eq(FLT, f, 1.234568e+06));
72 sscanf("-1.234568e6", "%lF", &d);
73 assert(eq(DBL, d, -1.234568e6));
75 sscanf("+1.234568e-52", "%LG", &ld);
76 assert(eq(LDBL, ld, 1.234568e-52L));
78 sscanf("0.1", "%la", &d);
79 assert(eq(DBL, d, 0.1));
81 sscanf("00.2", "%lA", &d);
82 assert(eq(DBL, d, 0.2));
84 sscanf("123456", "%5le%s", &d, buf);
85 assert(eq(DBL, d, 12345.));
86 assert(strcmp(buf, "6") == 0);
88 sscanf("1.0Q", "%*5le%s", buf);
89 assert(strcmp(buf, "Q") == 0);
91 sscanf("-1.23e", "%e%s", &f, buf);
92 assert(eq(FLT, f, -1.23));
93 assert(strcmp(buf, "e") == 0);
95 sscanf("1.25e+", "%le%s", &d, buf);
96 assert(eq(DBL, d, 1.25));
97 assert(strcmp(buf, "e+") == 0);
99 sscanf("1.23E4E5", "%le%s", &d, buf);
100 assert(eq(DBL, d, 1.23e4));
101 assert(strcmp(buf, "E5") == 0);
103 sscanf("12e6", "%le", &d);
104 assert(eq(DBL, d, 12e6));
106 sscanf("1.a", "%le%s", &d, buf);
107 assert(eq(DBL, d, 1.0));
108 assert(strcmp(buf, "a") == 0);
110 sscanf(".0p4", "%le%s", &d, buf);
111 assert(eq(DBL, d, 0.0));
112 assert(strcmp(buf, "p4") == 0);
115 assert(sscanf(".", "%le", &d) == 0);
118 sscanf("0x08", "%le", &d);
121 sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf);
122 assert(d == 0x90a.bcdefp+09);
123 assert(strcmp(buf, "a") == 0);
125 #if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
126 sscanf("3.14159265358979323846", "%Lg", &ld);
127 assert(eq(LDBL, ld, 3.14159265358979323846L));
129 sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf);
130 assert(ld == 0x0.0123456789abcdefffp-3L);
131 assert(strcmp(buf, "g") == 0);
134 sscanf("0xg", "%le%s", &d, buf);
136 assert(strcmp(buf, "xg") == 0);
138 assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
140 sscanf("1.23", "%le%s", &d, buf);
142 assert(strcmp(buf, ".23") == 0);
144 sscanf("1,23", "%le", &d);
147 assert(setlocale(LC_NUMERIC, ""));
149 printf("ok 1 - scanfloat\n");
152 * Infinity and NaN tests
154 sscanf("-Inf", "%le", &d);
155 assert(d < 0.0 && isinf(d));
157 sscanf("iNfInItY and beyond", "%le%s", &d, buf);
158 assert(d > 0.0 && isinf(d));
159 assert(strcmp(buf, " and beyond"));
161 sscanf("NaN", "%le", &d);
164 sscanf("NAN(123Y", "%le%s", &d, buf);
166 assert(strcmp(buf, "(123Y") == 0);
168 sscanf("nan(f00f)plugh", "%le%s", &d, buf);
170 assert(strcmp(buf, "plugh") == 0);
172 sscanf("-nan", "%le", &d);
175 /* Only quiet NaNs should be returned. */
176 sscanf("NaN", "%e", &f);
177 sscanf("nan", "%le", &d);
178 sscanf("nan", "%Le", &ld);
179 feclearexcept(FE_ALL_EXCEPT);
183 assert(fetestexcept(FE_INVALID) == 0);
184 sscanf("nan(1234)", "%e", &f);
185 sscanf("nan(1234)", "%le", &d);
186 sscanf("nan(1234)", "%Le", &ld);
187 feclearexcept(FE_ALL_EXCEPT);
191 /* POSIX says we should only generate quiet NaNs. */
192 assert(fetestexcept(FE_INVALID) == 0);
194 printf("ok 2 - scanfloat\n");
200 fesetround(FE_DOWNWARD);
202 sscanf("1.999999999999999999999999999999999", "%le", &d);
204 sscanf("0x1.ffffffffffffffp0", "%le", &d);
206 sscanf("1.999999999999999999999999999999999", "%Le", &ld);
209 sscanf("1.0571892669084007", "%le", &d);
210 assert(d == 0x1.0ea3f4af0dc59p0);
211 sscanf("-1.0571892669084007", "%le", &d);
212 assert(d == -0x1.0ea3f4af0dc5ap0);
213 sscanf("1.0571892669084010", "%le", &d);
214 assert(d == 0x1.0ea3f4af0dc5ap0);
216 sscanf("0x1.23p-5000", "%le", &d);
219 sscanf("0x1.2345678p-1050", "%le", &d);
220 assert(d == 0x1.234567p-1050);
222 fesetround(FE_UPWARD);
224 sscanf("1.0571892669084007", "%le", &d);
225 assert(d == 0x1.0ea3f4af0dc5ap0);
226 sscanf("-1.0571892669084007", "%le", &d);
227 assert(d == -0x1.0ea3f4af0dc59p0);
228 sscanf("1.0571892669084010", "%le", &d);
229 assert(d == 0x1.0ea3f4af0dc5bp0);
231 sscanf("0x1.23p-5000", "%le", &d);
232 assert(d == 0x1p-1074);
234 sscanf("0x1.2345678p-1050", "%le", &d);
235 assert(d == 0x1.234568p-1050);
237 fesetround(FE_TOWARDZERO);
239 sscanf("1.0571892669084007", "%le", &d);
240 assert(d == 0x1.0ea3f4af0dc59p0);
241 sscanf("-1.0571892669084007", "%le", &d);
242 assert(d == -0x1.0ea3f4af0dc59p0);
243 sscanf("1.0571892669084010", "%le", &d);
244 assert(d == 0x1.0ea3f4af0dc5ap0);
246 sscanf("0x1.23p-5000", "%le", &d);
249 sscanf("0x1.2345678p-1050", "%le", &d);
250 assert(d == 0x1.234567p-1050);
252 fesetround(FE_TONEAREST);
254 /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
255 sscanf("1.0571892669084007", "%le", &d);
256 assert(d == 0x1.0ea3f4af0dc59p0);
257 sscanf("-1.0571892669084007", "%le", &d);
258 assert(d == -0x1.0ea3f4af0dc59p0);
259 sscanf("1.0571892669084010", "%le", &d);
260 assert(d == 0x1.0ea3f4af0dc5bp0);
262 /* strtod() should round small numbers to 0. */
263 sscanf("0x1.23p-5000", "%le", &d);
266 /* Extra digits in a denormal shouldn't break anything. */
267 sscanf("0x1.2345678p-1050", "%le", &d);
268 assert(d == 0x1.234568p-1050);
270 printf("ok 3 - scanfloat\n");
273 * Tests specific to strtod().
276 assert(strtod("0xy", &endp) == 0);
277 assert(strcmp("xy", endp) == 0);
279 /* This used to cause an infinite loop and round the wrong way. */
280 fesetround(FE_DOWNWARD);
281 assert(strtof("3.5e38", &endp) == FLT_MAX);
282 assert(strtod("2e308", &endp) == DBL_MAX);
283 fesetround(FE_UPWARD);
284 assert(strtof("3.5e38", &endp) == INFINITY);
285 assert(strtod("2e308", &endp) == INFINITY);
286 fesetround(FE_TOWARDZERO);
287 assert(strtof("3.5e38", &endp) == FLT_MAX);
288 assert(strtod("2e308", &endp) == DBL_MAX);
289 fesetround(FE_TONEAREST);
290 assert(strtof("3.5e38", &endp) == INFINITY);
291 assert(strtod("2e308", &endp) == INFINITY);
293 printf("ok 4 - scanfloat\n");
299 _eq(long double epsilon, long double a, long double b)
303 delta = fabsl(a - b);
304 return (delta <= epsilon);