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