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 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> 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> 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> 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> 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> 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> 530 void test_integer() { 531 test_integer_to_chars<T>(); 532 test_integer_from_chars<T>(); 533 } 534 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 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 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> 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> 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> 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 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> 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 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 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