]>
Commit | Line | Data |
---|---|---|
bfff8b1b | 1 | /* Copyright (C) 1991-2017 Free Software Foundation, Inc. |
afd4eb37 | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
afd4eb37 | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 8 | |
afd4eb37 UD |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 17 | |
28f540f4 | 18 | #include <ctype.h> |
dc5fd907 UD |
19 | #include <locale.h> |
20 | #include <stddef.h> | |
28f540f4 RM |
21 | #include <stdio.h> |
22 | #include <stdlib.h> | |
23 | #include <errno.h> | |
24 | #include <string.h> | |
a529b416 | 25 | #include <math.h> |
28f540f4 RM |
26 | |
27 | struct ltest | |
28 | { | |
afd4eb37 | 29 | const char *str; /* Convert this. */ |
28f540f4 RM |
30 | double expect; /* To get this. */ |
31 | char left; /* With this left over. */ | |
32 | int err; /* And this in errno. */ | |
33 | }; | |
afd4eb37 | 34 | static const struct ltest tests[] = |
28f540f4 RM |
35 | { |
36 | { "12.345", 12.345, '\0', 0 }, | |
37 | { "12.345e19", 12.345e19, '\0', 0 }, | |
38 | { "-.1e+9", -.1e+9, '\0', 0 }, | |
39 | { ".125", .125, '\0', 0 }, | |
40 | { "1e20", 1e20, '\0', 0 }, | |
afd4eb37 | 41 | { "0e-19", 0, '\0', 0 }, |
6259ec0d | 42 | { "4\00012", 4.0, '\0', 0 }, |
fb5663ca | 43 | { "5.9e-76", 5.9e-76, '\0', 0 }, |
cd33623e | 44 | { "0x1.4p+3", 10.0, '\0', 0 }, |
2aa562e8 UD |
45 | { "0xAp0", 10.0, '\0', 0 }, |
46 | { "0x0Ap0", 10.0, '\0', 0 }, | |
cd33623e | 47 | { "0x0A", 10.0, '\0', 0 }, |
6491b809 UD |
48 | { "0xA0", 160.0, '\0', 0 }, |
49 | { "0x0.A0p8", 160.0, '\0', 0 }, | |
50 | { "0x0.50p9", 160.0, '\0', 0 }, | |
51 | { "0x0.28p10", 160.0, '\0', 0 }, | |
52 | { "0x0.14p11", 160.0, '\0', 0 }, | |
53 | { "0x0.0A0p12", 160.0, '\0', 0 }, | |
54 | { "0x0.050p13", 160.0, '\0', 0 }, | |
55 | { "0x0.028p14", 160.0, '\0', 0 }, | |
56 | { "0x0.014p15", 160.0, '\0', 0 }, | |
57 | { "0x00.00A0p16", 160.0, '\0', 0 }, | |
58 | { "0x00.0050p17", 160.0, '\0', 0 }, | |
59 | { "0x00.0028p18", 160.0, '\0', 0 }, | |
60 | { "0x00.0014p19", 160.0, '\0', 0 }, | |
eab1830e AJ |
61 | { "0x1p-1023", |
62 | 1.11253692925360069154511635866620203210960799023116591527666e-308, | |
2a27fd6d | 63 | '\0', 0 }, |
eab1830e AJ |
64 | { "0x0.8p-1022", |
65 | 1.11253692925360069154511635866620203210960799023116591527666e-308, | |
2a27fd6d | 66 | '\0', 0 }, |
a529b416 UD |
67 | { "Inf", HUGE_VAL, '\0', 0 }, |
68 | { "-Inf", -HUGE_VAL, '\0', 0 }, | |
69 | { "+InFiNiTy", HUGE_VAL, '\0', 0 }, | |
85b5767c | 70 | { "0x80000Ap-23", 0x80000Ap-23, '\0', 0 }, |
04d08991 | 71 | { "1e-324", 0, '\0', ERANGE }, |
8f203e6c JM |
72 | { "0x100000000000008p0", 0x1p56, '\0', 0 }, |
73 | { "0x100000000000008.p0", 0x1p56, '\0', 0 }, | |
74 | { "0x100000000000008.00p0", 0x1p56, '\0', 0 }, | |
75 | { "0x10000000000000800p0", 0x1p64, '\0', 0 }, | |
76 | { "0x10000000000000801p0", 0x1.0000000000001p64, '\0', 0 }, | |
28f540f4 RM |
77 | { NULL, 0, '\0', 0 } |
78 | }; | |
79 | ||
46827b5c UD |
80 | static void expand (char *dst, int c); |
81 | static int long_dbl (void); | |
dc5fd907 | 82 | static int locale_test (void); |
28f540f4 | 83 | |
c1f41083 AS |
84 | static int |
85 | do_test (void) | |
28f540f4 | 86 | { |
936365c1 | 87 | char buf[100]; |
2e09a79a | 88 | const struct ltest *lt; |
28f540f4 RM |
89 | char *ep; |
90 | int status = 0; | |
5ae9d168 | 91 | int save_errno; |
28f540f4 RM |
92 | |
93 | for (lt = tests; lt->str != NULL; ++lt) | |
94 | { | |
95 | double d; | |
96 | ||
97 | errno = 0; | |
98 | d = strtod(lt->str, &ep); | |
5ae9d168 UD |
99 | save_errno = errno; |
100 | printf ("strtod (\"%s\") test %u", | |
28f540f4 | 101 | lt->str, (unsigned int) (lt - tests)); |
5ae9d168 UD |
102 | if (d == lt->expect && *ep == lt->left && save_errno == lt->err) |
103 | puts ("\tOK"); | |
28f540f4 RM |
104 | else |
105 | { | |
5ae9d168 | 106 | puts ("\tBAD"); |
28f540f4 | 107 | if (d != lt->expect) |
5ae9d168 | 108 | printf (" returns %.60g, expected %.60g\n", d, lt->expect); |
28f540f4 RM |
109 | if (lt->left != *ep) |
110 | { | |
111 | char exp1[5], exp2[5]; | |
5ae9d168 UD |
112 | expand (exp1, *ep); |
113 | expand (exp2, lt->left); | |
114 | printf (" leaves '%s', expected '%s'\n", exp1, exp2); | |
28f540f4 | 115 | } |
5ae9d168 UD |
116 | if (save_errno != lt->err) |
117 | printf (" errno %d (%s) instead of %d (%s)\n", | |
118 | save_errno, strerror (save_errno), | |
119 | lt->err, strerror (lt->err)); | |
28f540f4 RM |
120 | status = 1; |
121 | } | |
122 | } | |
123 | ||
936365c1 UD |
124 | sprintf (buf, "%f", strtod ("-0.0", NULL)); |
125 | if (strcmp (buf, "-0.000000") != 0) | |
126 | { | |
431c33c0 | 127 | printf (" strtod (\"-0.0\", NULL) returns \"%s\"\n", buf); |
936365c1 UD |
128 | status = 1; |
129 | } | |
130 | ||
b5f7b119 UD |
131 | const char input[] = "3752432815e-39"; |
132 | ||
133 | float f1 = strtold (input, NULL); | |
134 | float f2; | |
135 | float f3 = strtof (input, NULL); | |
136 | sscanf (input, "%g", &f2); | |
137 | ||
138 | if (f1 != f2) | |
139 | { | |
140 | printf ("f1 = %a != f2 = %a\n", f1, f2); | |
141 | status = 1; | |
142 | } | |
143 | if (f1 != f3) | |
144 | { | |
145 | printf ("f1 = %a != f3 = %a\n", f1, f3); | |
146 | status = 1; | |
147 | } | |
148 | if (f2 != f3) | |
149 | { | |
150 | printf ("f2 = %a != f3 = %a\n", f2, f3); | |
151 | status = 1; | |
152 | } | |
153 | ||
286a45c5 | 154 | const char input2[] = "+1.000000000116415321826934814453125"; |
c53320c0 | 155 | if (strtold (input2, NULL) != +1.000000000116415321826934814453125L) |
286a45c5 UD |
156 | { |
157 | printf ("input2: %La != %La\n", strtold (input2, NULL), | |
fa4a36fd | 158 | +1.000000000116415321826934814453125L); |
286a45c5 UD |
159 | status = 1; |
160 | } | |
161 | ||
deddf809 UD |
162 | static struct { const char *str; long double l; } ltests[] = |
163 | { | |
164 | { "42.0000000000000000001", 42.0000000000000000001L }, | |
165 | { "42.00000000000000000001", 42.00000000000000000001L }, | |
166 | { "42.000000000000000000001", 42.000000000000000000001L } | |
167 | }; | |
168 | int n; | |
169 | for (n = 0; n < sizeof (ltests) / sizeof (ltests[0]); ++n) | |
170 | if (strtold (ltests[n].str, NULL) != ltests[n].l) | |
171 | { | |
172 | printf ("ltests[%d]: %La != %La\n", n, | |
173 | strtold (ltests[n].str, NULL), ltests[n].l); | |
174 | status = 1; | |
175 | } | |
176 | ||
46827b5c UD |
177 | status |= long_dbl (); |
178 | ||
dc5fd907 UD |
179 | status |= locale_test (); |
180 | ||
bf4de8f3 | 181 | return status ? EXIT_FAILURE : EXIT_SUCCESS; |
28f540f4 RM |
182 | } |
183 | ||
184 | static void | |
9d46370c | 185 | expand (char *dst, int c) |
28f540f4 | 186 | { |
5ae9d168 | 187 | if (isprint (c)) |
28f540f4 RM |
188 | { |
189 | dst[0] = c; | |
190 | dst[1] = '\0'; | |
191 | } | |
192 | else | |
5ae9d168 | 193 | (void) sprintf (dst, "%#.3o", (unsigned int) c); |
28f540f4 | 194 | } |
46827b5c UD |
195 | |
196 | static int | |
197 | long_dbl (void) | |
198 | { | |
2827300f UD |
199 | /* Regenerate this string using |
200 | ||
201 | echo '(2^53-1)*2^(1024-53)' | bc | sed 's/\([^\]*\)\\*$/ "\1"/' | |
202 | ||
203 | */ | |
204 | static const char longestdbl[] = | |
205 | "17976931348623157081452742373170435679807056752584499659891747680315" | |
206 | "72607800285387605895586327668781715404589535143824642343213268894641" | |
207 | "82768467546703537516986049910576551282076245490090389328944075868508" | |
208 | "45513394230458323690322294816580855933212334827479782620414472316873" | |
209 | "8177180919299881250404026184124858368"; | |
46827b5c UD |
210 | double d = strtod (longestdbl, NULL); |
211 | ||
212 | printf ("strtod (\"%s\", NULL) = %g\n", longestdbl, d); | |
213 | ||
214 | if (d != 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000) | |
215 | return 1; | |
216 | ||
217 | return 0; | |
218 | } | |
dc5fd907 UD |
219 | |
220 | /* Perform a few tests in a locale with thousands separators. */ | |
221 | static int | |
222 | locale_test (void) | |
223 | { | |
224 | static const struct | |
225 | { | |
226 | const char *loc; | |
227 | const char *str; | |
228 | double exp; | |
229 | ptrdiff_t nread; | |
230 | } tests[] = | |
231 | { | |
232 | { "de_DE.UTF-8", "1,5", 1.5, 3 }, | |
233 | { "de_DE.UTF-8", "1.5", 1.0, 1 }, | |
234 | { "de_DE.UTF-8", "1.500", 1500.0, 5 }, | |
235 | { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65, 26 } | |
236 | }; | |
237 | #define ntests (sizeof (tests) / sizeof (tests[0])) | |
238 | size_t n; | |
239 | int result = 0; | |
240 | ||
241 | puts ("\nLocale tests"); | |
242 | ||
243 | for (n = 0; n < ntests; ++n) | |
244 | { | |
245 | double d; | |
246 | char *endp; | |
247 | ||
248 | if (setlocale (LC_ALL, tests[n].loc) == NULL) | |
249 | { | |
250 | printf ("cannot set locale %s\n", tests[n].loc); | |
251 | result = 1; | |
252 | continue; | |
253 | } | |
254 | ||
255 | /* We call __strtod_interal here instead of strtod to tests the | |
256 | handling of grouping. */ | |
257 | d = __strtod_internal (tests[n].str, &endp, 1); | |
258 | if (d != tests[n].exp) | |
259 | { | |
260 | printf ("strtod(\"%s\") returns %g and not %g\n", | |
261 | tests[n].str, d, tests[n].exp); | |
262 | result = 1; | |
263 | } | |
264 | else if (endp - tests[n].str != tests[n].nread) | |
265 | { | |
266 | printf ("strtod(\"%s\") read %td bytes and not %td\n", | |
267 | tests[n].str, endp - tests[n].str, tests[n].nread); | |
268 | result = 1; | |
269 | } | |
270 | } | |
271 | ||
272 | if (result == 0) | |
273 | puts ("all OK"); | |
274 | ||
275 | return result; | |
276 | } | |
c1f41083 AS |
277 | |
278 | #define TEST_FUNCTION do_test () | |
279 | #include "../test-skeleton.c" |