Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/stdio/scanfloat_test.c
39530 views
1
/*-
2
* Copyright (C) 2003, 2005 David Schultz <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
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.
13
*
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
24
* SUCH DAMAGE.
25
*/
26
27
/*
28
* Test for scanf() floating point formats.
29
*/
30
31
#include <fenv.h>
32
#include <float.h>
33
#include <locale.h>
34
#include <math.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
39
#include <atf-c.h>
40
41
#define eq(type, a, b) _eq(type##_EPSILON, (a), (b))
42
static int
43
_eq(long double epsilon, long double a, long double b)
44
{
45
long double delta;
46
47
delta = fabsl(a - b);
48
return (delta <= epsilon);
49
}
50
51
ATF_TC_WITHOUT_HEAD(normalized_numbers);
52
ATF_TC_BODY(normalized_numbers, tc)
53
{
54
char buf[128];
55
long double ld = 0.0;
56
double d = 0.0;
57
float f = 0.0;
58
59
buf[0] = '\0';
60
ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
61
62
ATF_REQUIRE_EQ(1, sscanf("3.141592", "%e", &f));
63
ATF_REQUIRE(eq(FLT, f, 3.141592));
64
65
ATF_REQUIRE_EQ(1, sscanf("3.141592653589793", "%lf", &d));
66
ATF_REQUIRE(eq(DBL, d, 3.141592653589793));
67
68
ATF_REQUIRE_EQ(1, sscanf("1.234568e+06", "%E", &f));
69
ATF_REQUIRE(eq(FLT, f, 1.234568e+06));
70
71
ATF_REQUIRE_EQ(1, sscanf("-1.234568e6", "%lF", &d));
72
ATF_REQUIRE(eq(DBL, d, -1.234568e6));
73
74
ATF_REQUIRE_EQ(1, sscanf("+1.234568e-52", "%LG", &ld));
75
ATF_REQUIRE(eq(LDBL, ld, 1.234568e-52L));
76
77
ATF_REQUIRE_EQ(1, sscanf("0.1", "%la", &d));
78
ATF_REQUIRE(eq(DBL, d, 0.1));
79
80
ATF_REQUIRE_EQ(1, sscanf("00.2", "%lA", &d));
81
ATF_REQUIRE(eq(DBL, d, 0.2));
82
83
ATF_REQUIRE_EQ(2, sscanf("123456", "%5le%s", &d, buf));
84
ATF_REQUIRE(eq(DBL, d, 12345.));
85
ATF_REQUIRE(strcmp(buf, "6") == 0);
86
87
ATF_REQUIRE_EQ(1, sscanf("1.0Q", "%*5le%s", buf));
88
ATF_REQUIRE(strcmp(buf, "Q") == 0);
89
90
ATF_REQUIRE_EQ(2, sscanf("-1.23e", "%e%s", &f, buf));
91
ATF_REQUIRE(eq(FLT, f, -1.23));
92
ATF_REQUIRE(strcmp(buf, "e") == 0);
93
94
ATF_REQUIRE_EQ(2, sscanf("1.25e+", "%le%s", &d, buf));
95
ATF_REQUIRE(eq(DBL, d, 1.25));
96
ATF_REQUIRE(strcmp(buf, "e+") == 0);
97
98
ATF_REQUIRE_EQ(2, sscanf("1.23E4E5", "%le%s", &d, buf));
99
ATF_REQUIRE(eq(DBL, d, 1.23e4));
100
ATF_REQUIRE(strcmp(buf, "E5") == 0);
101
102
ATF_REQUIRE_EQ(1, sscanf("12e6", "%le", &d));
103
ATF_REQUIRE(eq(DBL, d, 12e6));
104
105
ATF_REQUIRE_EQ(2, sscanf("1.a", "%le%s", &d, buf));
106
ATF_REQUIRE(eq(DBL, d, 1.0));
107
ATF_REQUIRE(strcmp(buf, "a") == 0);
108
109
ATF_REQUIRE_EQ(2, sscanf(".0p4", "%le%s", &d, buf));
110
ATF_REQUIRE(eq(DBL, d, 0.0));
111
ATF_REQUIRE(strcmp(buf, "p4") == 0);
112
113
d = 0.25;
114
ATF_REQUIRE_EQ(0, sscanf(".", "%le", &d));
115
ATF_REQUIRE(d == 0.25);
116
117
ATF_REQUIRE_EQ(1, sscanf("0x08", "%le", &d));
118
ATF_REQUIRE(d == 0x8p0);
119
120
ATF_REQUIRE_EQ(2, sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf));
121
ATF_REQUIRE(d == 0x90a.bcdefp+09);
122
ATF_REQUIRE(strcmp(buf, "a") == 0);
123
124
#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
125
ATF_REQUIRE_EQ(1, sscanf("3.14159265358979323846", "%Lg", &ld));
126
ATF_REQUIRE(eq(LDBL, ld, 3.14159265358979323846L));
127
128
ATF_REQUIRE_EQ(2, sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf));
129
ATF_REQUIRE(ld == 0x0.0123456789abcdefffp-3L);
130
ATF_REQUIRE(strcmp(buf, "g") == 0);
131
#endif
132
133
ATF_REQUIRE_EQ(2, sscanf("0xg", "%le%s", &d, buf));
134
ATF_REQUIRE(d == 0.0);
135
ATF_REQUIRE(strcmp(buf, "xg") == 0);
136
137
ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
138
139
ATF_REQUIRE_EQ(2, sscanf("1.23", "%le%s", &d, buf));
140
ATF_REQUIRE(d == 1.0);
141
ATF_REQUIRE(strcmp(buf, ".23") == 0);
142
143
ATF_REQUIRE_EQ(1, sscanf("1,23", "%le", &d));
144
ATF_REQUIRE(d == 1.23);
145
146
ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
147
}
148
149
ATF_TC_WITHOUT_HEAD(infinities_and_nans);
150
ATF_TC_BODY(infinities_and_nans, tc)
151
{
152
char buf[128];
153
long double ld = 0.0;
154
double d = 0.0;
155
float f = 0.0;
156
157
ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
158
159
ATF_REQUIRE_EQ(1, sscanf("-Inf", "%le", &d));
160
ATF_REQUIRE(d < 0.0 && isinf(d));
161
162
ATF_REQUIRE_EQ(2, sscanf("iNfInItY and beyond", "%le%s", &d, buf));
163
ATF_REQUIRE(d > 0.0 && isinf(d));
164
ATF_REQUIRE(strcmp(buf, " and beyond"));
165
166
ATF_REQUIRE_EQ(1, sscanf("NaN", "%le", &d));
167
ATF_REQUIRE(isnan(d));
168
169
ATF_REQUIRE_EQ(2, sscanf("NAN(123Y", "%le%s", &d, buf));
170
ATF_REQUIRE(isnan(d));
171
ATF_REQUIRE(strcmp(buf, "(123Y") == 0);
172
173
ATF_REQUIRE_EQ(2, sscanf("nan(f00f)plugh", "%le%s", &d, buf));
174
ATF_REQUIRE(isnan(d));
175
ATF_REQUIRE(strcmp(buf, "plugh") == 0);
176
177
ATF_REQUIRE_EQ(1, sscanf("-nan", "%le", &d));
178
ATF_REQUIRE(isnan(d));
179
180
/* Only quiet NaNs should be returned. */
181
ATF_REQUIRE_EQ(1, sscanf("NaN", "%e", &f));
182
ATF_REQUIRE_EQ(1, sscanf("nan", "%le", &d));
183
ATF_REQUIRE_EQ(1, sscanf("nan", "%Le", &ld));
184
ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
185
ATF_REQUIRE(f != f);
186
ATF_REQUIRE(d != d);
187
ATF_REQUIRE(ld != ld);
188
ATF_REQUIRE(fetestexcept(FE_INVALID) == 0);
189
ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%e", &f));
190
ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%le", &d));
191
ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%Le", &ld));
192
ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
193
ATF_REQUIRE(f != f);
194
ATF_REQUIRE(d != d);
195
ATF_REQUIRE(ld != ld);
196
/* POSIX says we should only generate quiet NaNs. */
197
ATF_REQUIRE(fetestexcept(FE_INVALID) == 0);
198
}
199
200
ATF_TC_WITHOUT_HEAD(rounding_tests);
201
ATF_TC_BODY(rounding_tests, tc)
202
{
203
long double ld = 0.0;
204
double d = 0.0;
205
206
ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
207
208
ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
209
210
ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%le", &d));
211
ATF_REQUIRE(d < 2.0);
212
ATF_REQUIRE_EQ(1, sscanf("0x1.ffffffffffffffp0", "%le", &d));
213
ATF_REQUIRE(d < 2.0);
214
ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%Le", &ld));
215
ATF_REQUIRE(ld < 2.0);
216
217
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
218
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
219
ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
220
ATF_REQUIRE(d == -0x1.0ea3f4af0dc5ap0);
221
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
222
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
223
224
ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
225
ATF_REQUIRE(d == 0.0);
226
227
ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
228
ATF_REQUIRE(d == 0x1.234567p-1050);
229
230
ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
231
232
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
233
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
234
ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
235
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
236
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
237
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
238
239
ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
240
ATF_REQUIRE(d == 0x1p-1074);
241
242
ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
243
ATF_REQUIRE(d == 0x1.234568p-1050);
244
245
ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
246
247
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
248
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
249
ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
250
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
251
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
252
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
253
254
ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
255
ATF_REQUIRE(d == 0.0);
256
257
ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
258
ATF_REQUIRE(d == 0x1.234567p-1050);
259
260
ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
261
262
/* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
263
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
264
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
265
ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
266
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
267
ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
268
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
269
270
/* strtod() should round small numbers to 0. */
271
ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
272
ATF_REQUIRE(d == 0.0);
273
274
/* Extra digits in a denormal shouldn't break anything. */
275
ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
276
ATF_REQUIRE(d == 0x1.234568p-1050);
277
}
278
279
ATF_TC_WITHOUT_HEAD(strtod);
280
ATF_TC_BODY(strtod, tc)
281
{
282
char *endp;
283
284
ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
285
286
ATF_REQUIRE(strtod("0xy", &endp) == 0);
287
ATF_REQUIRE(strcmp("xy", endp) == 0);
288
289
/* This used to cause an infinite loop and round the wrong way. */
290
ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
291
ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
292
ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
293
ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
294
ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
295
ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
296
ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
297
ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
298
ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
299
ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
300
ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
301
ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
302
}
303
304
ATF_TP_ADD_TCS(tp)
305
{
306
307
ATF_TP_ADD_TC(tp, normalized_numbers);
308
ATF_TP_ADD_TC(tp, infinities_and_nans);
309
ATF_TP_ADD_TC(tp, rounding_tests);
310
ATF_TP_ADD_TC(tp, strtod);
311
312
return (atf_no_error());
313
}
314
315