xref: /llvm-project/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp (revision 6c4267fb1779bc5550bb413f33250f9365acfbc6)
1 // Copyright (c) Microsoft Corporation.
2 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3 
4 #include "test.hpp"
5 
6 #include <algorithm>
7 #include <array>
8 #include <assert.h>
9 #include <charconv>
10 #include <chrono>
11 #include <cmath>
12 #include <functional>
13 #include <iterator>
14 #include <limits>
15 #include <locale>
16 #include <optional>
17 #include <random>
18 #include <set>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <string>
24 #include <string_view>
25 #include <system_error>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
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"
49 
50 using namespace std;
51 
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;
57 
58     vector<std::uint32_t> vec(n * k);
59 
60     puts("USAGE:");
61     puts("test.exe              : generates seed data from random_device.");
62 
63     if (argc == 1) {
64         random_device rd;
65         generate(vec.begin(), vec.end(), ref(rd));
66         puts("Generated seed data.");
67     } else {
68         puts("ERROR: Too many command-line arguments.");
69         abort();
70     }
71 
72     puts("SEED DATA:");
73     for (const auto& elem : vec) {
74         printf("%zu ", static_cast<std::size_t>(elem));
75     }
76     printf("\n");
77 
78     seed_seq seq(vec.cbegin(), vec.cend());
79 
80     mt64.seed(seq);
81 
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()));
86     }
87 }
88 
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));
93 
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) {
97 
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.
106 
107     constexpr std::size_t BufferPrefix = 20; // detect buffer underruns (specific value isn't important)
108 
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
113 
114     constexpr std::size_t BufferSuffix = 30; // detect buffer overruns (specific value isn't important)
115 
116     array<char, BufferPrefix + Space + BufferSuffix> buff;
117 
118     char* const buff_begin = buff.data();
119     char* const first      = buff_begin + BufferPrefix;
120     char* const buff_end   = buff_begin + buff.size();
121 
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.");
125 
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;
129 
130         buff.fill('@');
131         const auto is_fill_char = [](const char c) { return c == '@'; };
132 
133         to_chars_result result{};
134         if (opt_precision.has_value()) {
135             assert(opt_arg.has_value());
136 
137             if constexpr (is_floating_point_v<T>) {
138                 result = to_chars(first, last, value, opt_arg.value(), opt_precision.value());
139             } else {
140                 abort();
141             }
142         } else if (opt_arg.has_value()) {
143             result = to_chars(first, last, value, opt_arg.value());
144         } else {
145             result = to_chars(first, last, value);
146         }
147 
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));
154         } else {
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));
160         }
161     }
162 }
163 
164 template <typename T>
165 void test_integer_to_chars(const T value, const optional<int> opt_base, const string_view correct) {
166 
167     test_common_to_chars(value, opt_base, nullopt, correct);
168 
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();
172 
173         T dest = 0;
174 
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));
178 
179         assert(from_res.ptr == correct_last);
180         assert(from_res.ec == errc{});
181         assert(dest == value);
182     }
183 }
184 
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"};
189 
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"}}},
231     {3522553278ULL,
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"}}},
237     {UINT32_MAX,
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"}}},
243     {545890816626160ULL,
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"}}},
281     {UINT64_MAX,
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"}}},
291 };
292 
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",
305                 "-1ag", "-187"}}},
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"}}},
310     {-66748412,
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",
341             "-1wdu892toj0a9"}}},
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"}}},
352 };
353 
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");
359 
360         // tests [3, 71]
361         test_integer_to_chars(static_cast<T>(base * 2 - 1), base, output_max_digit[base]);
362 
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)]);
366             }
367         }
368 
369         if constexpr (is_signed_v<T>) {
370             test_integer_to_chars(static_cast<T>(-1), base, "-1");
371 
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)]);
375                 }
376             }
377         }
378     }
379 
380     test_integer_to_chars(static_cast<T>(42), nullopt, "42");
381 }
382 
383 enum class TestFromCharsMode { Normal, SignalingNaN };
384 
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) {
389 
390     if constexpr (is_integral_v<T>) {
391         assert(mode == TestFromCharsMode::Normal);
392     }
393 
394     constexpr T unmodified = 111;
395 
396     T dest = unmodified;
397 
398     const from_chars_result result = from_chars(input.data(), input.data() + input.size(), dest, base_or_fmt);
399 
400     assert(result.ptr == input.data() + correct_idx);
401     assert(result.ec == correct_ec);
402 
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()));
409             } else {
410                 assert(mode == TestFromCharsMode::SignalingNaN);
411                 assert(!opt_correct.has_value());
412                 assert(isnan(dest));
413             }
414         } else {
415             assert(opt_correct.has_value());
416             assert(dest == opt_correct.value());
417         }
418     } else {
419         assert(!opt_correct.has_value());
420         assert(dest == unmodified);
421     }
422 }
423 
424 constexpr errc inv_arg = errc::invalid_argument;
425 constexpr errc out_ran = errc::result_out_of_range;
426 
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
436 
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"
439         }
440 
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
449 
450         vector<char> bogus_digits;
451 
452         if (base < 10) {
453             bogus_digits = {static_cast<char>('0' + base), 'A', 'a'};
454         } else {
455             // '[' and '{' are bogus for base 36
456             bogus_digits = {static_cast<char>('A' + (base - 10)), static_cast<char>('a' + (base - 10))};
457         }
458 
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
462         }
463 
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));
467 
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));
473         }
474 
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));
479 
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);
483 
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);
487         }
488     }
489 
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));
496     }
497 
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'
501 
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'
505     }
506 }
507 
508 template <typename T>
509 void test_integer() {
510     test_integer_to_chars<T>();
511     test_integer_from_chars<T>();
512 }
513 
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>();
520     test_integer<int>();
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>();
526 
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
533 
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
539 
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
545 }
546 
547 void assert_message_bits(const bool b, const char* const msg, const std::uint32_t bits) {
548     if (!b) {
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");
553         abort();
554     }
555 }
556 
557 void assert_message_bits(const bool b, const char* const msg, const std::uint64_t bits) {
558     if (!b) {
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");
564         abort();
565     }
566 }
567 
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.");
571 
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);
575 
576 constexpr std::uint32_t PrefixesToTest = 100; // Tunable for test coverage vs. performance.
577 static_assert(PrefixesToTest >= 1, "Must test at least 1 prefix.");
578 
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.");
583 
584 template <bool IsDouble>
585 void test_floating_prefix(const conditional_t<IsDouble, std::uint64_t, std::uint32_t> prefix) {
586 
587     using UIntType     = conditional_t<IsDouble, std::uint64_t, std::uint32_t>;
588     using FloatingType = conditional_t<IsDouble, double, float>;
589 
590     // "-1.2345678901234567e-100" or "-1.23456789e-10"
591     constexpr std::size_t buffer_size = IsDouble ? 24 : 15;
592     char buffer[buffer_size];
593 
594 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
595     FloatingType val;
596 #endif
597 
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];
606 
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];
610 
611     for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
612         const UIntType bits      = prefix + frac;
613         const FloatingType input = _Bit_cast<FloatingType>(bits);
614 
615         {
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;
620 
621             const auto from_result = from_chars(buffer, last, val);
622 
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
627         }
628 
629         {
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));
634 
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);
640             }
641         }
642     }
643 }
644 
645 template <bool IsDouble>
646 void test_floating_hex_prefix(const conditional_t<IsDouble, std::uint64_t, std::uint32_t> prefix) {
647 
648     using UIntType     = conditional_t<IsDouble, std::uint64_t, std::uint32_t>;
649     using FloatingType = conditional_t<IsDouble, double, float>;
650 
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.
655 
656     // "-1.fffffffffffffp+1023" or "-1.fffffep+127"
657     constexpr std::size_t buffer_size = IsDouble ? 22 : 14;
658     char buffer[buffer_size];
659 
660 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
661     FloatingType val;
662 #endif
663 
664     for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
665         const UIntType bits      = prefix + frac;
666         const FloatingType input = _Bit_cast<FloatingType>(bits);
667 
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);
670 
671 #ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
672         const char* const last = to_result.ptr;
673 
674         const auto from_result = from_chars(buffer, last, val, chars_format::hex);
675 
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
680     }
681 }
682 
683 template <bool IsDouble>
684 void test_floating_precision_prefix(const conditional_t<IsDouble, std::uint64_t, std::uint32_t> prefix) {
685 
686     using UIntType     = conditional_t<IsDouble, std::uint64_t, std::uint32_t>;
687     using FloatingType = conditional_t<IsDouble, double, float>;
688 
689     // Precision for min subnormal in fixed notation. (More than enough for scientific notation.)
690     constexpr int precision = IsDouble ? 1074 : 149;
691 
692     // Number of digits for max normal in fixed notation.
693     constexpr int max_integer_length = IsDouble ? 309 : 39;
694 
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
698                                           + 1 // decimal point
699                                           + precision; // fractional digits
700     char charconv_buffer[charconv_buffer_size];
701 
702     constexpr std::size_t stdio_buffer_size = charconv_buffer_size + 1; // null terminator
703     char stdio_buffer[stdio_buffer_size];
704 
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
710 
711     for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
712         const UIntType bits      = prefix + frac;
713         const FloatingType input = _Bit_cast<FloatingType>(bits);
714 
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));
718 
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);
722 
723         assert_message_bits(charconv_sv == stdio_sv, "fixed precision output", bits);
724 
725 
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));
729 
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;
733 
734         assert_message_bits(charconv_sv == stdio_sv, "scientific precision output", bits);
735 
736 
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));
740 
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;
744 
745         assert_message_bits(charconv_sv == stdio_sv, "general precision output", bits);
746     }
747 }
748 
749 void test_floating_prefixes(mt19937_64& mt64) {
750     {
751         set<std::uint64_t> prefixes64;
752 
753         while (prefixes64.size() < PrefixesToTest) {
754             const std::uint64_t val = mt64();
755 
756             if ((val & 0x7FF0000000000000ULL) != 0x7FF0000000000000ULL) { // skip INF/NAN
757                 prefixes64.insert(val & Mask64);
758             }
759         }
760 
761         for (const auto& prefix : prefixes64) {
762             test_floating_prefix<true>(prefix);
763             test_floating_precision_prefix<true>(prefix);
764         }
765 
766         test_floating_hex_prefix<true>(*prefixes64.begin()); // save time by testing fewer hexfloats
767     }
768 
769     {
770         set<std::uint32_t> prefixes32;
771 
772         while (prefixes32.size() < PrefixesToTest) {
773             const std::uint32_t val = static_cast<std::uint32_t>(mt64());
774 
775             if ((val & 0x7F800000U) != 0x7F800000U) { // skip INF/NAN
776                 prefixes32.insert(val & Mask32);
777             }
778         }
779 
780         for (const auto& prefix : prefixes32) {
781             test_floating_prefix<false>(prefix);
782             test_floating_precision_prefix<false>(prefix);
783         }
784 
785         test_floating_hex_prefix<false>(*prefixes32.begin()); // save time by testing fewer hexfloats
786     }
787 }
788 
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
801 
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
812 
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
816     }
817 
818     constexpr T inf  = numeric_limits<T>::infinity();
819     constexpr T qnan = numeric_limits<T>::quiet_NaN();
820 
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);
825 
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);
830 
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);
842 
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);
854 
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.
857 #  ifdef _MSC_VER
858     test_from_chars<T>("nan(InD)", fmt, 8, errc{}, -qnan);
859     test_from_chars<T>("-nan(InD)", fmt, 9, errc{}, -qnan);
860 
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);
863 #  endif
864 
865     switch (fmt) {
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});
900         break;
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});
904         break;
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});
908         break;
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});
942         break;
943     }
944 }
945 #endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
946 
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) {
950 
951     test_common_to_chars(value, opt_fmt, opt_precision, correct);
952 }
953 
954 void all_floating_tests(mt19937_64& mt64) {
955     test_floating_prefixes(mt64);
956 
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);
961     }
962     // Test rounding.
963 
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);
967     }
968 
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);
972     }
973 
974     {
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;
981 
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);
985     }
986 
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));
990     }
991 
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));
994     }
995 #endif //  TEST_HAS_FROM_CHARS_FLOATING_POINT
996 
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);
1001         } else {
1002             test_floating_to_chars(t.value, t.fmt, nullopt, t.correct);
1003         }
1004     }
1005 
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);
1010         } else {
1011             test_floating_to_chars(t.value, t.fmt, nullopt, t.correct);
1012         }
1013     }
1014 
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);
1018     }
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);
1021     }
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);
1024     }
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);
1027     }
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);
1030     }
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);
1033     }
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);
1036     }
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);
1039     }
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);
1042     }
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);
1045     }
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);
1048     }
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);
1051     }
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);
1054     }
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);
1057     }
1058 }
1059 
1060 int main(int argc, char** argv) {
1061     const auto start = chrono::steady_clock::now();
1062 
1063     mt19937_64 mt64;
1064 
1065     initialize_randomness(mt64, argc, argv);
1066 
1067     all_integer_tests();
1068 
1069     all_floating_tests(mt64);
1070 
1071     const auto finish  = chrono::steady_clock::now();
1072     const long long ms = chrono::duration_cast<chrono::milliseconds>(finish - start).count();
1073 
1074     puts("PASS");
1075     printf("Randomized test cases: %zu\n", static_cast<std::size_t>(PrefixesToTest * Fractions));
1076     printf("Total time: %lld ms\n", ms);
1077 
1078     if (ms < 3'000) {
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.");
1082     }
1083 }
1084