]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/20_util/from_chars/8.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / from_chars / 8.cc
CommitLineData
a945c346 1// Copyright (C) 2020-2024 Free Software Foundation, Inc.
29ef50b6
JJ
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
29ef50b6
JJ
18// { dg-do run { target c++23 } }
19// { dg-add-options ieee }
20
21#include <charconv>
22#include <string>
23#include <limits>
24#include <stdfloat>
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#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
33void
34test01()
35{
36 std::string s;
37 std::float64_t f64;
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(), f64, fmt);
45 VERIFY( std::isinf(f64) );
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(), f64, fmt);
51 VERIFY( std::isinf(f64) );
52 VERIFY( f64 < 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(), f64, fmt);
58 VERIFY( std::isinf(f64) );
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(), f64, fmt);
64 VERIFY( std::isnan(f64) );
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(), f64, fmt);
70 VERIFY( std::isnan(f64) );
71 VERIFY( res.ptr == s.data() + s.length() );
72 VERIFY( res.ec == std::errc{} );
73 }
74}
75
76void
77test02()
78{
79 std::string s;
80 std::float64_t f64 = 1.0f64;
81 std::from_chars_result res;
82
83 s = "0x123";
84 res = std::from_chars(s.data(), s.data() + s.length(), f64);
85 VERIFY( f64 == 0.0f64 );
86 VERIFY( res.ptr == s.data() + 1 );
87 VERIFY( res.ec == std::errc{} );
88
89 f64 = 1.0f64;
90 res = std::from_chars(s.data(), s.data() + s.length(), f64,
91 std::chars_format::fixed);
92 VERIFY( f64 == 0.0f64 );
93 VERIFY( res.ptr == s.data() + 1 );
94 VERIFY( res.ec == std::errc{} );
95
96 f64 = 1.0f64;
97 res = std::from_chars(s.data(), s.data() + s.length(), f64,
98 std::chars_format::scientific);
99 VERIFY( f64 == 1.0f64 );
100 VERIFY( res.ptr == s.data() );
101 VERIFY( res.ec == std::errc::invalid_argument );
102
103 f64 = 1.0f64;
104 res = std::from_chars(s.data(), s.data() + s.length(), f64,
105 std::chars_format::general);
106 VERIFY( f64 == 0.0f64 );
107 VERIFY( res.ptr == s.data() + 1 );
108 VERIFY( res.ec == std::errc{} );
109
110 f64 = 1.0f64;
111 res = std::from_chars(s.data(), s.data() + s.length(), f64,
112 std::chars_format::hex);
113 VERIFY( f64 == 0.0f64 );
114 VERIFY( res.ptr == s.data() + 1 );
115 VERIFY( res.ec == std::errc{} );
116}
117
118void
119test03()
120{
121 std::string s;
122 std::float64_t f64 = 1.0f64;
123 std::from_chars_result res;
124
125 s = "0.5e+2azzz";
126 res = std::from_chars(s.data(), s.data() + s.length(), f64);
127 VERIFY( f64 == 0.5e+2f64 );
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(), f64,
132 std::chars_format::fixed);
133 VERIFY( f64 == 0.5f64 );
134 VERIFY( res.ptr == s.data() + 3 );
135 VERIFY( res.ec == std::errc{} );
136
137 f64 = 1.0f64;
138 res = std::from_chars(s.data(), s.data() + s.length(), f64,
139 std::chars_format::scientific);
140 VERIFY( f64 == 0.5e+2f64 );
141 VERIFY( res.ptr == s.data() + s.length() - 1 - 3 );
142 VERIFY( res.ec == std::errc{} );
143
144 f64 = 1.0f64;
145 res = std::from_chars(s.data(), s.data() + s.length(), f64,
146 std::chars_format::general);
147 VERIFY( f64 == 0.5e+2f64 );
148 VERIFY( res.ptr == s.data() + s.length() - 1 - 3 );
149 VERIFY( res.ec == std::errc{} );
150
151 f64 = 1.0;
152 res = std::from_chars(s.data(), s.data() + s.length(), f64,
153 std::chars_format::hex);
154 VERIFY( f64 == 0x0.5Ep0f64 );
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(), f64,
160 std::chars_format::hex);
161 VERIFY( f64 == 0.40625f64 );
162 VERIFY( res.ptr == s.data() + s.length() - 3 );
163 VERIFY( res.ec == std::errc{} );
164}
165
166void
167test04()
168{
169 // Huge input strings
170 std::string s(1000, '0');
171 std::float64_t f64 = 1.0f64;
172 std::from_chars_result res;
173 res = std::from_chars(s.data(), s.data() + s.length(), f64);
174 VERIFY( res.ptr == s.data() + s.length() );
175 VERIFY( res.ec == std::errc{} );
176 VERIFY( f64 == 0.0f64 );
177
178 s += ".5";
179 res = std::from_chars(s.data(), s.data() + s.length(), f64);
180 VERIFY( res.ptr == s.data() + s.length() );
181 VERIFY( res.ec == std::errc{} );
182 VERIFY( f64 == 0.5f64 );
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(), f64);
188 VERIFY( res.ptr == s.data() + len );
189 VERIFY( res.ec == std::errc{} );
190 VERIFY( f64 == 50.f64 );
191}
192#endif
193
194using std::to_string;
195
196#ifdef __GLIBCXX_TYPE_INT_N_0
197std::string
198to_string(unsigned __GLIBCXX_TYPE_INT_N_0 val)
199{
200 using Limits = std::numeric_limits<unsigned __GLIBCXX_TYPE_INT_N_0>;
201 std::string s(Limits::digits10+2, '0');
202 for (auto iter = s.end(); val != 0; val /= 10)
203 *--iter = '0' + (val % 10);
204 return s;
205}
206#endif
207
208template<typename FloatT>
209void
210test_small_num()
211{
212 std::from_chars_result res;
213 FloatT flt;
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
238 if (i > 9)
239 continue;
240
241 // Test single-digit integers with small exponents.
242
243 const char s2[] = { '.', *s1, 'e', '0', '0', '0', '1' };
244 const char* s2_end = s2 + sizeof(s2);
245
246 const char s3[] = { *s1, '0', 'e', '-', '0', '0', '1' };
247 const char* s3_end = s3 + sizeof(s3);
248
249 for (auto fmt : { std::chars_format::scientific,
250 std::chars_format::general })
251 {
252 res = std::from_chars(s2, s2_end, flt, fmt);
253 VERIFY( res.ec == std::errc{} );
254 VERIFY( res.ptr == s2_end );
255 VERIFY( flt == i );
256
257 res = std::from_chars(s3, s3_end, flt, fmt);
258 VERIFY( res.ec == std::errc{} );
259 VERIFY( res.ptr == s3_end );
260 VERIFY( flt == i );
261 }
262 }
263}
264
265void
266test05()
267{
268#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
269 test_small_num<std::float32_t>();
270#endif
271#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
272 test_small_num<std::float64_t>();
273#endif
274#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
275 test_small_num<std::float128_t>();
276#endif
277}
278
279template<typename FloatT, typename UIntT>
280void
281test_max_mantissa()
282{
283 using Float_limits = std::numeric_limits<FloatT>;
284 using UInt_limits = std::numeric_limits<UIntT>;
285
286 if (Float_limits::is_iec559 && Float_limits::digits < UInt_limits::digits)
287 {
1f378f6d 288#ifdef _GLIBCXX_USE_C99_MATH_FUNCS
29ef50b6
JJ
289 std::printf("Testing %d-bit float, using %zu-bit integer\n",
290 Float_limits::digits + (int)std::log2(Float_limits::max_exponent) + 1,
291 sizeof(UIntT) * __CHAR_BIT__);
292#endif
293
294 std::from_chars_result res;
295 FloatT flt;
296
297 for (int i = 0; i < 10; ++i)
298 {
299 // (1 << digits) - 1 is the maximum value of the mantissa
300 const auto val = ((UIntT)1 << Float_limits::digits) - 1 - i;
301 std::string s = to_string(val);
302 auto len = s.length();
303 s += "000"; // these should be ignored
304 for (auto fmt : { std::chars_format::fixed,
305 std::chars_format::general })
306 {
307 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
308 VERIFY( res.ec == std::errc{} );
309 VERIFY( res.ptr == s.data() + len );
310 VERIFY( flt == val );
311 }
312 s.resize(len);
313 const auto orig_len = len;
314 s += "e+000";
315 len = s.length();
316 s += "111";
317 for (auto fmt : { std::chars_format::scientific,
318 std::chars_format::general })
319 {
320 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
321 VERIFY( res.ec == std::errc{} );
322 VERIFY( res.ptr == s.data() + len );
323 VERIFY( flt == val );
324
325 std::string s2 = s.substr(0, len - 5);
326 s2.insert(s2.begin() + orig_len - 1, '.');
327 s2 += "e000000000001";
328 res = std::from_chars(s.data(), s.data() + len, flt, fmt);
329 VERIFY( res.ec == std::errc{} );
330 VERIFY( res.ptr == s.data() + len );
331 VERIFY( flt == val );
332 }
333 }
334 }
335}
336
337void
338test06()
339{
340#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
341 test_max_mantissa<std::float32_t, unsigned long>();
342#endif
343#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
344 test_max_mantissa<std::float64_t, unsigned long long>();
345#endif
346#if defined(__GLIBCXX_TYPE_INT_N_0) \
347 && defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
348 test_max_mantissa<std::float128_t, unsigned __GLIBCXX_TYPE_INT_N_0>();
349#endif
350}
351#endif
352
353int
354main()
355{
356#if __cpp_lib_to_chars >= 201611L
357#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
358 test01();
359 test02();
360 test03();
361 test04();
362#endif
363 test05();
364 test06();
365#endif
366}