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