]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/from_chars/4.cc
libstdc++: Add std::from_chars for floating-point types
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / from_chars / 4.cc
1 // Copyright (C) 2020 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8
9 // This 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
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 // <charconv> is supported in C++14 as a GNU extension
19 // { dg-do run { target c++14 } }
20
21 #include <charconv>
22 #include <string>
23 #include <limits>
24 #include <cmath>
25 #include <cstdlib>
26 #include <testsuite_hooks.h>
27
28 // Test std::from_chars floating-point conversions.
29
30 void
31 test01()
32 {
33 std::string s;
34 double d;
35 std::from_chars_result res;
36
37 for (auto fmt : { std::chars_format::fixed, std::chars_format::scientific,
38 std::chars_format::general, std::chars_format::hex })
39 {
40 s = "Info";
41 res = std::from_chars(s.data(), s.data() + s.length(), d, fmt);
42 VERIFY( std::isinf(d) );
43 VERIFY( res.ptr == s.data() + 3 );
44 VERIFY( res.ec == std::errc{} );
45
46 s = "-INFIN";
47 res = std::from_chars(s.data(), s.data() + s.length(), d, fmt);
48 VERIFY( std::isinf(d) );
49 VERIFY( d < 0 );
50 VERIFY( res.ptr == s.data() + 4 );
51 VERIFY( res.ec == std::errc{} );
52
53 s = "InFiNiTy aNd BeYoNd";
54 res = std::from_chars(s.data(), s.data() + s.length(), d, fmt);
55 VERIFY( std::isinf(d) );
56 VERIFY( res.ptr == s.data() + 8 );
57 VERIFY( res.ec == std::errc{} );
58
59 s = "nAn";
60 res = std::from_chars(s.data(), s.data() + s.length(), d, fmt);
61 VERIFY( std::isnan(d) );
62 VERIFY( res.ptr == s.data() + 3 );
63 VERIFY( res.ec == std::errc{} );
64
65 s = "-NAN()";
66 res = std::from_chars(s.data(), s.data() + s.length(), d, fmt);
67 VERIFY( std::isnan(d) );
68 VERIFY( res.ptr == s.data() + s.length() );
69 VERIFY( res.ec == std::errc{} );
70 }
71 }
72
73 void
74 test02()
75 {
76 std::string s;
77 double d = 1.0;
78 std::from_chars_result res;
79
80 s = "0x123";
81 res = std::from_chars(s.data(), s.data() + s.length(), d);
82 VERIFY( d == 0.0 );
83 VERIFY( res.ptr == s.data() + 1 );
84 VERIFY( res.ec == std::errc{} );
85
86 d = 1.0;
87 res = std::from_chars(s.data(), s.data() + s.length(), d,
88 std::chars_format::fixed);
89 VERIFY( d == 0.0 );
90 VERIFY( res.ptr == s.data() + 1 );
91 VERIFY( res.ec == std::errc{} );
92
93 d = 1.0;
94 res = std::from_chars(s.data(), s.data() + s.length(), d,
95 std::chars_format::scientific);
96 VERIFY( d == 1.0 );
97 VERIFY( res.ptr == s.data() );
98 VERIFY( res.ec == std::errc::invalid_argument );
99
100 d = 1.0;
101 res = std::from_chars(s.data(), s.data() + s.length(), d,
102 std::chars_format::general);
103 VERIFY( d == 0.0 );
104 VERIFY( res.ptr == s.data() + 1 );
105 VERIFY( res.ec == std::errc{} );
106
107 d = 1.0;
108 res = std::from_chars(s.data(), s.data() + s.length(), d,
109 std::chars_format::hex);
110 VERIFY( d == 0.0 );
111 VERIFY( res.ptr == s.data() + 1 );
112 VERIFY( res.ec == std::errc{} );
113 }
114
115 void
116 test03()
117 {
118 std::string s;
119 double d = 1.0;
120 std::from_chars_result res;
121
122 s = "0.5e+2azzz";
123 res = std::from_chars(s.data(), s.data() + s.length(), d);
124 VERIFY( d == 0.5e+2 );
125 VERIFY( res.ptr == s.data() + s.length() - 1 - 3 );
126 VERIFY( res.ec == std::errc{} );
127
128 res = std::from_chars(s.data(), s.data() + s.length(), d,
129 std::chars_format::fixed);
130 VERIFY( d == 0.5 );
131 VERIFY( res.ptr == s.data() + 3 );
132 VERIFY( res.ec == std::errc{} );
133
134 d = 1.0;
135 res = std::from_chars(s.data(), s.data() + s.length(), d,
136 std::chars_format::scientific);
137 VERIFY( d == 0.5e+2 );
138 VERIFY( res.ptr == s.data() + s.length() - 1 - 3 );
139 VERIFY( res.ec == std::errc{} );
140
141 d = 1.0;
142 res = std::from_chars(s.data(), s.data() + s.length(), d,
143 std::chars_format::general);
144 VERIFY( d == 0.5e+2 );
145 VERIFY( res.ptr == s.data() + s.length() - 1 - 3 );
146 VERIFY( res.ec == std::errc{} );
147
148 d = 1.0;
149 res = std::from_chars(s.data(), s.data() + s.length(), d,
150 std::chars_format::hex);
151 VERIFY( d == 0x0.5Ep0 );
152 VERIFY( res.ptr == s.data() + 4 );
153 VERIFY( res.ec == std::errc{} );
154
155 s = "1.Ap-2zzz";
156 res = std::from_chars(s.data(), s.data() + s.length(), d,
157 std::chars_format::hex);
158 VERIFY( d == 0.40625 );
159 VERIFY( res.ptr == s.data() + s.length() - 3 );
160 VERIFY( res.ec == std::errc{} );
161 }
162
163 void
164 test04()
165 {
166 // Huge input strings
167 std::string s(1000, '0');
168 double d = 1.0;
169 std::from_chars_result res;
170 res = std::from_chars(s.data(), s.data() + s.length(), d);
171 VERIFY( res.ptr == s.data() + s.length() );
172 VERIFY( res.ec == std::errc{} );
173 VERIFY( d == 0.0 );
174
175 s += ".5";
176 res = std::from_chars(s.data(), s.data() + s.length(), d);
177 VERIFY( res.ptr == s.data() + s.length() );
178 VERIFY( res.ec == std::errc{} );
179 VERIFY( d == 0.5 );
180
181 s += "e2";
182 auto len = s.length();
183 s += std::string(1000, 'a');
184 res = std::from_chars(s.data(), s.data() + s.length(), d);
185 VERIFY( res.ptr == s.data() + len );
186 VERIFY( res.ec == std::errc{} );
187 VERIFY( d == 50 );
188 }
189
190 using std::to_string;
191
192 #ifdef __GLIBCXX_TYPE_INT_N_0
193 std::string
194 to_string(unsigned __GLIBCXX_TYPE_INT_N_0 val)
195 {
196 using Limits = std::numeric_limits<unsigned __GLIBCXX_TYPE_INT_N_0>;
197 std::string s(Limits::digits10+2, '0');
198 for (auto iter = s.end(); val != 0; val /= 10)
199 *--iter = '0' + (val % 10);
200 return s;
201 }
202 #endif
203
204 void
205 test05()
206 {
207 std::from_chars_result res;
208 float flt;
209 double dbl;
210 long double ldbl;
211
212 // Small integer values that are exactly representable
213
214 for (int i = 0; i < 100; ++i)
215 {
216 std::string s = to_string(i);
217 int len = s.length();
218 s += "123";
219 const char* s1 = s.c_str();
220 const char* s1_end = s1 + len;
221
222 for (auto fmt : { std::chars_format::fixed,
223 std::chars_format::general,
224 std::chars_format::hex })
225 {
226 if (fmt == std::chars_format::hex && i > 9)
227 continue;
228
229 res = std::from_chars(s1, s1_end, flt, fmt);
230 VERIFY( res.ec == std::errc{} );
231 VERIFY( res.ptr == s1_end );
232 VERIFY( flt == i );
233
234 res = std::from_chars(s1, s1_end, dbl, fmt);
235 VERIFY( res.ec == std::errc{} );
236 VERIFY( res.ptr == s1_end );
237 VERIFY( dbl == i );
238
239 res = std::from_chars(s1, s1_end, ldbl, fmt);
240 VERIFY( res.ec == std::errc{} );
241 VERIFY( res.ptr == s1_end );
242 VERIFY( ldbl == i );
243 }
244
245 if (i > 9)
246 continue;
247
248 // Test single-digit integers with small exponents.
249
250 const char s2[] = { '.', *s1, 'e', '0', '0', '0', '1' };
251 const char* s2_end = s2 + sizeof(s2);
252
253 const char s3[] = { *s1, '0', 'e', '-', '0', '0', '1' };
254 const char* s3_end = s3 + sizeof(s3);
255
256 for (auto fmt : { std::chars_format::scientific,
257 std::chars_format::general })
258 {
259 res = std::from_chars(s2, s2_end, flt, fmt);
260 VERIFY( res.ec == std::errc{} );
261 VERIFY( res.ptr == s2_end );
262 VERIFY( flt == i );
263
264 res = std::from_chars(s3, s3_end, flt, fmt);
265 VERIFY( res.ec == std::errc{} );
266 VERIFY( res.ptr == s3_end );
267 VERIFY( flt == i );
268
269 res = std::from_chars(s2, s2_end, dbl, fmt);
270 VERIFY( res.ec == std::errc{} );
271 VERIFY( res.ptr == s2_end );
272 VERIFY( dbl == i );
273
274 res = std::from_chars(s3, s3_end, dbl, fmt);
275 VERIFY( res.ec == std::errc{} );
276 VERIFY( res.ptr == s3_end );
277 VERIFY( dbl == i );
278
279 res = std::from_chars(s2, s2_end, ldbl, fmt);
280 VERIFY( res.ec == std::errc{} );
281 VERIFY( res.ptr == s2_end );
282 VERIFY( ldbl == i );
283
284 res = std::from_chars(s3, s3_end, ldbl, fmt);
285 VERIFY( res.ec == std::errc{} );
286 VERIFY( res.ptr == s3_end );
287 VERIFY( ldbl == i );
288 }
289 }
290 }
291
292 template<typename FloatT, typename UIntT>
293 void
294 test_max_mantissa()
295 {
296 using Float_limits = std::numeric_limits<FloatT>;
297 using UInt_limits = std::numeric_limits<UIntT>;
298
299 if constexpr (Float_limits::is_iec559
300 && Float_limits::digits < UInt_limits::digits)
301 {
302 std::printf("Testing %d-bit float, using %zu-bit integer\n",
303 Float_limits::digits + (int)std::log2(Float_limits::max_exponent) + 1,
304 sizeof(UIntT) * __CHAR_BIT__);
305
306 std::from_chars_result res;
307 FloatT flt;
308
309 for (int i = 0; i < 10; ++i)
310 {
311 // (1 << digits) - 1 is the maximum value of the mantissa
312 const auto val = ((UIntT)1 << Float_limits::digits) - 1 - i;
313 std::string s = to_string(val);
314 auto len = s.length();
315 s += "000"; // these should be ignored
316 for (auto fmt : { std::chars_format::fixed,
317 std::chars_format::general })
318 {
319 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
320 VERIFY( res.ec == std::errc{} );
321 VERIFY( res.ptr == s.data() + len );
322 VERIFY( flt == val );
323 }
324 s.resize(len);
325 const auto orig_len = len;
326 s += "e+000";
327 len = s.length();
328 s += "111";
329 for (auto fmt : { std::chars_format::scientific,
330 std::chars_format::general })
331 {
332 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
333 VERIFY( res.ec == std::errc{} );
334 VERIFY( res.ptr == s.data() + len );
335 VERIFY( flt == val );
336
337 std::string s2 = s.substr(0, len - 5);
338 s2.insert(s2.cbegin() + orig_len - 1, '.');
339 s2 += "e000000000001";
340 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
341 VERIFY( res.ec == std::errc{} );
342 VERIFY( res.ptr == s.data() + len );
343 VERIFY( flt == val );
344 }
345 }
346 }
347 }
348
349 void
350 test06()
351 {
352 test_max_mantissa<float, unsigned long>();
353 test_max_mantissa<double, unsigned long long>();
354 #ifdef __GLIBCXX_TYPE_INT_N_0
355 test_max_mantissa<long double, unsigned __GLIBCXX_TYPE_INT_N_0>();
356 #endif
357 }
358
359 int
360 main()
361 {
362 test01();
363 test02();
364 test03();
365 test04();
366 test05();
367 test06();
368 }