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