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