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