brintos

brintos / llvm-project-archived public Read only

0
0
Text · 57.9 KiB · ace6d46 Raw
1084 lines · cpp
1// Copyright (c) Microsoft Corporation.2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception3 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 50using namespace std;51 52void 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 89static_assert((chars_format::scientific & chars_format::fixed) == chars_format{});90static_assert((chars_format::scientific & chars_format::hex) == chars_format{});91static_assert((chars_format::fixed & chars_format::hex) == chars_format{});92static_assert(chars_format::general == (chars_format::fixed | chars_format::scientific));93 94template <typename T, typename Optional>95void 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 sizes99    // less than correct.size(), this verifies that the too-small buffer is correctly detected, and that we don't100    // attempt to write outside of it, even by a single char. (This exhaustive validation is necessary because the101    // implementation must check whenever it attempts to write. Sometimes we can calculate the total size and perform102    // 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 succeed104    // without attempting to write to extra chars even when they're available. Finally, we also verify that we aren't105    // 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 binary110                           : is_same_v<T, float>111                               ? 1 + 151 // worst case: negative min subnormal float, fixed notation112                               : 1 + 1076; // worst case: negative min subnormal double, fixed notation113 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 unspecified153            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 164template <typename T>165void 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}]186constexpr 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}]191constexpr std::uint64_t stress_chunks_positive                          = 12000000345000678900ULL;192constexpr 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}]294constexpr std::int64_t stress_chunks_negative                          = -9000876000000054321LL;295constexpr 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 354template <typename T>355void 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 383enum class TestFromCharsMode { Normal, SignalingNaN };384 385template <typename T, typename BaseOrFmt>386void 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 424constexpr errc inv_arg = errc::invalid_argument;425constexpr errc out_ran = errc::result_out_of_range;426 427template <typename T>428void test_integer_from_chars() {429    for (int base = 2; base <= 36; ++base) {430        test_from_chars<T>("", base, 0, inv_arg); // no characters431        test_from_chars<T>("@1", base, 0, inv_arg); // '@' is bogus432        test_from_chars<T>(".1", base, 0, inv_arg); // '.' is bogus, for integers433        test_from_chars<T>("+1", base, 0, inv_arg); // '+' is bogus, N4713 23.20.3 [charconv.from.chars]/3434                                                    // "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 sequence436 437        if constexpr (is_unsigned_v<T>) { // N4713 23.20.3 [charconv.from.chars]/3438            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 characters444        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 repeated449 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 36456            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 digit462        }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 the476        // 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 sequence491    // 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 508template <typename T>509void test_integer() {510    test_integer_to_chars<T>();511    test_integer_from_chars<T>();512}513 514void 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 risky529    test_from_chars<unsigned int>("4294967294", 10, 10, errc{}, 4294967294U); // risky with good digit530    test_from_chars<unsigned int>("4294967295", 10, 10, errc{}, 4294967295U); // risky with max digit531    test_from_chars<unsigned int>("4294967296", 10, 10, out_ran); // risky with bad digit532    test_from_chars<unsigned int>("4294967300", 10, 10, out_ran); // beyond risky533 534    test_from_chars<int>("2147483639", 10, 10, errc{}, 2147483639); // not risky535    test_from_chars<int>("2147483646", 10, 10, errc{}, 2147483646); // risky with good digit536    test_from_chars<int>("2147483647", 10, 10, errc{}, 2147483647); // risky with max digit537    test_from_chars<int>("2147483648", 10, 10, out_ran); // risky with bad digit538    test_from_chars<int>("2147483650", 10, 10, out_ran); // beyond risky539 540    test_from_chars<int>("-2147483639", 10, 11, errc{}, -2147483639); // not risky541    test_from_chars<int>("-2147483647", 10, 11, errc{}, -2147483647); // risky with good digit542    test_from_chars<int>("-2147483648", 10, 11, errc{}, -2147483647 - 1); // risky with max digit543    test_from_chars<int>("-2147483649", 10, 11, out_ran); // risky with bad digit544    test_from_chars<int>("-2147483650", 10, 11, out_ran); // beyond risky545}546 547void 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 557void 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 568constexpr std::uint32_t FractionBits = 10; // Tunable for test coverage vs. performance.569static_assert(FractionBits >= 1, "Must test at least 1 fraction bit.");570static_assert(FractionBits <= 23, "There are only 23 fraction bits in a float.");571 572constexpr std::uint32_t Fractions = 1U << FractionBits;573constexpr std::uint32_t Mask32    = ~((1U << FractionBits) - 1U);574constexpr std::uint64_t Mask64    = ~((1ULL << FractionBits) - 1ULL);575 576constexpr std::uint32_t PrefixesToTest = 100; // Tunable for test coverage vs. performance.577static_assert(PrefixesToTest >= 1, "Must test at least 1 prefix.");578 579constexpr std::uint32_t PrefixLimit = 2 // sign bit580                               * 255 // non-INF/NAN exponents for float581                               * (1U << (23 - FractionBits)); // fraction bits in prefix582static_assert(PrefixesToTest <= PrefixLimit, "Too many prefixes.");583 584template <bool IsDouble>585void 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_POINT595    FloatingType val;596#endif597 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 sign602    // + 325 (for double; 46 for float) characters in the "0.000~~~000" prefix of the min subnormal603    // + 17 (for double; 9 for float) characters for round-trip digits604    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 terminator608    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_POINT619            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_POINT627        }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 645template <bool IsDouble>646void 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_POINT661    FloatingType val;662#endif663 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_POINT672        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_POINT680    }681}682 683template <bool IsDouble>684void 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 sign697                                          + max_integer_length // integer digits698                                          + 1 // decimal point699                                          + precision; // fractional digits700    char charconv_buffer[charconv_buffer_size];701 702    constexpr std::size_t stdio_buffer_size = charconv_buffer_size + 1; // null terminator703    char stdio_buffer[stdio_buffer_size];704 705    // 1 character for a negative sign706    // + worst cases: 0x1.fffffffffffffp-1022 and 0x1.fffffep-126f707    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 terminator710 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 749void 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/NAN757                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 hexfloats767    }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/NAN776                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 hexfloats786    }787}788 789#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT790template <typename T>791void test_floating_from_chars(const chars_format fmt) {792    test_from_chars<T>("", fmt, 0, inv_arg); // no characters793    test_from_chars<T>("@1", fmt, 0, inv_arg); // '@' is bogus794    test_from_chars<T>("z1", fmt, 0, inv_arg); // 'z' is bogus795    test_from_chars<T>(".", fmt, 0, inv_arg); // '.' without digits is bogus796    test_from_chars<T>("+1", fmt, 0, inv_arg); // '+' is bogus797    test_from_chars<T>(" 1", fmt, 0, inv_arg); // ' ' is bogus798    test_from_chars<T>("p5", fmt, 0, inv_arg); // binary-exponent-part without digits is bogus799    test_from_chars<T>("in", fmt, 0, inv_arg); // incomplete inf is bogus800    test_from_chars<T>("na", fmt, 0, inv_arg); // incomplete nan is bogus801 802    test_from_chars<T>("-", fmt, 0, inv_arg); // '-' followed by no characters803    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-part809    test_from_chars<T>("-in", fmt, 0, inv_arg); // '-' followed by bogus incomplete inf810    test_from_chars<T>("-na", fmt, 0, inv_arg); // '-' followed by bogus incomplete nan811    test_from_chars<T>("--1", fmt, 0, inv_arg); // '-' can't be repeated812 813    if (fmt != chars_format::hex) { // "e5" are valid hexits814        test_from_chars<T>("e5", fmt, 0, inv_arg); // exponent-part without digits is bogus815        test_from_chars<T>("-e5", fmt, 0, inv_arg); // '-' followed by bogus exponent-part816    }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_VER858    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#  endif864 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 warning872        test_from_chars<T>(".14", fmt, 3, errc{}, static_cast<T>(.14)); // avoid truncation warning873        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 warning879        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 warning882        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_POINT946 947template <typename T>948void 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 954void all_floating_tests(mt19937_64& mt64) {955    test_floating_prefixes(mt64);956 957#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT958    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 differently976        // 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_POINT996 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 1060int 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