1 // Copyright (c) Microsoft Corporation.
2 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
24 #include <string_view>
25 #include <system_error>
26 #include <type_traits>
30 #include "double_fixed_precision_to_chars_test_cases_1.hpp"
31 #include "double_fixed_precision_to_chars_test_cases_2.hpp"
32 #include "double_fixed_precision_to_chars_test_cases_3.hpp"
33 #include "double_fixed_precision_to_chars_test_cases_4.hpp"
34 #include "double_from_chars_test_cases.hpp"
35 #include "double_general_precision_to_chars_test_cases.hpp"
36 #include "double_hex_precision_to_chars_test_cases.hpp"
37 #include "double_scientific_precision_to_chars_test_cases_1.hpp"
38 #include "double_scientific_precision_to_chars_test_cases_2.hpp"
39 #include "double_scientific_precision_to_chars_test_cases_3.hpp"
40 #include "double_scientific_precision_to_chars_test_cases_4.hpp"
41 #include "double_to_chars_test_cases.hpp"
42 #include "float_fixed_precision_to_chars_test_cases.hpp"
43 #include "float_from_chars_test_cases.hpp"
44 #include "float_general_precision_to_chars_test_cases.hpp"
45 #include "float_hex_precision_to_chars_test_cases.hpp"
46 #include "float_scientific_precision_to_chars_test_cases.hpp"
47 #include "float_to_chars_test_cases.hpp"
48 #include "floating_point_test_cases.hpp"
52 void initialize_randomness(mt19937_64
& mt64
, const int argc
, char** const /*argv*/) {
53 constexpr std::size_t n
= mt19937_64::state_size
;
54 constexpr std::size_t w
= mt19937_64::word_size
;
55 static_assert(w
% 32 == 0);
56 constexpr std::size_t k
= w
/ 32;
58 vector
<std::uint32_t> vec(n
* k
);
61 puts("test.exe : generates seed data from random_device.");
65 generate(vec
.begin(), vec
.end(), ref(rd
));
66 puts("Generated seed data.");
68 puts("ERROR: Too many command-line arguments.");
73 for (const auto& elem
: vec
) {
74 printf("%zu ", static_cast<std::size_t>(elem
));
78 seed_seq
seq(vec
.cbegin(), vec
.cend());
82 puts("Successfully seeded mt64. First three values:");
83 for (int i
= 0; i
< 3; ++i
) {
84 // libc++ uses long for 64-bit values.
85 printf("0x%016llX\n", static_cast<unsigned long long>(mt64()));
89 static_assert((chars_format::scientific
& chars_format::fixed
) == chars_format
{});
90 static_assert((chars_format::scientific
& chars_format::hex
) == chars_format
{});
91 static_assert((chars_format::fixed
& chars_format::hex
) == chars_format
{});
92 static_assert(chars_format::general
== (chars_format::fixed
| chars_format::scientific
));
94 template <typename T
, typename Optional
>
95 void test_common_to_chars(
96 const T value
, const Optional opt_arg
, const optional
<int> opt_precision
, const string_view correct
) {
98 // Important: Test every effective buffer size from 0 through correct.size() and slightly beyond. For the sizes
99 // less than correct.size(), this verifies that the too-small buffer is correctly detected, and that we don't
100 // attempt to write outside of it, even by a single char. (This exhaustive validation is necessary because the
101 // implementation must check whenever it attempts to write. Sometimes we can calculate the total size and perform
102 // a single check, but sometimes we need to check when writing each part of the result.) Testing correct.size()
103 // verifies that we can succeed without overrunning, and testing slightly larger sizes verifies that we can succeed
104 // without attempting to write to extra chars even when they're available. Finally, we also verify that we aren't
105 // underrunning the buffer. This is a concern because sometimes we walk backwards when rounding.
107 constexpr std::size_t BufferPrefix
= 20; // detect buffer underruns (specific value isn't important)
109 constexpr std::size_t Space
= is_integral_v
<T
> ? 1 + 64 // worst case: -2^63 in binary
110 : is_same_v
<T
, float>
111 ? 1 + 151 // worst case: negative min subnormal float, fixed notation
112 : 1 + 1076; // worst case: negative min subnormal double, fixed notation
114 constexpr std::size_t BufferSuffix
= 30; // detect buffer overruns (specific value isn't important)
116 array
<char, BufferPrefix
+ Space
+ BufferSuffix
> buff
;
118 char* const buff_begin
= buff
.data();
119 char* const first
= buff_begin
+ BufferPrefix
;
120 char* const buff_end
= buff_begin
+ buff
.size();
122 constexpr std::size_t ExtraChars
= 3;
123 static_assert(ExtraChars
+ 10 < BufferSuffix
,
124 "The specific values aren't important, but there should be plenty of room to detect buffer overruns.");
126 for (std::size_t n
= 0; n
<= correct
.size() + ExtraChars
; ++n
) {
127 assert(n
<= static_cast<std::size_t>(buff_end
- first
));
128 char* const last
= first
+ n
;
131 const auto is_fill_char
= [](const char c
) { return c
== '@'; };
133 to_chars_result result
{};
134 if (opt_precision
.has_value()) {
135 assert(opt_arg
.has_value());
137 if constexpr (is_floating_point_v
<T
>) {
138 result
= to_chars(first
, last
, value
, opt_arg
.value(), opt_precision
.value());
142 } else if (opt_arg
.has_value()) {
143 result
= to_chars(first
, last
, value
, opt_arg
.value());
145 result
= to_chars(first
, last
, value
);
148 if (n
< correct
.size()) {
149 assert(result
.ptr
== last
);
150 assert(result
.ec
== errc::value_too_large
);
151 assert(all_of(buff_begin
, first
, is_fill_char
));
152 // [first, last) is unspecified
153 assert(all_of(last
, buff_end
, is_fill_char
));
155 assert(result
.ptr
== first
+ correct
.size());
156 assert(result
.ec
== errc
{});
157 assert(all_of(buff_begin
, first
, is_fill_char
));
158 assert(equal(first
, result
.ptr
, correct
.begin(), correct
.end()));
159 assert(all_of(result
.ptr
, buff_end
, is_fill_char
));
164 template <typename T
>
165 void test_integer_to_chars(const T value
, const optional
<int> opt_base
, const string_view correct
) {
167 test_common_to_chars(value
, opt_base
, nullopt
, correct
);
169 { // Also test successful from_chars() scenarios.
170 const char* const correct_first
= correct
.data();
171 const char* const correct_last
= correct_first
+ correct
.size();
175 const from_chars_result from_res
=
176 (opt_base
.has_value() ? from_chars(correct_first
, correct_last
, dest
, opt_base
.value())
177 : from_chars(correct_first
, correct_last
, dest
));
179 assert(from_res
.ptr
== correct_last
);
180 assert(from_res
.ec
== errc
{});
181 assert(dest
== value
);
185 // https://www.wolframalpha.com : Table[BaseForm[n * 2 - 1, n], {n, 2, 36}]
186 constexpr const char* output_max_digit
[] = {"skip0", "skip1", "11", "12", "13", "14", "15", "16", "17", "18", "19",
187 "1a", "1b", "1c", "1d", "1e", "1f", "1g", "1h", "1i", "1j", "1k", "1l", "1m", "1n", "1o", "1p", "1q", "1r", "1s",
188 "1t", "1u", "1v", "1w", "1x", "1y", "1z"};
190 // https://www.wolframalpha.com : Table[BaseForm[k, n], {k, {MEOW, MEOW, MEOW}}, {n, 2, 36}]
191 constexpr std::uint64_t stress_chunks_positive
= 12000000345000678900ULL;
192 constexpr pair
<std::uint64_t, array
<const char*, 37>> output_positive
[] = {
193 {123U, {{"skip0", "skip1", "1111011", "11120", "1323", "443", "323", "234", "173", "146", "123", "102", "a3", "96",
194 "8b", "83", "7b", "74", "6f", "69", "63", "5i", "5d", "58", "53", "4n", "4j", "4f", "4b", "47", "43",
195 "3u", "3r", "3o", "3l", "3i", "3f"}}},
196 {std::uint64_t{INT8_MAX
}, {{"skip0", "skip1", "1111111", "11201", "1333", "1002", "331", "241", "177", "151", "127",
197 "106", "a7", "9a", "91", "87", "7f", "78", "71", "6d", "67", "61", "5h", "5c", "57", "52",
198 "4n", "4j", "4f", "4b", "47", "43", "3v", "3s", "3p", "3m", "3j"}}},
199 {161U, {{"skip0", "skip1", "10100001", "12222", "2201", "1121", "425", "320", "241", "188", "161", "137", "115",
200 "c5", "b7", "ab", "a1", "98", "8h", "89", "81", "7e", "77", "70", "6h", "6b", "65", "5q", "5l", "5g",
201 "5b", "56", "51", "4t", "4p", "4l", "4h"}}},
202 {UINT8_MAX
, {{"skip0", "skip1", "11111111", "100110", "3333", "2010", "1103", "513", "377", "313", "255", "212",
203 "193", "168", "143", "120", "ff", "f0", "e3", "d8", "cf", "c3", "bd", "b2", "af", "a5", "9l", "9c",
204 "93", "8n", "8f", "87", "7v", "7o", "7h", "7a", "73"}}},
205 {1729U, {{"skip0", "skip1", "11011000001", "2101001", "123001", "23404", "12001", "5020", "3301", "2331", "1729",
206 "1332", "1001", "a30", "8b7", "7a4", "6c1", "5gc", "561", "4f0", "469", "3j7", "3cd", "364", "301",
207 "2j4", "2ed", "2a1", "25l", "21i", "1rj", "1oo", "1m1", "1jd", "1gt", "1ee", "1c1"}}},
208 {std::uint64_t{INT16_MAX
}, {{"skip0", "skip1", "111111111111111", "1122221121", "13333333", "2022032", "411411",
209 "164350", "77777", "48847", "32767", "22689", "16b67", "11bb7", "bd27", "9a97", "7fff",
210 "6b68", "5b27", "4eeb", "41i7", "3b67", "31f9", "2flf", "28l7", "22ah", "1mc7", "1hpg",
211 "1dm7", "19rq", "16c7", "1330", "vvv", "u2v", "sbp", "qq7", "pa7"}}},
212 {57494U, {{"skip0", "skip1", "1110000010010110", "2220212102", "32002112", "3314434", "1122102", "326423", "160226",
213 "86772", "57494", "3a218", "29332", "20228", "16d4a", "1207e", "e096", "bbg0", "9f82", "8750", "73ee",
214 "647h", "58h8", "4gfh", "43je", "3goj", "3718", "2onb", "2h9a", "2aag", "23qe", "1spk", "1o4m", "1jq8",
215 "1fp0", "1bwo", "18d2"}}},
216 {UINT16_MAX
, {{"skip0", "skip1", "1111111111111111", "10022220020", "33333333", "4044120", "1223223", "362031",
217 "177777", "108806", "65535", "45268", "31b13", "23aa2", "19c51", "14640", "ffff", "d5d0", "b44f",
218 "9aa4", "83gf", "71cf", "638j", "58k8", "4hif", "44la", "3iof", "38o6", "2rgf", "2jqo", "2cof",
219 "2661", "1vvv", "1r5u", "1mnh", "1ihf", "1ekf"}}},
220 {71125478U, {{"skip0", "skip1", "100001111010100100111100110", "11221211112210222", "10033110213212",
221 "121202003403", "11020244342", "1522361624", "417244746", "157745728", "71125478", "3716a696",
222 "1b9a06b2", "11973ba8", "9636514", "639e338", "43d49e6", "2g19gfb", "21b9d18", "19dec94", "124addi",
223 "h8f25b", "dhdfa6", "b13hg2", "8m91he", "7720j3", "5pgj58", "4pmelq", "43k17i", "3dg8ek", "2ro898",
224 "2f0et8", "23qif6", "1qw5lh", "1j7l7s", "1cdvli", "16cgrq"}}},
225 {std::uint64_t{INT32_MAX
},
226 {{"skip0", "skip1", "1111111111111111111111111111111", "12112122212110202101", "1333333333333333",
227 "13344223434042", "553032005531", "104134211161", "17777777777", "5478773671", "2147483647", "a02220281",
228 "4bb2308a7", "282ba4aaa", "1652ca931", "c87e66b7", "7fffffff", "53g7f548", "3928g3h1", "27c57h32",
229 "1db1f927", "140h2d91", "ikf5bf1", "ebelf95", "b5gge57", "8jmdnkm", "6oj8ion", "5ehncka", "4clm98f",
230 "3hk7987", "2sb6cs7", "2d09uc1", "1vvvvvv", "1lsqtl1", "1d8xqrp", "15v22um", "zik0zj"}}},
232 {{"skip0", "skip1", "11010001111101011110010110111110", "100002111022020200020", "3101331132112332",
233 "24203233201103", "1341312313010", "153202131426", "32175362676", "10074266606", "3522553278", "1548431462",
234 "823842766", "441a34c6a", "255b8d486", "1593b4753", "d1f5e5be", "89ffb3b6", "5da3e606", "3hgbfb5i",
235 "2f0fj33i", "1k1ac536", "191b46e2", "10i6fmk8", "ia967l6", "eahia63", "baca9ga", "92d86i6", "78iq4i6",
236 "5qlc1dc", "4osos2i", "3u1862s", "38vbpdu", "2o0a7ro", "29hx9e6", "1w2dnod", "1m98ji6"}}},
238 {{"skip0", "skip1", "11111111111111111111111111111111", "102002022201221111210", "3333333333333333",
239 "32244002423140", "1550104015503", "211301422353", "37777777777", "12068657453", "4294967295", "1904440553",
240 "9ba461593", "535a79888", "2ca5b7463", "1a20dcd80", "ffffffff", "a7ffda90", "704he7g3", "4f5aff65",
241 "3723ai4f", "281d55i3", "1fj8b183", "1606k7ib", "mb994af", "hek2mgk", "dnchbnl", "b28jpdl", "8pfgih3",
242 "76beigf", "5qmcpqf", "4q0jto3", "3vvvvvv", "3aokq93", "2qhxjlh", "2br45qa", "1z141z3"}}},
244 {{"skip0", "skip1", "1111100000111110000011100001101100000110111110000", "2122120211122121121021010202111",
245 "1330013300130031200313300", "1033022333343024014120", "5213002440142255104", "222661211220253465",
246 "17407603415406760", "2576748547233674", "545890816626160", "148a34aa4706535", "51285369b87494",
247 "1a57a38b045a95", "98b3383b9766c", "4319d1601875a", "1f07c1c360df0", "ffd471f34f13", "88g09ff9dh84",
248 "4d0d5e232c53", "2d63h403i580", "1bf5h8185hdj", "kc3g550fkcg", "d41id5k9984", "8ef5n0him4g", "5i2dijfe1la",
249 "3me22fm5fhi", "2hfmhgg73kd", "1ngpfabr53c", "18i7220bh11", "rm0lcjngpa", "kk1elesni1", "fgfge3c3fg",
250 "bp4q5l6bjg", "8xna46jp0k", "6wejomvji5", "5di2s1qhv4"}}},
251 {std::uint64_t{INT64_MAX
},
252 {{"skip0", "skip1", "111111111111111111111111111111111111111111111111111111111111111",
253 "2021110011022210012102010021220101220221", "13333333333333333333333333333333",
254 "1104332401304422434310311212", "1540241003031030222122211", "22341010611245052052300",
255 "777777777777777777777", "67404283172107811827", "9223372036854775807", "1728002635214590697",
256 "41a792678515120367", "10b269549075433c37", "4340724c6c71dc7a7", "160e2ad3246366807", "7fffffffffffffff",
257 "33d3d8307b214008", "16agh595df825fa7", "ba643dci0ffeehh", "5cbfjia3fh26ja7", "2heiciiie82dh97",
258 "1adaibb21dckfa7", "i6k448cf4192c2", "acd772jnc9l0l7", "64ie1focnn5g77", "3igoecjbmca687", "27c48l5b37oaop",
259 "1bk39f3ah3dmq7", "q1se8f0m04isb", "hajppbc1fc207", "bm03i95hia437", "7vvvvvvvvvvvv", "5hg4ck9jd4u37",
260 "3tdtk1v8j6tpp", "2pijmikexrxp7", "1y2p0ij32e8e7"}}},
261 {stress_chunks_positive
,
262 {{"skip0", "skip1", "1010011010001000100100001011110000101100010101001001010111110100",
263 "2221221122020020011022001202200200202200", "22122020210023300230111021113310",
264 "1301130403021123030133211100", "2311004450342244200504500", "30325064311430214266301",
265 "1232104413605425112764", "87848206138052620680", "12000000345000678900", "2181782a1686924456a",
266 "54aa47a9058877b130", "150593a5b002c87b16", "571cad2b93c7760a8", "1c60d2676d4e53e00", "a68890bc2c5495f4",
267 "43499224707a4f4g", "1e052gdga1d26f40", "f06dh4g564c8a91", "769df0d9ace4h50", "3ee7bcj1ajghi4f",
268 "1k9agc4gfl0l43a", "10id7dakdlcjd22", "dge08fe0l5hl7c", "8184326d31ib60", "4ljbglf3cpim76",
269 "2pph66481kiiki", "1niph2ao132e58", "14qgbgk3c3iffg", "mhc35an1bhb00", "f78o8ur705ln5", "ad24gngm595fk",
270 "76e1n5i5v0ivl", "50wu8jsnks82g", "3ja41smfvqb1f", "2j64t3qgq0ut0"}}},
271 {14454900944617508688ULL,
272 {{"skip0", "skip1", "1100100010011010000111111101001011100011011000101000111101010000",
273 "10120022020112011211121221212101012220210", "30202122013331023203120220331100",
274 "1432224030234034034040234223", "3014532424232535441404120", "34610451042001242144165",
275 "1442320775134330507520", "116266464747855335823", "14454900944617508688", "266642a9a9471339935",
276 "662251403263939640", "1895280092bc310481", "68cb9c8292557406c", "23023deab20002893", "c89a1fd2e3628f50",
277 "50e7147a7db8ef84", "22a34a05086f78ec", "i1dgef04357g7i1", "8g90b882jcj8be8", "49c1kk35i0k24ic",
278 "272a16i54ebkacg", "15fdih7l3m7k8md", "gbj7303eg9nge0", "9hckfdkj3kkdmd", "5lc7hifdkl4nne",
279 "3f86e4mgpna5ol", "266pj428na273c", "1bomgjbnlg4m3f", "r5tf1f7f009ji", "iarsig29iqhhm", "ch6gvqbhm53qg",
280 "8lwtvcdj6rlqr", "61w23lajggp44", "49p1f3dsqqcdx", "31tkqqkxypopc"}}},
282 {{"skip0", "skip1", "1111111111111111111111111111111111111111111111111111111111111111",
283 "11112220022122120101211020120210210211220", "33333333333333333333333333333333",
284 "2214220303114400424121122430", "3520522010102100444244423", "45012021522523134134601",
285 "1777777777777777777777", "145808576354216723756", "18446744073709551615", "335500516a429071284",
286 "839365134a2a240713", "219505a9511a867b72", "8681049adb03db171", "2c1d56b648c6cd110", "ffffffffffffffff",
287 "67979g60f5428010", "2d3fgb0b9cg4bd2f", "141c8786h1ccaagg", "b53bjh07be4dj0f", "5e8g4ggg7g56dif",
288 "2l4lf104353j8kf", "1ddh88h2782i515", "l12ee5fn0ji1if", "c9c336o0mlb7ef", "7b7n2pcniokcgf",
289 "4eo8hfam6fllmo", "2nc6j26l66rhof", "1n3rsh11f098rn", "14l9lkmo30o40f", "nd075ib45k86f", "fvvvvvvvvvvvv",
290 "b1w8p7j5q9r6f", "7orp63sh4dphh", "5g24a25twkwff", "3w5e11264sgsf"}}},
293 // https://www.wolframalpha.com : Table[BaseForm[k, n], {k, {MEOW, MEOW, MEOW}}, {n, 2, 36}]
294 constexpr std::int64_t stress_chunks_negative
= -9000876000000054321LL;
295 constexpr pair
<std::int64_t, array
<const char*, 37>> output_negative
[] = {
296 {-85, {{"skip0", "skip1", "-1010101", "-10011", "-1111", "-320", "-221", "-151", "-125", "-104", "-85", "-78",
297 "-71", "-67", "-61", "-5a", "-55", "-50", "-4d", "-49", "-45", "-41", "-3j", "-3g", "-3d", "-3a", "-37",
298 "-34", "-31", "-2r", "-2p", "-2n", "-2l", "-2j", "-2h", "-2f", "-2d"}}},
299 {INT8_MIN
, {{"skip0", "skip1", "-10000000", "-11202", "-2000", "-1003", "-332", "-242", "-200", "-152", "-128",
300 "-107", "-a8", "-9b", "-92", "-88", "-80", "-79", "-72", "-6e", "-68", "-62", "-5i", "-5d", "-58",
301 "-53", "-4o", "-4k", "-4g", "-4c", "-48", "-44", "-40", "-3t", "-3q", "-3n", "-3k"}}},
302 {-1591, {{"skip0", "skip1", "-11000110111", "-2011221", "-120313", "-22331", "-11211", "-4432", "-3067", "-2157",
303 "-1591", "-1217", "-b07", "-955", "-819", "-711", "-637", "-58a", "-4g7", "-47e", "-3jb", "-3cg",
304 "-367", "-304", "-2i7", "-2dg", "-295", "-24p", "-20n", "-1pp", "-1n1", "-1ka", "-1hn", "-1f7", "-1cr",
306 {INT16_MIN
, {{"skip0", "skip1", "-1000000000000000", "-1122221122", "-20000000", "-2022033", "-411412", "-164351",
307 "-100000", "-48848", "-32768", "-2268a", "-16b68", "-11bb8", "-bd28", "-9a98", "-8000", "-6b69",
308 "-5b28", "-4eec", "-41i8", "-3b68", "-31fa", "-2flg", "-28l8", "-22ai", "-1mc8", "-1hph", "-1dm8",
309 "-19rr", "-16c8", "-1331", "-1000", "-u2w", "-sbq", "-qq8", "-pa8"}}},
311 {{"skip0", "skip1", "-11111110100111111111111100", "-11122121011121102", "-3332213333330", "-114041422122",
312 "-10342352232", "-1440231533", "-376477774", "-148534542", "-66748412", "-34750085", "-1a42b678",
313 "-10aa0803", "-8c1731a", "-5cd7492", "-3fa7ffc", "-2d03163", "-1h5f3b2", "-17i39c6", "-10h3b0c", "-g749jh",
314 "-ckkdkg", "-a8c0ak", "-894afk", "-6klmbc", "-5g1i6g", "-4hg4gb", "-3ogi7o", "-37anqb", "-2mc4r2",
315 "-2a8h7i", "-1vkvvs", "-1n9ca5", "-1fw8sk", "-19gshh", "-13qnek"}}},
316 {INT32_MIN
, {{"skip0", "skip1", "-10000000000000000000000000000000", "-12112122212110202102", "-2000000000000000",
317 "-13344223434043", "-553032005532", "-104134211162", "-20000000000", "-5478773672", "-2147483648",
318 "-a02220282", "-4bb2308a8", "-282ba4aab", "-1652ca932", "-c87e66b8", "-80000000", "-53g7f549",
319 "-3928g3h2", "-27c57h33", "-1db1f928", "-140h2d92", "-ikf5bf2", "-ebelf96", "-b5gge58", "-8jmdnkn",
320 "-6oj8ioo", "-5ehnckb", "-4clm98g", "-3hk7988", "-2sb6cs8", "-2d09uc2", "-2000000", "-1lsqtl2",
321 "-1d8xqrq", "-15v22un", "-zik0zk"}}},
322 {-297139747082649553LL,
323 {{"skip0", "skip1", "-10000011111101001110000011010010001100000101011111111010001",
324 "-1222110012002112101210012211022102101", "-100133221300122101200223333101", "-4443033200104011124241203",
325 "-21313431255203203120401", "-350320603201030412545", "-20375160322140537721", "-1873162471705738371",
326 "-297139747082649553", "-65150976074a24025", "-173522497b5373101", "-5a60a99bc3b71654", "-1ca51a06cc38ba25",
327 "-a2a25babe62241d", "-41fa7069182bfd1", "-1d00134fba1769g", "-e4f799fc5f7e81", "-714ebbh8388188",
328 "-3cahb17836b3hd", "-1j8659jf5hbg3j", "-112bbb2jege5c5", "-dcjfmk2kjb4cc", "-836bm4klbgl61",
329 "-4ofia1416ee73", "-32ommgjef1l2h", "-1qc52eal5m8ba", "-17n53r05a4r15", "-oa88m2qiqjik", "-gn67qoat5r8d",
330 "-blgd6n5s90al", "-87t70q8o5fuh", "-5t09hwaqu9qg", "-47vssihaoa4x", "-32p24fbjye7x", "-299r8zck3841"}}},
331 {stress_chunks_negative
,
332 {{"skip0", "skip1", "-111110011101001100010010000100010000111010101111001010000110001",
333 "-2012222010200021010000112111002001111200", "-13303221202100202013111321100301",
334 "-1101001100304341000003214241", "-1522150121302454031001413", "-22054250360123016161454",
335 "-763514220420725712061", "-65863607100474061450", "-9000876000000054321", "-1689813530958833498",
336 "-408258185a67069269", "-106b01597a47ba2948", "-41c02922bc776d49b", "-1584cd10979dc84b6",
337 "-7ce9890887579431", "-327cf6cbc67023c3", "-1604b5f6a0de8129", "-b50d3ef02f124a4", "-59h9bfif0006fg1",
338 "-2g5d8ekh05d2dfi", "-19i418c38g1chfj", "-hjgf7d0k0gla9a", "-a6b21ncehfa3f9", "-61060fnl003bml",
339 "-3g88bakondgf8l", "-25q3i730ed21di", "-1al84glo518iip", "-pcli8ig7pjhbo", "-gs31q8id2jnkl",
340 "-bd7kaglgdrbgk", "-7pqc9123lf51h", "-5d2sd1r5ms7su", "-3q833s8kdrun3", "-2n7vmqigfueqb",
342 {INT64_MIN
, {{"skip0", "skip1", "-1000000000000000000000000000000000000000000000000000000000000000",
343 "-2021110011022210012102010021220101220222", "-20000000000000000000000000000000",
344 "-1104332401304422434310311213", "-1540241003031030222122212", "-22341010611245052052301",
345 "-1000000000000000000000", "-67404283172107811828", "-9223372036854775808", "-1728002635214590698",
346 "-41a792678515120368", "-10b269549075433c38", "-4340724c6c71dc7a8", "-160e2ad3246366808",
347 "-8000000000000000", "-33d3d8307b214009", "-16agh595df825fa8", "-ba643dci0ffeehi",
348 "-5cbfjia3fh26ja8", "-2heiciiie82dh98", "-1adaibb21dckfa8", "-i6k448cf4192c3", "-acd772jnc9l0l8",
349 "-64ie1focnn5g78", "-3igoecjbmca688", "-27c48l5b37oaoq", "-1bk39f3ah3dmq8", "-q1se8f0m04isc",
350 "-hajppbc1fc208", "-bm03i95hia438", "-8000000000000", "-5hg4ck9jd4u38", "-3tdtk1v8j6tpq",
351 "-2pijmikexrxp8", "-1y2p0ij32e8e8"}}},
354 template <typename T
>
355 void test_integer_to_chars() {
356 for (int base
= 2; base
<= 36; ++base
) {
357 test_integer_to_chars(static_cast<T
>(0), base
, "0");
358 test_integer_to_chars(static_cast<T
>(1), base
, "1");
361 test_integer_to_chars(static_cast<T
>(base
* 2 - 1), base
, output_max_digit
[base
]);
363 for (const auto& p
: output_positive
) {
364 if (p
.first
<= static_cast<std::uint64_t>(numeric_limits
<T
>::max())) {
365 test_integer_to_chars(static_cast<T
>(p
.first
), base
, p
.second
[static_cast<std::size_t>(base
)]);
369 if constexpr (is_signed_v
<T
>) {
370 test_integer_to_chars(static_cast<T
>(-1), base
, "-1");
372 for (const auto& p
: output_negative
) {
373 if (p
.first
>= static_cast<std::int64_t>(numeric_limits
<T
>::min())) {
374 test_integer_to_chars(static_cast<T
>(p
.first
), base
, p
.second
[static_cast<std::size_t>(base
)]);
380 test_integer_to_chars(static_cast<T
>(42), nullopt
, "42");
383 enum class TestFromCharsMode
{ Normal
, SignalingNaN
};
385 template <typename T
, typename BaseOrFmt
>
386 void test_from_chars(const string_view input
, const BaseOrFmt base_or_fmt
, const std::size_t correct_idx
,
387 const errc correct_ec
, const optional
<T
> opt_correct
= nullopt
,
388 const TestFromCharsMode mode
= TestFromCharsMode::Normal
) {
390 if constexpr (is_integral_v
<T
>) {
391 assert(mode
== TestFromCharsMode::Normal
);
394 constexpr T unmodified
= 111;
398 const from_chars_result result
= from_chars(input
.data(), input
.data() + input
.size(), dest
, base_or_fmt
);
400 assert(result
.ptr
== input
.data() + correct_idx
);
401 assert(result
.ec
== correct_ec
);
403 if (correct_ec
== errc
{} || (is_floating_point_v
<T
> && correct_ec
== errc::result_out_of_range
)) {
404 if constexpr (is_floating_point_v
<T
>) {
405 if (mode
== TestFromCharsMode::Normal
) {
406 using Uint
= conditional_t
<is_same_v
<T
, float>, std::uint32_t, std::uint64_t>;
407 assert(opt_correct
.has_value());
408 assert(_Bit_cast
<Uint
>(dest
) == _Bit_cast
<Uint
>(opt_correct
.value()));
410 assert(mode
== TestFromCharsMode::SignalingNaN
);
411 assert(!opt_correct
.has_value());
415 assert(opt_correct
.has_value());
416 assert(dest
== opt_correct
.value());
419 assert(!opt_correct
.has_value());
420 assert(dest
== unmodified
);
424 constexpr errc inv_arg
= errc::invalid_argument
;
425 constexpr errc out_ran
= errc::result_out_of_range
;
427 template <typename T
>
428 void test_integer_from_chars() {
429 for (int base
= 2; base
<= 36; ++base
) {
430 test_from_chars
<T
>("", base
, 0, inv_arg
); // no characters
431 test_from_chars
<T
>("@1", base
, 0, inv_arg
); // '@' is bogus
432 test_from_chars
<T
>(".1", base
, 0, inv_arg
); // '.' is bogus, for integers
433 test_from_chars
<T
>("+1", base
, 0, inv_arg
); // '+' is bogus, N4713 23.20.3 [charconv.from.chars]/3
434 // "a minus sign is the only sign that may appear"
435 test_from_chars
<T
>(" 1", base
, 0, inv_arg
); // ' ' is bogus, no whitespace in subject sequence
437 if constexpr (is_unsigned_v
<T
>) { // N4713 23.20.3 [charconv.from.chars]/3
438 test_from_chars
<T
>("-1", base
, 0, inv_arg
); // "and only if value has a signed type"
441 // N4713 23.20.3 [charconv.from.chars]/1 "[ Note: If the pattern allows for an optional sign,
442 // but the string has no digit characters following the sign, no characters match the pattern. -end note ]"
443 test_from_chars
<T
>("-", base
, 0, inv_arg
); // '-' followed by no characters
444 test_from_chars
<T
>("-@1", base
, 0, inv_arg
); // '-' followed by bogus '@'
445 test_from_chars
<T
>("-.1", base
, 0, inv_arg
); // '-' followed by bogus '.'
446 test_from_chars
<T
>("-+1", base
, 0, inv_arg
); // '-' followed by bogus '+'
447 test_from_chars
<T
>("- 1", base
, 0, inv_arg
); // '-' followed by bogus ' '
448 test_from_chars
<T
>("--1", base
, 0, inv_arg
); // '-' can't be repeated
450 vector
<char> bogus_digits
;
453 bogus_digits
= {static_cast<char>('0' + base
), 'A', 'a'};
455 // '[' and '{' are bogus for base 36
456 bogus_digits
= {static_cast<char>('A' + (base
- 10)), static_cast<char>('a' + (base
- 10))};
459 for (const auto& bogus
: bogus_digits
) {
460 test_from_chars
<T
>(bogus
+ "1"s
, base
, 0, inv_arg
); // bogus digit (for this base)
461 test_from_chars
<T
>("-"s
+ bogus
+ "1"s
, base
, 0, inv_arg
); // '-' followed by bogus digit
464 // Test leading zeroes.
465 test_from_chars
<T
>(string(100, '0'), base
, 100, errc
{}, static_cast<T
>(0));
466 test_from_chars
<T
>(string(100, '0') + "11"s
, base
, 102, errc
{}, static_cast<T
>(base
+ 1));
468 // Test negative zero and negative leading zeroes.
469 if constexpr (is_signed_v
<T
>) {
470 test_from_chars
<T
>("-0", base
, 2, errc
{}, static_cast<T
>(0));
471 test_from_chars
<T
>("-"s
+ string(100, '0'), base
, 101, errc
{}, static_cast<T
>(0));
472 test_from_chars
<T
>("-"s
+ string(100, '0') + "11"s
, base
, 103, errc
{}, static_cast<T
>(-base
- 1));
475 // N4713 23.20.3 [charconv.from.chars]/1 "The member ptr of the return value points to the
476 // first character not matching the pattern, or has the value last if all characters match."
477 test_from_chars
<T
>("11", base
, 2, errc
{}, static_cast<T
>(base
+ 1));
478 test_from_chars
<T
>("11@@@", base
, 2, errc
{}, static_cast<T
>(base
+ 1));
480 // When overflowing, we need to keep consuming valid digits, in order to return ptr correctly.
481 test_from_chars
<T
>(string(100, '1'), base
, 100, out_ran
);
482 test_from_chars
<T
>(string(100, '1') + "@@@"s
, base
, 100, out_ran
);
484 if constexpr (is_signed_v
<T
>) {
485 test_from_chars
<T
>("-"s
+ string(100, '1'), base
, 101, out_ran
);
486 test_from_chars
<T
>("-"s
+ string(100, '1') + "@@@"s
, base
, 101, out_ran
);
490 // N4713 23.20.3 [charconv.from.chars]/3 "The pattern is the expected form of the subject sequence
491 // in the "C" locale for the given nonzero base, as described for strtol"
492 // C11 7.22.1.4/3 "The letters from a (or A) through z (or Z) are ascribed the values 10 through 35"
493 for (int i
= 0; i
< 26; ++i
) {
494 test_from_chars
<T
>(string(1, static_cast<char>('A' + i
)), 36, 1, errc
{}, static_cast<T
>(10 + i
));
495 test_from_chars
<T
>(string(1, static_cast<char>('a' + i
)), 36, 1, errc
{}, static_cast<T
>(10 + i
));
498 // N4713 23.20.3 [charconv.from.chars]/3 "no "0x" or "0X" prefix shall appear if the value of base is 16"
499 test_from_chars
<T
>("0x1729", 16, 1, errc
{}, static_cast<T
>(0)); // reads '0', stops at 'x'
500 test_from_chars
<T
>("0X1729", 16, 1, errc
{}, static_cast<T
>(0)); // reads '0', stops at 'X'
502 if constexpr (is_signed_v
<T
>) {
503 test_from_chars
<T
>("-0x1729", 16, 2, errc
{}, static_cast<T
>(0)); // reads "-0", stops at 'x'
504 test_from_chars
<T
>("-0X1729", 16, 2, errc
{}, static_cast<T
>(0)); // reads "-0", stops at 'X'
508 template <typename T
>
509 void test_integer() {
510 test_integer_to_chars
<T
>();
511 test_integer_from_chars
<T
>();
514 void all_integer_tests() {
515 test_integer
<char>();
516 test_integer
<signed char>();
517 test_integer
<unsigned char>();
518 test_integer
<short>();
519 test_integer
<unsigned short>();
521 test_integer
<unsigned int>();
522 test_integer
<long>();
523 test_integer
<unsigned long>();
524 test_integer
<long long>();
525 test_integer
<unsigned long long>();
527 // Test overflow scenarios.
528 test_from_chars
<unsigned int>("4294967289", 10, 10, errc
{}, 4294967289U); // not risky
529 test_from_chars
<unsigned int>("4294967294", 10, 10, errc
{}, 4294967294U); // risky with good digit
530 test_from_chars
<unsigned int>("4294967295", 10, 10, errc
{}, 4294967295U); // risky with max digit
531 test_from_chars
<unsigned int>("4294967296", 10, 10, out_ran
); // risky with bad digit
532 test_from_chars
<unsigned int>("4294967300", 10, 10, out_ran
); // beyond risky
534 test_from_chars
<int>("2147483639", 10, 10, errc
{}, 2147483639); // not risky
535 test_from_chars
<int>("2147483646", 10, 10, errc
{}, 2147483646); // risky with good digit
536 test_from_chars
<int>("2147483647", 10, 10, errc
{}, 2147483647); // risky with max digit
537 test_from_chars
<int>("2147483648", 10, 10, out_ran
); // risky with bad digit
538 test_from_chars
<int>("2147483650", 10, 10, out_ran
); // beyond risky
540 test_from_chars
<int>("-2147483639", 10, 11, errc
{}, -2147483639); // not risky
541 test_from_chars
<int>("-2147483647", 10, 11, errc
{}, -2147483647); // risky with good digit
542 test_from_chars
<int>("-2147483648", 10, 11, errc
{}, -2147483647 - 1); // risky with max digit
543 test_from_chars
<int>("-2147483649", 10, 11, out_ran
); // risky with bad digit
544 test_from_chars
<int>("-2147483650", 10, 11, out_ran
); // beyond risky
547 void assert_message_bits(const bool b
, const char* const msg
, const std::uint32_t bits
) {
549 fprintf(stderr
, "%s failed for 0x%08zX\n", msg
, static_cast<std::size_t>(bits
));
550 fprintf(stderr
, "This is a randomized test.\n");
551 fprintf(stderr
, "DO NOT IGNORE/RERUN THIS FAILURE.\n");
552 fprintf(stderr
, "You must report it to the STL maintainers.\n");
557 void assert_message_bits(const bool b
, const char* const msg
, const std::uint64_t bits
) {
559 // libc++ uses long for 64-bit values.
560 fprintf(stderr
, "%s failed for 0x%016llX\n", msg
, static_cast<unsigned long long>(bits
));
561 fprintf(stderr
, "This is a randomized test.\n");
562 fprintf(stderr
, "DO NOT IGNORE/RERUN THIS FAILURE.\n");
563 fprintf(stderr
, "You must report it to the STL maintainers.\n");
568 constexpr std::uint32_t FractionBits
= 10; // Tunable for test coverage vs. performance.
569 static_assert(FractionBits
>= 1, "Must test at least 1 fraction bit.");
570 static_assert(FractionBits
<= 23, "There are only 23 fraction bits in a float.");
572 constexpr std::uint32_t Fractions
= 1U << FractionBits
;
573 constexpr std::uint32_t Mask32
= ~((1U << FractionBits
) - 1U);
574 constexpr std::uint64_t Mask64
= ~((1ULL << FractionBits
) - 1ULL);
576 constexpr std::uint32_t PrefixesToTest
= 100; // Tunable for test coverage vs. performance.
577 static_assert(PrefixesToTest
>= 1, "Must test at least 1 prefix.");
579 constexpr std::uint32_t PrefixLimit
= 2 // sign bit
580 * 255 // non-INF/NAN exponents for float
581 * (1U << (23 - FractionBits
)); // fraction bits in prefix
582 static_assert(PrefixesToTest
<= PrefixLimit
, "Too many prefixes.");
584 template <bool IsDouble
>
585 void test_floating_prefix(const conditional_t
<IsDouble
, std::uint64_t, std::uint32_t> prefix
) {
587 using UIntType
= conditional_t
<IsDouble
, std::uint64_t, std::uint32_t>;
588 using FloatingType
= conditional_t
<IsDouble
, double, float>;
590 // "-1.2345678901234567e-100" or "-1.23456789e-10"
591 constexpr std::size_t buffer_size
= IsDouble
? 24 : 15;
592 char buffer
[buffer_size
];
594 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
598 // Exact sizes are difficult to prove for fixed notation.
599 // This must be at least (IsDouble ? 327 : 48), and I suspect that that's exact.
600 // Here's a loose upper bound:
601 // 1 character for a negative sign
602 // + 325 (for double; 46 for float) characters in the "0.000~~~000" prefix of the min subnormal
603 // + 17 (for double; 9 for float) characters for round-trip digits
604 constexpr std::size_t fixed_buffer_size
= IsDouble
? 1 + 325 + 17 : 1 + 46 + 9;
605 char fixed_buffer
[fixed_buffer_size
];
607 // worst case: negative sign + max normal + null terminator
608 constexpr std::size_t stdio_buffer_size
= 1 + (IsDouble
? 309 : 39) + 1;
609 char stdio_buffer
[stdio_buffer_size
];
611 for (std::uint32_t frac
= 0; frac
< Fractions
; ++frac
) {
612 const UIntType bits
= prefix
+ frac
;
613 const FloatingType input
= _Bit_cast
<FloatingType
>(bits
);
616 const auto to_result
= to_chars(buffer
, end(buffer
), input
, chars_format::scientific
);
617 assert_message_bits(to_result
.ec
== errc
{}, "to_result.ec", bits
);
618 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
619 const char* const last
= to_result
.ptr
;
621 const auto from_result
= from_chars(buffer
, last
, val
);
623 assert_message_bits(from_result
.ptr
== last
, "from_result.ptr", bits
);
624 assert_message_bits(from_result
.ec
== errc
{}, "from_result.ec", bits
);
625 assert_message_bits(_Bit_cast
<UIntType
>(val
) == bits
, "round-trip", bits
);
626 #endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
630 // Also verify that to_chars() and sprintf_s() emit the same output for integers in fixed notation.
631 const auto fixed_result
= to_chars(fixed_buffer
, end(fixed_buffer
), input
, chars_format::fixed
);
632 assert_message_bits(fixed_result
.ec
== errc
{}, "fixed_result.ec", bits
);
633 const string_view
fixed_sv(fixed_buffer
, static_cast<std::size_t>(fixed_result
.ptr
- fixed_buffer
));
635 if (find(fixed_sv
.begin(), fixed_sv
.end(), '.') == fixed_sv
.end()) {
636 const int stdio_ret
= sprintf_s(stdio_buffer
, size(stdio_buffer
), "%.0f", input
);
637 assert_message_bits(stdio_ret
!= -1, "stdio_ret", bits
);
638 const string_view
stdio_sv(stdio_buffer
);
639 assert_message_bits(fixed_sv
== stdio_sv
, "fixed_sv", bits
);
645 template <bool IsDouble
>
646 void test_floating_hex_prefix(const conditional_t
<IsDouble
, std::uint64_t, std::uint32_t> prefix
) {
648 using UIntType
= conditional_t
<IsDouble
, std::uint64_t, std::uint32_t>;
649 using FloatingType
= conditional_t
<IsDouble
, double, float>;
651 // The precision is the number of hexits after the decimal point.
652 // These hexits correspond to the explicitly stored fraction bits.
653 // double explicitly stores 52 fraction bits. 52 / 4 == 13, so we need 13 hexits.
654 // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, so we need 6 hexits.
656 // "-1.fffffffffffffp+1023" or "-1.fffffep+127"
657 constexpr std::size_t buffer_size
= IsDouble
? 22 : 14;
658 char buffer
[buffer_size
];
660 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
664 for (std::uint32_t frac
= 0; frac
< Fractions
; ++frac
) {
665 const UIntType bits
= prefix
+ frac
;
666 const FloatingType input
= _Bit_cast
<FloatingType
>(bits
);
668 const auto to_result
= to_chars(buffer
, end(buffer
), input
, chars_format::hex
);
669 assert_message_bits(to_result
.ec
== errc
{}, "(hex) to_result.ec", bits
);
671 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
672 const char* const last
= to_result
.ptr
;
674 const auto from_result
= from_chars(buffer
, last
, val
, chars_format::hex
);
676 assert_message_bits(from_result
.ptr
== last
, "(hex) from_result.ptr", bits
);
677 assert_message_bits(from_result
.ec
== errc
{}, "(hex) from_result.ec", bits
);
678 assert_message_bits(_Bit_cast
<UIntType
>(val
) == bits
, "(hex) round-trip", bits
);
679 #endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
683 template <bool IsDouble
>
684 void test_floating_precision_prefix(const conditional_t
<IsDouble
, std::uint64_t, std::uint32_t> prefix
) {
686 using UIntType
= conditional_t
<IsDouble
, std::uint64_t, std::uint32_t>;
687 using FloatingType
= conditional_t
<IsDouble
, double, float>;
689 // Precision for min subnormal in fixed notation. (More than enough for scientific notation.)
690 constexpr int precision
= IsDouble
? 1074 : 149;
692 // Number of digits for max normal in fixed notation.
693 constexpr int max_integer_length
= IsDouble
? 309 : 39;
695 // Size for fixed notation. (More than enough for scientific notation.)
696 constexpr std::size_t charconv_buffer_size
= 1 // negative sign
697 + max_integer_length
// integer digits
699 + precision
; // fractional digits
700 char charconv_buffer
[charconv_buffer_size
];
702 constexpr std::size_t stdio_buffer_size
= charconv_buffer_size
+ 1; // null terminator
703 char stdio_buffer
[stdio_buffer_size
];
705 // 1 character for a negative sign
706 // + worst cases: 0x1.fffffffffffffp-1022 and 0x1.fffffep-126f
707 constexpr std::size_t general_buffer_size
= 1 + (IsDouble
? 773 : 117);
708 char general_buffer
[general_buffer_size
];
709 char general_stdio_buffer
[general_buffer_size
+ 1]; // + null terminator
711 for (std::uint32_t frac
= 0; frac
< Fractions
; ++frac
) {
712 const UIntType bits
= prefix
+ frac
;
713 const FloatingType input
= _Bit_cast
<FloatingType
>(bits
);
715 auto result
= to_chars(charconv_buffer
, end(charconv_buffer
), input
, chars_format::fixed
, precision
);
716 assert_message_bits(result
.ec
== errc
{}, "to_chars fixed precision", bits
);
717 string_view
charconv_sv(charconv_buffer
, static_cast<std::size_t>(result
.ptr
- charconv_buffer
));
719 int stdio_ret
= sprintf_s(stdio_buffer
, size(stdio_buffer
), "%.*f", precision
, input
);
720 assert_message_bits(stdio_ret
!= -1, "sprintf_s fixed precision", bits
);
721 string_view
stdio_sv(stdio_buffer
);
723 assert_message_bits(charconv_sv
== stdio_sv
, "fixed precision output", bits
);
726 result
= to_chars(charconv_buffer
, end(charconv_buffer
), input
, chars_format::scientific
, precision
);
727 assert_message_bits(result
.ec
== errc
{}, "to_chars scientific precision", bits
);
728 charconv_sv
= string_view(charconv_buffer
, static_cast<std::size_t>(result
.ptr
- charconv_buffer
));
730 stdio_ret
= sprintf_s(stdio_buffer
, size(stdio_buffer
), "%.*e", precision
, input
);
731 assert_message_bits(stdio_ret
!= -1, "sprintf_s scientific precision", bits
);
732 stdio_sv
= stdio_buffer
;
734 assert_message_bits(charconv_sv
== stdio_sv
, "scientific precision output", bits
);
737 result
= to_chars(general_buffer
, end(general_buffer
), input
, chars_format::general
, 5000);
738 assert_message_bits(result
.ec
== errc
{}, "to_chars general precision", bits
);
739 charconv_sv
= string_view(general_buffer
, static_cast<std::size_t>(result
.ptr
- general_buffer
));
741 stdio_ret
= sprintf_s(general_stdio_buffer
, size(general_stdio_buffer
), "%.5000g", input
);
742 assert_message_bits(stdio_ret
!= -1, "sprintf_s general precision", bits
);
743 stdio_sv
= general_stdio_buffer
;
745 assert_message_bits(charconv_sv
== stdio_sv
, "general precision output", bits
);
749 void test_floating_prefixes(mt19937_64
& mt64
) {
751 set
<std::uint64_t> prefixes64
;
753 while (prefixes64
.size() < PrefixesToTest
) {
754 const std::uint64_t val
= mt64();
756 if ((val
& 0x7FF0000000000000ULL
) != 0x7FF0000000000000ULL
) { // skip INF/NAN
757 prefixes64
.insert(val
& Mask64
);
761 for (const auto& prefix
: prefixes64
) {
762 test_floating_prefix
<true>(prefix
);
763 test_floating_precision_prefix
<true>(prefix
);
766 test_floating_hex_prefix
<true>(*prefixes64
.begin()); // save time by testing fewer hexfloats
770 set
<std::uint32_t> prefixes32
;
772 while (prefixes32
.size() < PrefixesToTest
) {
773 const std::uint32_t val
= static_cast<std::uint32_t>(mt64());
775 if ((val
& 0x7F800000U
) != 0x7F800000U
) { // skip INF/NAN
776 prefixes32
.insert(val
& Mask32
);
780 for (const auto& prefix
: prefixes32
) {
781 test_floating_prefix
<false>(prefix
);
782 test_floating_precision_prefix
<false>(prefix
);
785 test_floating_hex_prefix
<false>(*prefixes32
.begin()); // save time by testing fewer hexfloats
789 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
790 template <typename T
>
791 void test_floating_from_chars(const chars_format fmt
) {
792 test_from_chars
<T
>("", fmt
, 0, inv_arg
); // no characters
793 test_from_chars
<T
>("@1", fmt
, 0, inv_arg
); // '@' is bogus
794 test_from_chars
<T
>("z1", fmt
, 0, inv_arg
); // 'z' is bogus
795 test_from_chars
<T
>(".", fmt
, 0, inv_arg
); // '.' without digits is bogus
796 test_from_chars
<T
>("+1", fmt
, 0, inv_arg
); // '+' is bogus
797 test_from_chars
<T
>(" 1", fmt
, 0, inv_arg
); // ' ' is bogus
798 test_from_chars
<T
>("p5", fmt
, 0, inv_arg
); // binary-exponent-part without digits is bogus
799 test_from_chars
<T
>("in", fmt
, 0, inv_arg
); // incomplete inf is bogus
800 test_from_chars
<T
>("na", fmt
, 0, inv_arg
); // incomplete nan is bogus
802 test_from_chars
<T
>("-", fmt
, 0, inv_arg
); // '-' followed by no characters
803 test_from_chars
<T
>("-@1", fmt
, 0, inv_arg
); // '-' followed by bogus '@'
804 test_from_chars
<T
>("-z1", fmt
, 0, inv_arg
); // '-' followed by bogus 'z'
805 test_from_chars
<T
>("-.", fmt
, 0, inv_arg
); // '-' followed by bogus '.'
806 test_from_chars
<T
>("-+1", fmt
, 0, inv_arg
); // '-' followed by bogus '+'
807 test_from_chars
<T
>("- 1", fmt
, 0, inv_arg
); // '-' followed by bogus ' '
808 test_from_chars
<T
>("-p5", fmt
, 0, inv_arg
); // '-' followed by bogus binary-exponent-part
809 test_from_chars
<T
>("-in", fmt
, 0, inv_arg
); // '-' followed by bogus incomplete inf
810 test_from_chars
<T
>("-na", fmt
, 0, inv_arg
); // '-' followed by bogus incomplete nan
811 test_from_chars
<T
>("--1", fmt
, 0, inv_arg
); // '-' can't be repeated
813 if (fmt
!= chars_format::hex
) { // "e5" are valid hexits
814 test_from_chars
<T
>("e5", fmt
, 0, inv_arg
); // exponent-part without digits is bogus
815 test_from_chars
<T
>("-e5", fmt
, 0, inv_arg
); // '-' followed by bogus exponent-part
818 constexpr T inf
= numeric_limits
<T
>::infinity();
819 constexpr T qnan
= numeric_limits
<T
>::quiet_NaN();
821 test_from_chars
<T
>("InF", fmt
, 3, errc
{}, inf
);
822 test_from_chars
<T
>("infinite", fmt
, 3, errc
{}, inf
);
823 test_from_chars
<T
>("iNfInItY", fmt
, 8, errc
{}, inf
);
824 test_from_chars
<T
>("InfinityMeow", fmt
, 8, errc
{}, inf
);
826 test_from_chars
<T
>("-InF", fmt
, 4, errc
{}, -inf
);
827 test_from_chars
<T
>("-infinite", fmt
, 4, errc
{}, -inf
);
828 test_from_chars
<T
>("-iNfInItY", fmt
, 9, errc
{}, -inf
);
829 test_from_chars
<T
>("-InfinityMeow", fmt
, 9, errc
{}, -inf
);
831 test_from_chars
<T
>("NaN", fmt
, 3, errc
{}, qnan
);
832 test_from_chars
<T
>("nanotech", fmt
, 3, errc
{}, qnan
);
833 test_from_chars
<T
>("nan(", fmt
, 3, errc
{}, qnan
);
834 test_from_chars
<T
>("nan(@)", fmt
, 3, errc
{}, qnan
);
835 test_from_chars
<T
>("nan(()", fmt
, 3, errc
{}, qnan
);
836 test_from_chars
<T
>("nan(abc", fmt
, 3, errc
{}, qnan
);
837 test_from_chars
<T
>("nan()", fmt
, 5, errc
{}, qnan
);
838 test_from_chars
<T
>("nan(abc)def", fmt
, 8, errc
{}, qnan
);
839 test_from_chars
<T
>("nan(_09AZaz)", fmt
, 12, errc
{}, qnan
);
840 test_from_chars
<T
>("nan(int)", fmt
, 8, errc
{}, qnan
);
841 test_from_chars
<T
>("nan(snap)", fmt
, 9, errc
{}, qnan
);
843 test_from_chars
<T
>("-NaN", fmt
, 4, errc
{}, -qnan
);
844 test_from_chars
<T
>("-nanotech", fmt
, 4, errc
{}, -qnan
);
845 test_from_chars
<T
>("-nan(", fmt
, 4, errc
{}, -qnan
);
846 test_from_chars
<T
>("-nan(@)", fmt
, 4, errc
{}, -qnan
);
847 test_from_chars
<T
>("-nan(()", fmt
, 4, errc
{}, -qnan
);
848 test_from_chars
<T
>("-nan(abc", fmt
, 4, errc
{}, -qnan
);
849 test_from_chars
<T
>("-nan()", fmt
, 6, errc
{}, -qnan
);
850 test_from_chars
<T
>("-nan(abc)def", fmt
, 9, errc
{}, -qnan
);
851 test_from_chars
<T
>("-nan(_09AZaz)", fmt
, 13, errc
{}, -qnan
);
852 test_from_chars
<T
>("-nan(int)", fmt
, 9, errc
{}, -qnan
);
853 test_from_chars
<T
>("-nan(snap)", fmt
, 10, errc
{}, -qnan
);
855 // The UCRT considers indeterminate NaN to be negative quiet NaN with no payload bits set.
856 // It parses "nan(ind)" and "-nan(ind)" identically.
858 test_from_chars
<T
>("nan(InD)", fmt
, 8, errc
{}, -qnan
);
859 test_from_chars
<T
>("-nan(InD)", fmt
, 9, errc
{}, -qnan
);
861 test_from_chars
<T
>("nan(SnAn)", fmt
, 9, errc
{}, nullopt
, TestFromCharsMode::SignalingNaN
);
862 test_from_chars
<T
>("-nan(SnAn)", fmt
, 10, errc
{}, nullopt
, TestFromCharsMode::SignalingNaN
);
866 case chars_format::general
:
867 test_from_chars
<T
>("1729", fmt
, 4, errc
{}, T
{1729});
868 test_from_chars
<T
>("1729e3", fmt
, 6, errc
{}, T
{1729000});
869 test_from_chars
<T
>("10", fmt
, 2, errc
{}, T
{10});
870 test_from_chars
<T
>("11.", fmt
, 3, errc
{}, T
{11});
871 test_from_chars
<T
>("12.13", fmt
, 5, errc
{}, static_cast<T
>(12.13)); // avoid truncation warning
872 test_from_chars
<T
>(".14", fmt
, 3, errc
{}, static_cast<T
>(.14)); // avoid truncation warning
873 test_from_chars
<T
>("20e5", fmt
, 4, errc
{}, T
{2000000});
874 test_from_chars
<T
>("21.e5", fmt
, 5, errc
{}, T
{2100000});
875 test_from_chars
<T
>("22.23e5", fmt
, 7, errc
{}, T
{2223000});
876 test_from_chars
<T
>(".24e5", fmt
, 5, errc
{}, T
{24000});
877 test_from_chars
<T
>("33e+5", fmt
, 5, errc
{}, T
{3300000});
878 test_from_chars
<T
>("33e-5", fmt
, 5, errc
{}, static_cast<T
>(.00033)); // avoid truncation warning
879 test_from_chars
<T
>("4E7", fmt
, 3, errc
{}, T
{40000000});
880 test_from_chars
<T
>("-00123abc", fmt
, 6, errc
{}, T
{-123});
881 test_from_chars
<T
>(".0045000", fmt
, 8, errc
{}, static_cast<T
>(.0045)); // avoid truncation warning
882 test_from_chars
<T
>("000", fmt
, 3, errc
{}, T
{0});
883 test_from_chars
<T
>("0e9999", fmt
, 6, errc
{}, T
{0});
884 test_from_chars
<T
>("0e-9999", fmt
, 7, errc
{}, T
{0});
885 test_from_chars
<T
>("-000", fmt
, 4, errc
{}, T
{-0.0});
886 test_from_chars
<T
>("-0e9999", fmt
, 7, errc
{}, T
{-0.0});
887 test_from_chars
<T
>("-0e-9999", fmt
, 8, errc
{}, T
{-0.0});
888 test_from_chars
<T
>("1e9999", fmt
, 6, errc::result_out_of_range
, inf
);
889 test_from_chars
<T
>("-1e9999", fmt
, 7, errc::result_out_of_range
, -inf
);
890 test_from_chars
<T
>("1e-9999", fmt
, 7, errc::result_out_of_range
, T
{0});
891 test_from_chars
<T
>("-1e-9999", fmt
, 8, errc::result_out_of_range
, T
{-0.0});
892 test_from_chars
<T
>("1" + string(6000, '0'), fmt
, 6001, errc::result_out_of_range
, inf
);
893 test_from_chars
<T
>("-1" + string(6000, '0'), fmt
, 6002, errc::result_out_of_range
, -inf
);
894 test_from_chars
<T
>("." + string(6000, '0') + "1", fmt
, 6002, errc::result_out_of_range
, T
{0});
895 test_from_chars
<T
>("-." + string(6000, '0') + "1", fmt
, 6003, errc::result_out_of_range
, T
{-0.0});
896 test_from_chars
<T
>("1" + string(500, '0'), fmt
, 501, errc::result_out_of_range
, inf
);
897 test_from_chars
<T
>("-1" + string(500, '0'), fmt
, 502, errc::result_out_of_range
, -inf
);
898 test_from_chars
<T
>("." + string(500, '0') + "1", fmt
, 502, errc::result_out_of_range
, T
{0});
899 test_from_chars
<T
>("-." + string(500, '0') + "1", fmt
, 503, errc::result_out_of_range
, T
{-0.0});
901 case chars_format::scientific
:
902 test_from_chars
<T
>("1729", fmt
, 0, inv_arg
);
903 test_from_chars
<T
>("1729e3", fmt
, 6, errc
{}, T
{1729000});
905 case chars_format::fixed
:
906 test_from_chars
<T
>("1729", fmt
, 4, errc
{}, T
{1729});
907 test_from_chars
<T
>("1729e3", fmt
, 4, errc
{}, T
{1729});
909 case chars_format::hex
:
910 test_from_chars
<T
>("0x123", fmt
, 1, errc
{}, T
{0});
911 test_from_chars
<T
>("a0", fmt
, 2, errc
{}, T
{160});
912 test_from_chars
<T
>("a1.", fmt
, 3, errc
{}, T
{161});
913 test_from_chars
<T
>("a2.a3", fmt
, 5, errc
{}, T
{162.63671875});
914 test_from_chars
<T
>(".a4", fmt
, 3, errc
{}, T
{0.640625});
915 test_from_chars
<T
>("a0p5", fmt
, 4, errc
{}, T
{5120});
916 test_from_chars
<T
>("a1.p5", fmt
, 5, errc
{}, T
{5152});
917 test_from_chars
<T
>("a2.a3p5", fmt
, 7, errc
{}, T
{5204.375});
918 test_from_chars
<T
>(".a4p5", fmt
, 5, errc
{}, T
{20.5});
919 test_from_chars
<T
>("a0p+5", fmt
, 5, errc
{}, T
{5120});
920 test_from_chars
<T
>("a0p-5", fmt
, 5, errc
{}, T
{5});
921 test_from_chars
<T
>("ABCDEFP3", fmt
, 8, errc
{}, T
{90075000});
922 test_from_chars
<T
>("-00cdrom", fmt
, 5, errc
{}, T
{-205});
923 test_from_chars
<T
>(".00ef000", fmt
, 8, errc
{}, T
{0.0036468505859375});
924 test_from_chars
<T
>("000", fmt
, 3, errc
{}, T
{0});
925 test_from_chars
<T
>("0p9999", fmt
, 6, errc
{}, T
{0});
926 test_from_chars
<T
>("0p-9999", fmt
, 7, errc
{}, T
{0});
927 test_from_chars
<T
>("-000", fmt
, 4, errc
{}, T
{-0.0});
928 test_from_chars
<T
>("-0p9999", fmt
, 7, errc
{}, T
{-0.0});
929 test_from_chars
<T
>("-0p-9999", fmt
, 8, errc
{}, T
{-0.0});
930 test_from_chars
<T
>("1p9999", fmt
, 6, errc::result_out_of_range
, inf
);
931 test_from_chars
<T
>("-1p9999", fmt
, 7, errc::result_out_of_range
, -inf
);
932 test_from_chars
<T
>("1p-9999", fmt
, 7, errc::result_out_of_range
, T
{0});
933 test_from_chars
<T
>("-1p-9999", fmt
, 8, errc::result_out_of_range
, T
{-0.0});
934 test_from_chars
<T
>("1" + string(2000, '0'), fmt
, 2001, errc::result_out_of_range
, inf
);
935 test_from_chars
<T
>("-1" + string(2000, '0'), fmt
, 2002, errc::result_out_of_range
, -inf
);
936 test_from_chars
<T
>("." + string(2000, '0') + "1", fmt
, 2002, errc::result_out_of_range
, T
{0});
937 test_from_chars
<T
>("-." + string(2000, '0') + "1", fmt
, 2003, errc::result_out_of_range
, T
{-0.0});
938 test_from_chars
<T
>("1" + string(300, '0'), fmt
, 301, errc::result_out_of_range
, inf
);
939 test_from_chars
<T
>("-1" + string(300, '0'), fmt
, 302, errc::result_out_of_range
, -inf
);
940 test_from_chars
<T
>("." + string(300, '0') + "1", fmt
, 302, errc::result_out_of_range
, T
{0});
941 test_from_chars
<T
>("-." + string(300, '0') + "1", fmt
, 303, errc::result_out_of_range
, T
{-0.0});
945 #endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
947 template <typename T
>
948 void test_floating_to_chars(
949 const T value
, const optional
<chars_format
> opt_fmt
, const optional
<int> opt_precision
, const string_view correct
) {
951 test_common_to_chars(value
, opt_fmt
, opt_precision
, correct
);
954 void all_floating_tests(mt19937_64
& mt64
) {
955 test_floating_prefixes(mt64
);
957 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
958 for (const auto& fmt
: {chars_format::general
, chars_format::scientific
, chars_format::fixed
, chars_format::hex
}) {
959 test_floating_from_chars
<float>(fmt
);
960 test_floating_from_chars
<double>(fmt
);
964 // See float_from_chars_test_cases.hpp in this directory.
965 for (const auto& t
: float_from_chars_test_cases
) {
966 test_from_chars
<float>(t
.input
, t
.fmt
, t
.correct_idx
, t
.correct_ec
, t
.correct_value
);
969 // See double_from_chars_test_cases.hpp in this directory.
970 for (const auto& t
: double_from_chars_test_cases
) {
971 test_from_chars
<double>(t
.input
, t
.fmt
, t
.correct_idx
, t
.correct_ec
, t
.correct_value
);
975 // See LWG-2403. This number (exactly 0x1.fffffd00000004 in infinite precision) behaves differently
976 // when parsed as double and converted to float, versus being parsed as float directly.
977 const char* const lwg_2403
= "1.999999821186065729339276231257827021181583404541015625";
978 constexpr float correct_float
= 0x1.fffffep0f
;
979 constexpr double correct_double
= 0x1.fffffdp0
;
980 constexpr float twice_rounded_float
= 0x1.fffffcp0f
;
982 test_from_chars
<float>(lwg_2403
, chars_format::general
, 56, errc
{}, correct_float
);
983 test_from_chars
<double>(lwg_2403
, chars_format::general
, 56, errc
{}, correct_double
);
984 static_assert(static_cast<float>(correct_double
) == twice_rounded_float
);
987 // See floating_point_test_cases.hpp.
988 for (const auto& p
: floating_point_test_cases_float
) {
989 test_from_chars
<float>(p
.first
, chars_format::general
, strlen(p
.first
), errc
{}, _Bit_cast
<float>(p
.second
));
992 for (const auto& p
: floating_point_test_cases_double
) {
993 test_from_chars
<double>(p
.first
, chars_format::general
, strlen(p
.first
), errc
{}, _Bit_cast
<double>(p
.second
));
995 #endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
997 // See float_to_chars_test_cases.hpp in this directory.
998 for (const auto& t
: float_to_chars_test_cases
) {
999 if (t
.fmt
== chars_format
{}) {
1000 test_floating_to_chars(t
.value
, nullopt
, nullopt
, t
.correct
);
1002 test_floating_to_chars(t
.value
, t
.fmt
, nullopt
, t
.correct
);
1006 // See double_to_chars_test_cases.hpp in this directory.
1007 for (const auto& t
: double_to_chars_test_cases
) {
1008 if (t
.fmt
== chars_format
{}) {
1009 test_floating_to_chars(t
.value
, nullopt
, nullopt
, t
.correct
);
1011 test_floating_to_chars(t
.value
, t
.fmt
, nullopt
, t
.correct
);
1015 // See corresponding headers in this directory.
1016 for (const auto& t
: float_hex_precision_to_chars_test_cases
) {
1017 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1019 for (const auto& t
: float_fixed_precision_to_chars_test_cases
) {
1020 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1022 for (const auto& t
: float_scientific_precision_to_chars_test_cases
) {
1023 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1025 for (const auto& t
: float_general_precision_to_chars_test_cases
) {
1026 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1028 for (const auto& t
: double_hex_precision_to_chars_test_cases
) {
1029 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1031 for (const auto& t
: double_fixed_precision_to_chars_test_cases_1
) {
1032 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1034 for (const auto& t
: double_fixed_precision_to_chars_test_cases_2
) {
1035 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1037 for (const auto& t
: double_fixed_precision_to_chars_test_cases_3
) {
1038 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1040 for (const auto& t
: double_fixed_precision_to_chars_test_cases_4
) {
1041 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1043 for (const auto& t
: double_scientific_precision_to_chars_test_cases_1
) {
1044 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1046 for (const auto& t
: double_scientific_precision_to_chars_test_cases_2
) {
1047 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1049 for (const auto& t
: double_scientific_precision_to_chars_test_cases_3
) {
1050 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1052 for (const auto& t
: double_scientific_precision_to_chars_test_cases_4
) {
1053 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1055 for (const auto& t
: double_general_precision_to_chars_test_cases
) {
1056 test_floating_to_chars(t
.value
, t
.fmt
, t
.precision
, t
.correct
);
1060 int main(int argc
, char** argv
) {
1061 const auto start
= chrono::steady_clock::now();
1065 initialize_randomness(mt64
, argc
, argv
);
1067 all_integer_tests();
1069 all_floating_tests(mt64
);
1071 const auto finish
= chrono::steady_clock::now();
1072 const long long ms
= chrono::duration_cast
<chrono::milliseconds
>(finish
- start
).count();
1075 printf("Randomized test cases: %zu\n", static_cast<std::size_t>(PrefixesToTest
* Fractions
));
1076 printf("Total time: %lld ms\n", ms
);
1079 puts("That was fast. Consider tuning PrefixesToTest and FractionBits to test more cases.");
1080 } else if (ms
> 30'000) {
1081 puts("That was slow. Consider tuning PrefixesToTest and FractionBits to test fewer cases.");