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