scanfloat_test.c revision 179919
1139749Simp/*-
2158078Smarcel * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org>
3158078Smarcel * All rights reserved.
4158078Smarcel *
5119815Smarcel * Redistribution and use in source and binary forms, with or without
6119815Smarcel * modification, are permitted provided that the following conditions
7119815Smarcel * are met:
8119815Smarcel * 1. Redistributions of source code must retain the above copyright
9119815Smarcel *    notice, this list of conditions and the following disclaimer.
10119815Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11119815Smarcel *    notice, this list of conditions and the following disclaimer in the
12119815Smarcel *    documentation and/or other materials provided with the distribution.
13119815Smarcel *
14119815Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15119815Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16119815Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17119815Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18119815Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19119815Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20119815Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21119815Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22119815Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23119815Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24119815Smarcel * SUCH DAMAGE.
25119815Smarcel */
26119815Smarcel
27119815Smarcel/*
28119815Smarcel * Test for scanf() floating point formats.
29119815Smarcel */
30119815Smarcel
31119815Smarcel#include <sys/cdefs.h>
32119815Smarcel__FBSDID("$FreeBSD: head/tools/regression/lib/libc/stdio/test-scanfloat.c 179919 2008-06-21 19:28:26Z das $");
33119815Smarcel
34119815Smarcel#include <assert.h>
35119815Smarcel#include <fenv.h>
36119815Smarcel#include <float.h>
37119815Smarcel#include <locale.h>
38119815Smarcel#include <math.h>
39119815Smarcel#include <stdio.h>
40119815Smarcel#include <string.h>
41119815Smarcel
42119815Smarcel#define	eq(type, a, b)	_eq(type##_EPSILON, (a), (b))
43119815Smarcelstatic int _eq(long double epsilon, long double a, long double b);
44119815Smarcel
45158058Smarcelint
46158058Smarcelmain(int argc, char *argv[])
47119815Smarcel{
48119815Smarcel	char buf[128];
49119815Smarcel	long double ld = 0.0;
50119815Smarcel	double d = 0.0;
51119815Smarcel	float f = 0.0;
52119815Smarcel	char *endp;
53119815Smarcel
54119815Smarcel	printf("1..4\n");
55119815Smarcel
56119815Smarcel	buf[0] = '\0';
57119815Smarcel	assert(setlocale(LC_NUMERIC, ""));
58119815Smarcel
59119815Smarcel	/*
60119815Smarcel	 * Various tests for normalized numbers
61119815Smarcel	 */
62119815Smarcel	sscanf("3.141592", "%e", &f);
63119815Smarcel	assert(eq(FLT, f, 3.141592));
64158058Smarcel
65158058Smarcel	sscanf("3.141592653589793", "%lf", &d);
66158058Smarcel	assert(eq(DBL, d, 3.141592653589793));
67158058Smarcel
68119815Smarcel	sscanf("1.234568e+06", "%E", &f);
69119815Smarcel	assert(eq(FLT, f, 1.234568e+06));
70158058Smarcel
71119815Smarcel	sscanf("-1.234568e6", "%lF", &d);
72119815Smarcel	assert(eq(DBL, d, -1.234568e6));
73119815Smarcel
74158078Smarcel	sscanf("+1.234568e-52", "%LG", &ld);
75158078Smarcel	assert(eq(LDBL, ld, 1.234568e-52L));
76158078Smarcel
77158078Smarcel	sscanf("0.1", "%la", &d);
78158058Smarcel	assert(eq(DBL, d, 0.1));
79158058Smarcel
80158078Smarcel	sscanf("00.2", "%lA", &d);
81158078Smarcel	assert(eq(DBL, d, 0.2));
82169646Smarcel
83158078Smarcel	sscanf("123456", "%5le%s", &d, buf);
84158058Smarcel	assert(eq(DBL, d, 12345.));
85158058Smarcel	assert(strcmp(buf, "6") == 0);
86158058Smarcel
87158058Smarcel	sscanf("1.0Q", "%*5le%s", buf);
88158058Smarcel	assert(strcmp(buf, "Q") == 0);
89158058Smarcel
90158058Smarcel	sscanf("-1.23e", "%e%s", &f, buf);
91158058Smarcel	assert(eq(FLT, f, -1.23));
92158058Smarcel	assert(strcmp(buf, "e") == 0);
93158058Smarcel
94158058Smarcel	sscanf("1.25e+", "%le%s", &d, buf);
95158078Smarcel	assert(eq(DBL, d, 1.25));
96158078Smarcel	assert(strcmp(buf, "e+") == 0);
97158058Smarcel
98158058Smarcel	sscanf("1.23E4E5", "%le%s", &d, buf);
99188472Skaiw	assert(eq(DBL, d, 1.23e4));
100158078Smarcel	assert(strcmp(buf, "E5") == 0);
101158078Smarcel
102158078Smarcel	sscanf("12e6", "%le", &d);
103158078Smarcel	assert(eq(DBL, d, 12e6));
104158078Smarcel
105158078Smarcel	sscanf("1.a", "%le%s", &d, buf);
106158078Smarcel	assert(eq(DBL, d, 1.0));
107158078Smarcel	assert(strcmp(buf, "a") == 0);
108158078Smarcel
109158078Smarcel	sscanf(".0p4", "%le%s", &d, buf);
110158078Smarcel	assert(eq(DBL, d, 0.0));
111158078Smarcel	assert(strcmp(buf, "p4") == 0);
112158078Smarcel
113158058Smarcel	d = 0.25;
114158058Smarcel	assert(sscanf(".", "%le", &d) == 0);
115119815Smarcel	assert(d == 0.25);
116119815Smarcel
117119815Smarcel	sscanf("0x08", "%le", &d);
118158058Smarcel	assert(d == 0x8p0);
119119815Smarcel
120158058Smarcel	sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf);
121119815Smarcel	assert(d == 0x90a.bcdefp+09);
122158058Smarcel	assert(strcmp(buf, "a") == 0);
123158058Smarcel
124158058Smarcel#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
125158058Smarcel	sscanf("3.14159265358979323846", "%Lg", &ld);
126119815Smarcel	assert(eq(LDBL, ld, 3.14159265358979323846L));
127158058Smarcel
128158058Smarcel	sscanf("  0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf);
129158058Smarcel	assert(ld == 0x0.0123456789abcdefffp-3L);
130158058Smarcel	assert(strcmp(buf, "g") == 0);
131158058Smarcel#endif
132158058Smarcel
133158058Smarcel	sscanf("0xg", "%le%s", &d, buf);
134158058Smarcel	assert(d == 0.0);
135158058Smarcel	assert(strcmp(buf, "xg") == 0);
136158058Smarcel
137119815Smarcel	assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
138119815Smarcel
139119815Smarcel	sscanf("1.23", "%le%s", &d, buf);
140119815Smarcel	assert(d == 1.0);
141119815Smarcel	assert(strcmp(buf, ".23") == 0);
142119815Smarcel
143119815Smarcel	sscanf("1,23", "%le", &d);
144119815Smarcel	assert(d == 1.23);
145119815Smarcel
146119815Smarcel	assert(setlocale(LC_NUMERIC, ""));
147158058Smarcel
148119815Smarcel	printf("ok 1 - scanfloat\n");
149119815Smarcel
150119815Smarcel	/*
151119815Smarcel	 * Infinity and NaN tests
152119815Smarcel	 */
153119815Smarcel	sscanf("-Inf", "%le", &d);
154119815Smarcel	assert(d < 0.0 && isinf(d));
155119815Smarcel
156119815Smarcel	sscanf("iNfInItY and beyond", "%le%s", &d, buf);
157119815Smarcel	assert(d > 0.0 && isinf(d));
158158058Smarcel	assert(strcmp(buf, " and beyond"));
159119815Smarcel
160119815Smarcel	sscanf("NaN", "%le", &d);
161119815Smarcel	assert(isnan(d));
162123019Simp
163	sscanf("NAN(123Y", "%le%s", &d, buf);
164	assert(isnan(d));
165	assert(strcmp(buf, "(123Y") == 0);
166
167	sscanf("nan(f00f)plugh", "%le%s", &d, buf);
168	assert(isnan(d));
169	assert(strcmp(buf, "plugh") == 0);
170
171	sscanf("-nan", "%le", &d);
172	assert(isnan(d));
173
174	/* Only quiet NaNs should be returned. */
175	sscanf("NaN", "%e", &f);
176	sscanf("nan", "%le", &d);
177	sscanf("nan", "%Le", &ld);
178	feclearexcept(FE_ALL_EXCEPT);
179	assert(f != f);
180	assert(d != d);
181	assert(ld != ld);
182	assert(fetestexcept(FE_INVALID) == 0);
183	sscanf("nan(1234)", "%e", &f);
184	sscanf("nan(1234)", "%le", &d);
185	sscanf("nan(1234)", "%Le", &ld);
186	feclearexcept(FE_ALL_EXCEPT);
187	assert(f != f);
188	assert(d != d);
189	assert(ld != ld);
190#if 0
191	/*
192	 * POSIX says we should only generate quiet NaNs, but the gdtoa
193	 * author convincingly argues that if you ask for a NaN format
194	 * based on some implementation-defined string, you should get
195	 * what you asked for, even if it's a signaling NaN.
196	 */
197	assert(fetestexcept(FE_INVALID) == 0);
198#endif
199
200	printf("ok 2 - scanfloat\n");
201
202	/*
203	 * Rounding tests
204	 */
205
206	fesetround(FE_DOWNWARD);
207
208	sscanf("1.999999999999999999999999999999999", "%le", &d);
209	assert(d < 2.0);
210	sscanf("0x1.ffffffffffffffp0", "%le", &d);
211	assert(d < 2.0);
212	sscanf("1.999999999999999999999999999999999", "%Le", &ld);
213	assert(ld < 2.0);
214
215	sscanf("1.0571892669084007", "%le", &d);
216	assert(d == 0x1.0ea3f4af0dc59p0);
217	sscanf("-1.0571892669084007", "%le", &d);
218	assert(d == -0x1.0ea3f4af0dc5ap0);
219	sscanf("1.0571892669084010", "%le", &d);
220	assert(d == 0x1.0ea3f4af0dc5ap0);
221
222	sscanf("0x1.23p-5000", "%le", &d);
223	assert(d == 0.0);
224
225	sscanf("0x1.2345678p-1050", "%le", &d);
226	assert(d == 0x1.234567p-1050);
227
228	fesetround(FE_UPWARD);
229
230	sscanf("1.0571892669084007", "%le", &d);
231	assert(d == 0x1.0ea3f4af0dc5ap0);
232	sscanf("-1.0571892669084007", "%le", &d);
233	assert(d == -0x1.0ea3f4af0dc59p0);
234	sscanf("1.0571892669084010", "%le", &d);
235	assert(d == 0x1.0ea3f4af0dc5bp0);
236
237	sscanf("0x1.23p-5000", "%le", &d);
238	assert(d == 0x1p-1074);
239
240	sscanf("0x1.2345678p-1050", "%le", &d);
241	assert(d == 0x1.234568p-1050);
242
243	fesetround(FE_TOWARDZERO);
244
245	sscanf("1.0571892669084007", "%le", &d);
246	assert(d == 0x1.0ea3f4af0dc59p0);
247	sscanf("-1.0571892669084007", "%le", &d);
248	assert(d == -0x1.0ea3f4af0dc59p0);
249	sscanf("1.0571892669084010", "%le", &d);
250	assert(d == 0x1.0ea3f4af0dc5ap0);
251
252	sscanf("0x1.23p-5000", "%le", &d);
253	assert(d == 0.0);
254
255	sscanf("0x1.2345678p-1050", "%le", &d);
256	assert(d == 0x1.234567p-1050);
257
258	fesetround(FE_TONEAREST);
259
260	/* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
261	sscanf("1.0571892669084007", "%le", &d);
262	assert(d == 0x1.0ea3f4af0dc59p0);
263	sscanf("-1.0571892669084007", "%le", &d);
264	assert(d == -0x1.0ea3f4af0dc59p0);
265	sscanf("1.0571892669084010", "%le", &d);
266	assert(d == 0x1.0ea3f4af0dc5bp0);
267
268	/* strtod() should round small numbers to 0. */
269	sscanf("0x1.23p-5000", "%le", &d);
270	assert(d == 0.0);
271
272	/* Extra digits in a denormal shouldn't break anything. */
273	sscanf("0x1.2345678p-1050", "%le", &d);
274	assert(d == 0x1.234568p-1050);
275
276	printf("ok 3 - scanfloat\n");
277
278	/*
279	 * Tests specific to strtod().
280	 */
281
282	assert(strtod("0xy", &endp) == 0);
283	assert(strcmp("xy", endp) == 0);
284
285	printf("ok 4 - scanfloat\n");
286
287	return (0);
288}
289
290static int
291_eq(long double epsilon, long double a, long double b)
292{
293	long double delta;
294
295	delta = a - b;
296	if (delta < 0)		/* XXX no fabsl() */
297		delta = -delta;
298	return (delta <= epsilon);
299}
300