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