1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
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)
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.
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/>.
18 // { dg-do run { target c++23 } }
19 // { dg-add-options ieee }
27 #include <testsuite_hooks.h>
29 // Test std::from_chars floating-point conversions.
31 #if __cpp_lib_to_chars >= 201611L
32 #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
38 std::from_chars_result res
;
40 for (auto fmt
: { std::chars_format::fixed
, std::chars_format::scientific
,
41 std::chars_format::general
, std::chars_format::hex
})
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
{} );
50 res
= std::from_chars(s
.data(), s
.data() + s
.length(), f64
, fmt
);
51 VERIFY( std::isinf(f64
) );
53 VERIFY( res
.ptr
== s
.data() + 4 );
54 VERIFY( res
.ec
== std::errc
{} );
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
{} );
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
{} );
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
{} );
80 std::float64_t f64
= 1.0f64
;
81 std::from_chars_result res
;
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
{} );
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
{} );
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
);
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
{} );
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
{} );
122 std::float64_t f64
= 1.0f64
;
123 std::from_chars_result res
;
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
{} );
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
{} );
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
{} );
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
{} );
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
{} );
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
{} );
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
);
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
);
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
);
194 using std::to_string
;
196 #ifdef __GLIBCXX_TYPE_INT_N_0
198 to_string(unsigned __GLIBCXX_TYPE_INT_N_0 val
)
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);
208 template<typename FloatT
>
212 std::from_chars_result res
;
215 // Small integer values that are exactly representable
217 for (int i
= 0; i
< 100; ++i
)
219 std::string s
= to_string(i
);
220 int len
= s
.length();
222 const char* s1
= s
.c_str();
223 const char* s1_end
= s1
+ len
;
225 for (auto fmt
: { std::chars_format::fixed
,
226 std::chars_format::general
,
227 std::chars_format::hex
})
229 if (fmt
== std::chars_format::hex
&& i
> 9)
232 res
= std::from_chars(s1
, s1_end
, flt
, fmt
);
233 VERIFY( res
.ec
== std::errc
{} );
234 VERIFY( res
.ptr
== s1_end
);
241 // Test single-digit integers with small exponents.
243 const char s2
[] = { '.', *s1
, 'e', '0', '0', '0', '1' };
244 const char* s2_end
= s2
+ sizeof(s2
);
246 const char s3
[] = { *s1
, '0', 'e', '-', '0', '0', '1' };
247 const char* s3_end
= s3
+ sizeof(s3
);
249 for (auto fmt
: { std::chars_format::scientific
,
250 std::chars_format::general
})
252 res
= std::from_chars(s2
, s2_end
, flt
, fmt
);
253 VERIFY( res
.ec
== std::errc
{} );
254 VERIFY( res
.ptr
== s2_end
);
257 res
= std::from_chars(s3
, s3_end
, flt
, fmt
);
258 VERIFY( res
.ec
== std::errc
{} );
259 VERIFY( res
.ptr
== s3_end
);
268 #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
269 test_small_num
<std::float32_t
>();
271 #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
272 test_small_num
<std::float64_t
>();
274 #if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
275 test_small_num
<std::float128_t
>();
279 template<typename FloatT
, typename UIntT
>
283 using Float_limits
= std::numeric_limits
<FloatT
>;
284 using UInt_limits
= std::numeric_limits
<UIntT
>;
286 if (Float_limits::is_iec559
&& Float_limits::digits
< UInt_limits::digits
)
288 #ifdef _GLIBCXX_USE_C99_MATH_FUNCS
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__
);
294 std::from_chars_result res
;
297 for (int i
= 0; i
< 10; ++i
)
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
})
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
);
313 const auto orig_len
= len
;
317 for (auto fmt
: { std::chars_format::scientific
,
318 std::chars_format::general
})
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
);
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
);
340 #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
341 test_max_mantissa
<std::float32_t
, unsigned long>();
343 #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
344 test_max_mantissa
<std::float64_t
, unsigned long long>();
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
>();
356 #if __cpp_lib_to_chars >= 201611L
357 #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)