1// Copyright (c) Microsoft Corporation.
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3
4#include "test.hpp"
5
6#include <algorithm>
7#include <array>
8#include <assert.h>
9#include <charconv>
10#include <chrono>
11#include <cmath>
12#include <functional>
13#include <iterator>
14#include <limits>
15#include <locale>
16#include <optional>
17#include <random>
18#include <set>
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <string>
24#include <string_view>
25#include <system_error>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30#include "double_fixed_precision_to_chars_test_cases_1.hpp"
31#include "double_fixed_precision_to_chars_test_cases_2.hpp"
32#include "double_fixed_precision_to_chars_test_cases_3.hpp"
33#include "double_fixed_precision_to_chars_test_cases_4.hpp"
34#include "double_from_chars_test_cases.hpp"
35#include "double_general_precision_to_chars_test_cases.hpp"
36#include "double_hex_precision_to_chars_test_cases.hpp"
37#include "double_scientific_precision_to_chars_test_cases_1.hpp"
38#include "double_scientific_precision_to_chars_test_cases_2.hpp"
39#include "double_scientific_precision_to_chars_test_cases_3.hpp"
40#include "double_scientific_precision_to_chars_test_cases_4.hpp"
41#include "double_to_chars_test_cases.hpp"
42#include "float_fixed_precision_to_chars_test_cases.hpp"
43#include "float_from_chars_test_cases.hpp"
44#include "float_general_precision_to_chars_test_cases.hpp"
45#include "float_hex_precision_to_chars_test_cases.hpp"
46#include "float_scientific_precision_to_chars_test_cases.hpp"
47#include "float_to_chars_test_cases.hpp"
48#include "floating_point_test_cases.hpp"
49
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(s: "USAGE:");
61 puts(s: "test.exe : generates seed data from random_device.");
62
63 if (argc == 1) {
64 random_device rd;
65 generate(first: vec.begin(), last: vec.end(), gen: ref(t&: rd));
66 puts(s: "Generated seed data.");
67 } else {
68 puts(s: "ERROR: Too many command-line arguments.");
69 abort();
70 }
71
72 puts(s: "SEED DATA:");
73 for (const auto& elem : vec) {
74 printf(format: "%zu ", static_cast<std::size_t>(elem));
75 }
76 printf(format: "\n");
77
78 seed_seq seq(vec.cbegin(), vec.cend());
79
80 mt64.seed(q&: seq);
81
82 puts(s: "Successfully seeded mt64. First three values:");
83 for (int i = 0; i < 3; ++i) {
84 // libc++ uses long for 64-bit values.
85 printf(format: "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 sizes
99 // less than correct.size(), this verifies that the too-small buffer is correctly detected, and that we don't
100 // attempt to write outside of it, even by a single char. (This exhaustive validation is necessary because the
101 // implementation must check whenever it attempts to write. Sometimes we can calculate the total size and perform
102 // a single check, but sometimes we need to check when writing each part of the result.) Testing correct.size()
103 // verifies that we can succeed without overrunning, and testing slightly larger sizes verifies that we can succeed
104 // without attempting to write to extra chars even when they're available. Finally, we also verify that we aren't
105 // underrunning the buffer. This is a concern because sometimes we walk backwards when rounding.
106
107 constexpr std::size_t BufferPrefix = 20; // detect buffer underruns (specific value isn't important)
108
109 constexpr std::size_t Space = is_integral_v<T> ? 1 + 64 // worst case: -2^63 in binary
110 : is_same_v<T, float>
111 ? 1 + 151 // worst case: negative min subnormal float, fixed notation
112 : 1 + 1076; // worst case: negative min subnormal double, fixed notation
113
114 constexpr std::size_t BufferSuffix = 30; // detect buffer overruns (specific value isn't important)
115
116 array<char, BufferPrefix + Space + BufferSuffix> buff;
117
118 char* const buff_begin = buff.data();
119 char* const first = buff_begin + BufferPrefix;
120 char* const buff_end = buff_begin + buff.size();
121
122 constexpr std::size_t ExtraChars = 3;
123 static_assert(ExtraChars + 10 < BufferSuffix,
124 "The specific values aren't important, but there should be plenty of room to detect buffer overruns.");
125
126 for (std::size_t n = 0; n <= correct.size() + ExtraChars; ++n) {
127 assert(n <= static_cast<std::size_t>(buff_end - first));
128 char* const last = first + n;
129
130 buff.fill('@');
131 const auto is_fill_char = [](const char c) { return c == '@'; };
132
133 to_chars_result result{};
134 if (opt_precision.has_value()) {
135 assert(opt_arg.has_value());
136
137 if constexpr (is_floating_point_v<T>) {
138 result = to_chars(first, last, value, opt_arg.value(), opt_precision.value());
139 } else {
140 abort();
141 }
142 } else if (opt_arg.has_value()) {
143 result = to_chars(first, last, value, opt_arg.value());
144 } else {
145 result = to_chars(first, last, value);
146 }
147
148 if (n < correct.size()) {
149 assert(result.ptr == last);
150 assert(result.ec == errc::value_too_large);
151 assert(all_of(buff_begin, first, is_fill_char));
152 // [first, last) is unspecified
153 assert(all_of(last, buff_end, is_fill_char));
154 } else {
155 assert(result.ptr == first + correct.size());
156 assert(result.ec == errc{});
157 assert(all_of(buff_begin, first, is_fill_char));
158 assert(equal(first, result.ptr, correct.begin(), correct.end()));
159 assert(all_of(result.ptr, buff_end, is_fill_char));
160 }
161 }
162}
163
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, {._M_elems: {"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}, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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}, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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, {._M_elems: {"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 {._M_elems: {"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, {._M_elems: {"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 {._M_elems: {"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 {._M_elems: {"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, {._M_elems: {"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 characters
431 test_from_chars<T>("@1", base, 0, inv_arg); // '@' is bogus
432 test_from_chars<T>(".1", base, 0, inv_arg); // '.' is bogus, for integers
433 test_from_chars<T>("+1", base, 0, inv_arg); // '+' is bogus, N4713 23.20.3 [charconv.from.chars]/3
434 // "a minus sign is the only sign that may appear"
435 test_from_chars<T>(" 1", base, 0, inv_arg); // ' ' is bogus, no whitespace in subject sequence
436
437 if constexpr (is_unsigned_v<T>) { // N4713 23.20.3 [charconv.from.chars]/3
438 test_from_chars<T>("-1", base, 0, inv_arg); // "and only if value has a signed type"
439 }
440
441 // N4713 23.20.3 [charconv.from.chars]/1 "[ Note: If the pattern allows for an optional sign,
442 // but the string has no digit characters following the sign, no characters match the pattern. -end note ]"
443 test_from_chars<T>("-", base, 0, inv_arg); // '-' followed by no characters
444 test_from_chars<T>("-@1", base, 0, inv_arg); // '-' followed by bogus '@'
445 test_from_chars<T>("-.1", base, 0, inv_arg); // '-' followed by bogus '.'
446 test_from_chars<T>("-+1", base, 0, inv_arg); // '-' followed by bogus '+'
447 test_from_chars<T>("- 1", base, 0, inv_arg); // '-' followed by bogus ' '
448 test_from_chars<T>("--1", base, 0, inv_arg); // '-' can't be repeated
449
450 vector<char> bogus_digits;
451
452 if (base < 10) {
453 bogus_digits = {static_cast<char>('0' + base), 'A', 'a'};
454 } else {
455 // '[' and '{' are bogus for base 36
456 bogus_digits = {static_cast<char>('A' + (base - 10)), static_cast<char>('a' + (base - 10))};
457 }
458
459 for (const auto& bogus : bogus_digits) {
460 test_from_chars<T>(bogus + "1"s, base, 0, inv_arg); // bogus digit (for this base)
461 test_from_chars<T>("-"s + bogus + "1"s, base, 0, inv_arg); // '-' followed by bogus digit
462 }
463
464 // Test leading zeroes.
465 test_from_chars<T>(string(100, '0'), base, 100, errc{}, static_cast<T>(0));
466 test_from_chars<T>(string(100, '0') + "11"s, base, 102, errc{}, static_cast<T>(base + 1));
467
468 // Test negative zero and negative leading zeroes.
469 if constexpr (is_signed_v<T>) {
470 test_from_chars<T>("-0", base, 2, errc{}, static_cast<T>(0));
471 test_from_chars<T>("-"s + string(100, '0'), base, 101, errc{}, static_cast<T>(0));
472 test_from_chars<T>("-"s + string(100, '0') + "11"s, base, 103, errc{}, static_cast<T>(-base - 1));
473 }
474
475 // N4713 23.20.3 [charconv.from.chars]/1 "The member ptr of the return value points to the
476 // first character not matching the pattern, or has the value last if all characters match."
477 test_from_chars<T>("11", base, 2, errc{}, static_cast<T>(base + 1));
478 test_from_chars<T>("11@@@", base, 2, errc{}, static_cast<T>(base + 1));
479
480 // When overflowing, we need to keep consuming valid digits, in order to return ptr correctly.
481 test_from_chars<T>(string(100, '1'), base, 100, out_ran);
482 test_from_chars<T>(string(100, '1') + "@@@"s, base, 100, out_ran);
483
484 if constexpr (is_signed_v<T>) {
485 test_from_chars<T>("-"s + string(100, '1'), base, 101, out_ran);
486 test_from_chars<T>("-"s + string(100, '1') + "@@@"s, base, 101, out_ran);
487 }
488 }
489
490 // N4713 23.20.3 [charconv.from.chars]/3 "The pattern is the expected form of the subject sequence
491 // in the "C" locale for the given nonzero base, as described for strtol"
492 // C11 7.22.1.4/3 "The letters from a (or A) through z (or Z) are ascribed the values 10 through 35"
493 for (int i = 0; i < 26; ++i) {
494 test_from_chars<T>(string(1, static_cast<char>('A' + i)), 36, 1, errc{}, static_cast<T>(10 + i));
495 test_from_chars<T>(string(1, static_cast<char>('a' + i)), 36, 1, errc{}, static_cast<T>(10 + i));
496 }
497
498 // N4713 23.20.3 [charconv.from.chars]/3 "no "0x" or "0X" prefix shall appear if the value of base is 16"
499 test_from_chars<T>("0x1729", 16, 1, errc{}, static_cast<T>(0)); // reads '0', stops at 'x'
500 test_from_chars<T>("0X1729", 16, 1, errc{}, static_cast<T>(0)); // reads '0', stops at 'X'
501
502 if constexpr (is_signed_v<T>) {
503 test_from_chars<T>("-0x1729", 16, 2, errc{}, static_cast<T>(0)); // reads "-0", stops at 'x'
504 test_from_chars<T>("-0X1729", 16, 2, errc{}, static_cast<T>(0)); // reads "-0", stops at 'X'
505 }
506}
507
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>(input: "4294967289", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 4294967289U); // not risky
529 test_from_chars<unsigned int>(input: "4294967294", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 4294967294U); // risky with good digit
530 test_from_chars<unsigned int>(input: "4294967295", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 4294967295U); // risky with max digit
531 test_from_chars<unsigned int>(input: "4294967296", base_or_fmt: 10, correct_idx: 10, correct_ec: out_ran); // risky with bad digit
532 test_from_chars<unsigned int>(input: "4294967300", base_or_fmt: 10, correct_idx: 10, correct_ec: out_ran); // beyond risky
533
534 test_from_chars<int>(input: "2147483639", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 2147483639); // not risky
535 test_from_chars<int>(input: "2147483646", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 2147483646); // risky with good digit
536 test_from_chars<int>(input: "2147483647", base_or_fmt: 10, correct_idx: 10, correct_ec: errc{}, opt_correct: 2147483647); // risky with max digit
537 test_from_chars<int>(input: "2147483648", base_or_fmt: 10, correct_idx: 10, correct_ec: out_ran); // risky with bad digit
538 test_from_chars<int>(input: "2147483650", base_or_fmt: 10, correct_idx: 10, correct_ec: out_ran); // beyond risky
539
540 test_from_chars<int>(input: "-2147483639", base_or_fmt: 10, correct_idx: 11, correct_ec: errc{}, opt_correct: -2147483639); // not risky
541 test_from_chars<int>(input: "-2147483647", base_or_fmt: 10, correct_idx: 11, correct_ec: errc{}, opt_correct: -2147483647); // risky with good digit
542 test_from_chars<int>(input: "-2147483648", base_or_fmt: 10, correct_idx: 11, correct_ec: errc{}, opt_correct: -2147483647 - 1); // risky with max digit
543 test_from_chars<int>(input: "-2147483649", base_or_fmt: 10, correct_idx: 11, correct_ec: out_ran); // risky with bad digit
544 test_from_chars<int>(input: "-2147483650", base_or_fmt: 10, correct_idx: 11, correct_ec: out_ran); // beyond risky
545}
546
547void assert_message_bits(const bool b, const char* const msg, const std::uint32_t bits) {
548 if (!b) {
549 fprintf(stderr, format: "%s failed for 0x%08zX\n", msg, static_cast<std::size_t>(bits));
550 fprintf(stderr, format: "This is a randomized test.\n");
551 fprintf(stderr, format: "DO NOT IGNORE/RERUN THIS FAILURE.\n");
552 fprintf(stderr, format: "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, format: "%s failed for 0x%016llX\n", msg, static_cast<unsigned long long>(bits));
561 fprintf(stderr, format: "This is a randomized test.\n");
562 fprintf(stderr, format: "DO NOT IGNORE/RERUN THIS FAILURE.\n");
563 fprintf(stderr, format: "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 bit
580 * 255 // non-INF/NAN exponents for float
581 * (1U << (23 - FractionBits)); // fraction bits in prefix
582static_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_POINT
595 FloatingType val;
596#endif
597
598 // Exact sizes are difficult to prove for fixed notation.
599 // This must be at least (IsDouble ? 327 : 48), and I suspect that that's exact.
600 // Here's a loose upper bound:
601 // 1 character for a negative sign
602 // + 325 (for double; 46 for float) characters in the "0.000~~~000" prefix of the min subnormal
603 // + 17 (for double; 9 for float) characters for round-trip digits
604 constexpr std::size_t fixed_buffer_size = IsDouble ? 1 + 325 + 17 : 1 + 46 + 9;
605 char fixed_buffer[fixed_buffer_size];
606
607 // worst case: negative sign + max normal + null terminator
608 constexpr std::size_t stdio_buffer_size = 1 + (IsDouble ? 309 : 39) + 1;
609 char stdio_buffer[stdio_buffer_size];
610
611 for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
612 const UIntType bits = prefix + frac;
613 const FloatingType input = _Bit_cast<FloatingType>(bits);
614
615 {
616 const auto to_result = to_chars(buffer, end(buffer), input, chars_format::scientific);
617 assert_message_bits(to_result.ec == errc{}, "to_result.ec", bits);
618#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
619 const char* const last = to_result.ptr;
620
621 const auto from_result = from_chars(buffer, last, val);
622
623 assert_message_bits(from_result.ptr == last, "from_result.ptr", bits);
624 assert_message_bits(from_result.ec == errc{}, "from_result.ec", bits);
625 assert_message_bits(_Bit_cast<UIntType>(val) == bits, "round-trip", bits);
626#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
627 }
628
629 {
630 // Also verify that to_chars() and sprintf_s() emit the same output for integers in fixed notation.
631 const auto fixed_result = to_chars(fixed_buffer, end(fixed_buffer), input, chars_format::fixed);
632 assert_message_bits(fixed_result.ec == errc{}, "fixed_result.ec", bits);
633 const string_view fixed_sv(fixed_buffer, static_cast<std::size_t>(fixed_result.ptr - fixed_buffer));
634
635 if (find(first: fixed_sv.begin(), last: fixed_sv.end(), val: '.') == 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_POINT
661 FloatingType val;
662#endif
663
664 for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
665 const UIntType bits = prefix + frac;
666 const FloatingType input = _Bit_cast<FloatingType>(bits);
667
668 const auto to_result = to_chars(buffer, end(buffer), input, chars_format::hex);
669 assert_message_bits(to_result.ec == errc{}, "(hex) to_result.ec", bits);
670
671#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
672 const char* const last = to_result.ptr;
673
674 const auto from_result = from_chars(buffer, last, val, chars_format::hex);
675
676 assert_message_bits(from_result.ptr == last, "(hex) from_result.ptr", bits);
677 assert_message_bits(from_result.ec == errc{}, "(hex) from_result.ec", bits);
678 assert_message_bits(_Bit_cast<UIntType>(val) == bits, "(hex) round-trip", bits);
679#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
680 }
681}
682
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 sign
697 + max_integer_length // integer digits
698 + 1 // decimal point
699 + precision; // fractional digits
700 char charconv_buffer[charconv_buffer_size];
701
702 constexpr std::size_t stdio_buffer_size = charconv_buffer_size + 1; // null terminator
703 char stdio_buffer[stdio_buffer_size];
704
705 // 1 character for a negative sign
706 // + worst cases: 0x1.fffffffffffffp-1022 and 0x1.fffffep-126f
707 constexpr std::size_t general_buffer_size = 1 + (IsDouble ? 773 : 117);
708 char general_buffer[general_buffer_size];
709 char general_stdio_buffer[general_buffer_size + 1]; // + null terminator
710
711 for (std::uint32_t frac = 0; frac < Fractions; ++frac) {
712 const UIntType bits = prefix + frac;
713 const FloatingType input = _Bit_cast<FloatingType>(bits);
714
715 auto result = to_chars(charconv_buffer, end(charconv_buffer), input, chars_format::fixed, precision);
716 assert_message_bits(result.ec == errc{}, "to_chars fixed precision", bits);
717 string_view charconv_sv(charconv_buffer, static_cast<std::size_t>(result.ptr - charconv_buffer));
718
719 int stdio_ret = sprintf_s(stdio_buffer, size(stdio_buffer), "%.*f", precision, input);
720 assert_message_bits(stdio_ret != -1, "sprintf_s fixed precision", bits);
721 string_view stdio_sv(stdio_buffer);
722
723 assert_message_bits(charconv_sv == stdio_sv, "fixed precision output", bits);
724
725
726 result = to_chars(charconv_buffer, end(charconv_buffer), input, chars_format::scientific, precision);
727 assert_message_bits(result.ec == errc{}, "to_chars scientific precision", bits);
728 charconv_sv = string_view(charconv_buffer, static_cast<std::size_t>(result.ptr - charconv_buffer));
729
730 stdio_ret = sprintf_s(stdio_buffer, size(stdio_buffer), "%.*e", precision, input);
731 assert_message_bits(stdio_ret != -1, "sprintf_s scientific precision", bits);
732 stdio_sv = stdio_buffer;
733
734 assert_message_bits(charconv_sv == stdio_sv, "scientific precision output", bits);
735
736
737 result = to_chars(general_buffer, end(general_buffer), input, chars_format::general, 5000);
738 assert_message_bits(result.ec == errc{}, "to_chars general precision", bits);
739 charconv_sv = string_view(general_buffer, static_cast<std::size_t>(result.ptr - general_buffer));
740
741 stdio_ret = sprintf_s(general_stdio_buffer, size(general_stdio_buffer), "%.5000g", input);
742 assert_message_bits(stdio_ret != -1, "sprintf_s general precision", bits);
743 stdio_sv = general_stdio_buffer;
744
745 assert_message_bits(charconv_sv == stdio_sv, "general precision output", bits);
746 }
747}
748
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/NAN
757 prefixes64.insert(x: 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>(prefix: *prefixes64.begin()); // save time by testing fewer hexfloats
767 }
768
769 {
770 set<std::uint32_t> prefixes32;
771
772 while (prefixes32.size() < PrefixesToTest) {
773 const std::uint32_t val = static_cast<std::uint32_t>(mt64());
774
775 if ((val & 0x7F800000U) != 0x7F800000U) { // skip INF/NAN
776 prefixes32.insert(x: 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>(prefix: *prefixes32.begin()); // save time by testing fewer hexfloats
786 }
787}
788
789#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT
790template <typename T>
791void test_floating_from_chars(const chars_format fmt) {
792 test_from_chars<T>("", fmt, 0, inv_arg); // no characters
793 test_from_chars<T>("@1", fmt, 0, inv_arg); // '@' is bogus
794 test_from_chars<T>("z1", fmt, 0, inv_arg); // 'z' is bogus
795 test_from_chars<T>(".", fmt, 0, inv_arg); // '.' without digits is bogus
796 test_from_chars<T>("+1", fmt, 0, inv_arg); // '+' is bogus
797 test_from_chars<T>(" 1", fmt, 0, inv_arg); // ' ' is bogus
798 test_from_chars<T>("p5", fmt, 0, inv_arg); // binary-exponent-part without digits is bogus
799 test_from_chars<T>("in", fmt, 0, inv_arg); // incomplete inf is bogus
800 test_from_chars<T>("na", fmt, 0, inv_arg); // incomplete nan is bogus
801
802 test_from_chars<T>("-", fmt, 0, inv_arg); // '-' followed by no characters
803 test_from_chars<T>("-@1", fmt, 0, inv_arg); // '-' followed by bogus '@'
804 test_from_chars<T>("-z1", fmt, 0, inv_arg); // '-' followed by bogus 'z'
805 test_from_chars<T>("-.", fmt, 0, inv_arg); // '-' followed by bogus '.'
806 test_from_chars<T>("-+1", fmt, 0, inv_arg); // '-' followed by bogus '+'
807 test_from_chars<T>("- 1", fmt, 0, inv_arg); // '-' followed by bogus ' '
808 test_from_chars<T>("-p5", fmt, 0, inv_arg); // '-' followed by bogus binary-exponent-part
809 test_from_chars<T>("-in", fmt, 0, inv_arg); // '-' followed by bogus incomplete inf
810 test_from_chars<T>("-na", fmt, 0, inv_arg); // '-' followed by bogus incomplete nan
811 test_from_chars<T>("--1", fmt, 0, inv_arg); // '-' can't be repeated
812
813 if (fmt != chars_format::hex) { // "e5" are valid hexits
814 test_from_chars<T>("e5", fmt, 0, inv_arg); // exponent-part without digits is bogus
815 test_from_chars<T>("-e5", fmt, 0, inv_arg); // '-' followed by bogus exponent-part
816 }
817
818 constexpr T inf = numeric_limits<T>::infinity();
819 constexpr T qnan = numeric_limits<T>::quiet_NaN();
820
821 test_from_chars<T>("InF", fmt, 3, errc{}, inf);
822 test_from_chars<T>("infinite", fmt, 3, errc{}, inf);
823 test_from_chars<T>("iNfInItY", fmt, 8, errc{}, inf);
824 test_from_chars<T>("InfinityMeow", fmt, 8, errc{}, inf);
825
826 test_from_chars<T>("-InF", fmt, 4, errc{}, -inf);
827 test_from_chars<T>("-infinite", fmt, 4, errc{}, -inf);
828 test_from_chars<T>("-iNfInItY", fmt, 9, errc{}, -inf);
829 test_from_chars<T>("-InfinityMeow", fmt, 9, errc{}, -inf);
830
831 test_from_chars<T>("NaN", fmt, 3, errc{}, qnan);
832 test_from_chars<T>("nanotech", fmt, 3, errc{}, qnan);
833 test_from_chars<T>("nan(", fmt, 3, errc{}, qnan);
834 test_from_chars<T>("nan(@)", fmt, 3, errc{}, qnan);
835 test_from_chars<T>("nan(()", fmt, 3, errc{}, qnan);
836 test_from_chars<T>("nan(abc", fmt, 3, errc{}, qnan);
837 test_from_chars<T>("nan()", fmt, 5, errc{}, qnan);
838 test_from_chars<T>("nan(abc)def", fmt, 8, errc{}, qnan);
839 test_from_chars<T>("nan(_09AZaz)", fmt, 12, errc{}, qnan);
840 test_from_chars<T>("nan(int)", fmt, 8, errc{}, qnan);
841 test_from_chars<T>("nan(snap)", fmt, 9, errc{}, qnan);
842
843 test_from_chars<T>("-NaN", fmt, 4, errc{}, -qnan);
844 test_from_chars<T>("-nanotech", fmt, 4, errc{}, -qnan);
845 test_from_chars<T>("-nan(", fmt, 4, errc{}, -qnan);
846 test_from_chars<T>("-nan(@)", fmt, 4, errc{}, -qnan);
847 test_from_chars<T>("-nan(()", fmt, 4, errc{}, -qnan);
848 test_from_chars<T>("-nan(abc", fmt, 4, errc{}, -qnan);
849 test_from_chars<T>("-nan()", fmt, 6, errc{}, -qnan);
850 test_from_chars<T>("-nan(abc)def", fmt, 9, errc{}, -qnan);
851 test_from_chars<T>("-nan(_09AZaz)", fmt, 13, errc{}, -qnan);
852 test_from_chars<T>("-nan(int)", fmt, 9, errc{}, -qnan);
853 test_from_chars<T>("-nan(snap)", fmt, 10, errc{}, -qnan);
854
855 // The UCRT considers indeterminate NaN to be negative quiet NaN with no payload bits set.
856 // It parses "nan(ind)" and "-nan(ind)" identically.
857# ifdef _MSC_VER
858 test_from_chars<T>("nan(InD)", fmt, 8, errc{}, -qnan);
859 test_from_chars<T>("-nan(InD)", fmt, 9, errc{}, -qnan);
860
861 test_from_chars<T>("nan(SnAn)", fmt, 9, errc{}, nullopt, TestFromCharsMode::SignalingNaN);
862 test_from_chars<T>("-nan(SnAn)", fmt, 10, errc{}, nullopt, TestFromCharsMode::SignalingNaN);
863# endif
864
865 switch (fmt) {
866 case chars_format::general:
867 test_from_chars<T>("1729", fmt, 4, errc{}, T{1729});
868 test_from_chars<T>("1729e3", fmt, 6, errc{}, T{1729000});
869 test_from_chars<T>("10", fmt, 2, errc{}, T{10});
870 test_from_chars<T>("11.", fmt, 3, errc{}, T{11});
871 test_from_chars<T>("12.13", fmt, 5, errc{}, static_cast<T>(12.13)); // avoid truncation warning
872 test_from_chars<T>(".14", fmt, 3, errc{}, static_cast<T>(.14)); // avoid truncation warning
873 test_from_chars<T>("20e5", fmt, 4, errc{}, T{2000000});
874 test_from_chars<T>("21.e5", fmt, 5, errc{}, T{2100000});
875 test_from_chars<T>("22.23e5", fmt, 7, errc{}, T{2223000});
876 test_from_chars<T>(".24e5", fmt, 5, errc{}, T{24000});
877 test_from_chars<T>("33e+5", fmt, 5, errc{}, T{3300000});
878 test_from_chars<T>("33e-5", fmt, 5, errc{}, static_cast<T>(.00033)); // avoid truncation warning
879 test_from_chars<T>("4E7", fmt, 3, errc{}, T{40000000});
880 test_from_chars<T>("-00123abc", fmt, 6, errc{}, T{-123});
881 test_from_chars<T>(".0045000", fmt, 8, errc{}, static_cast<T>(.0045)); // avoid truncation warning
882 test_from_chars<T>("000", fmt, 3, errc{}, T{0});
883 test_from_chars<T>("0e9999", fmt, 6, errc{}, T{0});
884 test_from_chars<T>("0e-9999", fmt, 7, errc{}, T{0});
885 test_from_chars<T>("-000", fmt, 4, errc{}, T{-0.0});
886 test_from_chars<T>("-0e9999", fmt, 7, errc{}, T{-0.0});
887 test_from_chars<T>("-0e-9999", fmt, 8, errc{}, T{-0.0});
888 test_from_chars<T>("1e9999", fmt, 6, errc::result_out_of_range, inf);
889 test_from_chars<T>("-1e9999", fmt, 7, errc::result_out_of_range, -inf);
890 test_from_chars<T>("1e-9999", fmt, 7, errc::result_out_of_range, T{0});
891 test_from_chars<T>("-1e-9999", fmt, 8, errc::result_out_of_range, T{-0.0});
892 test_from_chars<T>("1" + string(6000, '0'), fmt, 6001, errc::result_out_of_range, inf);
893 test_from_chars<T>("-1" + string(6000, '0'), fmt, 6002, errc::result_out_of_range, -inf);
894 test_from_chars<T>("." + string(6000, '0') + "1", fmt, 6002, errc::result_out_of_range, T{0});
895 test_from_chars<T>("-." + string(6000, '0') + "1", fmt, 6003, errc::result_out_of_range, T{-0.0});
896 test_from_chars<T>("1" + string(500, '0'), fmt, 501, errc::result_out_of_range, inf);
897 test_from_chars<T>("-1" + string(500, '0'), fmt, 502, errc::result_out_of_range, -inf);
898 test_from_chars<T>("." + string(500, '0') + "1", fmt, 502, errc::result_out_of_range, T{0});
899 test_from_chars<T>("-." + string(500, '0') + "1", fmt, 503, errc::result_out_of_range, T{-0.0});
900 break;
901 case chars_format::scientific:
902 test_from_chars<T>("1729", fmt, 0, inv_arg);
903 test_from_chars<T>("1729e3", fmt, 6, errc{}, T{1729000});
904 break;
905 case chars_format::fixed:
906 test_from_chars<T>("1729", fmt, 4, errc{}, T{1729});
907 test_from_chars<T>("1729e3", fmt, 4, errc{}, T{1729});
908 break;
909 case chars_format::hex:
910 test_from_chars<T>("0x123", fmt, 1, errc{}, T{0});
911 test_from_chars<T>("a0", fmt, 2, errc{}, T{160});
912 test_from_chars<T>("a1.", fmt, 3, errc{}, T{161});
913 test_from_chars<T>("a2.a3", fmt, 5, errc{}, T{162.63671875});
914 test_from_chars<T>(".a4", fmt, 3, errc{}, T{0.640625});
915 test_from_chars<T>("a0p5", fmt, 4, errc{}, T{5120});
916 test_from_chars<T>("a1.p5", fmt, 5, errc{}, T{5152});
917 test_from_chars<T>("a2.a3p5", fmt, 7, errc{}, T{5204.375});
918 test_from_chars<T>(".a4p5", fmt, 5, errc{}, T{20.5});
919 test_from_chars<T>("a0p+5", fmt, 5, errc{}, T{5120});
920 test_from_chars<T>("a0p-5", fmt, 5, errc{}, T{5});
921 test_from_chars<T>("ABCDEFP3", fmt, 8, errc{}, T{90075000});
922 test_from_chars<T>("-00cdrom", fmt, 5, errc{}, T{-205});
923 test_from_chars<T>(".00ef000", fmt, 8, errc{}, T{0.0036468505859375});
924 test_from_chars<T>("000", fmt, 3, errc{}, T{0});
925 test_from_chars<T>("0p9999", fmt, 6, errc{}, T{0});
926 test_from_chars<T>("0p-9999", fmt, 7, errc{}, T{0});
927 test_from_chars<T>("-000", fmt, 4, errc{}, T{-0.0});
928 test_from_chars<T>("-0p9999", fmt, 7, errc{}, T{-0.0});
929 test_from_chars<T>("-0p-9999", fmt, 8, errc{}, T{-0.0});
930 test_from_chars<T>("1p9999", fmt, 6, errc::result_out_of_range, inf);
931 test_from_chars<T>("-1p9999", fmt, 7, errc::result_out_of_range, -inf);
932 test_from_chars<T>("1p-9999", fmt, 7, errc::result_out_of_range, T{0});
933 test_from_chars<T>("-1p-9999", fmt, 8, errc::result_out_of_range, T{-0.0});
934 test_from_chars<T>("1" + string(2000, '0'), fmt, 2001, errc::result_out_of_range, inf);
935 test_from_chars<T>("-1" + string(2000, '0'), fmt, 2002, errc::result_out_of_range, -inf);
936 test_from_chars<T>("." + string(2000, '0') + "1", fmt, 2002, errc::result_out_of_range, T{0});
937 test_from_chars<T>("-." + string(2000, '0') + "1", fmt, 2003, errc::result_out_of_range, T{-0.0});
938 test_from_chars<T>("1" + string(300, '0'), fmt, 301, errc::result_out_of_range, inf);
939 test_from_chars<T>("-1" + string(300, '0'), fmt, 302, errc::result_out_of_range, -inf);
940 test_from_chars<T>("." + string(300, '0') + "1", fmt, 302, errc::result_out_of_range, T{0});
941 test_from_chars<T>("-." + string(300, '0') + "1", fmt, 303, errc::result_out_of_range, T{-0.0});
942 break;
943 }
944}
945#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
946
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_POINT
958 for (const auto& fmt : {chars_format::general, chars_format::scientific, chars_format::fixed, chars_format::hex}) {
959 test_floating_from_chars<float>(fmt);
960 test_floating_from_chars<double>(fmt);
961 }
962 // Test rounding.
963
964 // See float_from_chars_test_cases.hpp in this directory.
965 for (const auto& t : float_from_chars_test_cases) {
966 test_from_chars<float>(t.input, t.fmt, t.correct_idx, t.correct_ec, t.correct_value);
967 }
968
969 // See double_from_chars_test_cases.hpp in this directory.
970 for (const auto& t : double_from_chars_test_cases) {
971 test_from_chars<double>(t.input, t.fmt, t.correct_idx, t.correct_ec, t.correct_value);
972 }
973
974 {
975 // See LWG-2403. This number (exactly 0x1.fffffd00000004 in infinite precision) behaves differently
976 // when parsed as double and converted to float, versus being parsed as float directly.
977 const char* const lwg_2403 = "1.999999821186065729339276231257827021181583404541015625";
978 constexpr float correct_float = 0x1.fffffep0f;
979 constexpr double correct_double = 0x1.fffffdp0;
980 constexpr float twice_rounded_float = 0x1.fffffcp0f;
981
982 test_from_chars<float>(lwg_2403, chars_format::general, 56, errc{}, correct_float);
983 test_from_chars<double>(lwg_2403, chars_format::general, 56, errc{}, correct_double);
984 static_assert(static_cast<float>(correct_double) == twice_rounded_float);
985 }
986
987 // See floating_point_test_cases.hpp.
988 for (const auto& p : floating_point_test_cases_float) {
989 test_from_chars<float>(p.first, chars_format::general, strlen(p.first), errc{}, _Bit_cast<float>(p.second));
990 }
991
992 for (const auto& p : floating_point_test_cases_double) {
993 test_from_chars<double>(p.first, chars_format::general, strlen(p.first), errc{}, _Bit_cast<double>(p.second));
994 }
995#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT
996
997 // See float_to_chars_test_cases.hpp in this directory.
998 for (const auto& t : float_to_chars_test_cases) {
999 if (t.fmt == chars_format{}) {
1000 test_floating_to_chars(value: t.value, opt_fmt: nullopt, opt_precision: nullopt, correct: t.correct);
1001 } else {
1002 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: nullopt, correct: 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(value: t.value, opt_fmt: nullopt, opt_precision: nullopt, correct: t.correct);
1010 } else {
1011 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: nullopt, correct: 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(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1018 }
1019 for (const auto& t : float_fixed_precision_to_chars_test_cases) {
1020 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1021 }
1022 for (const auto& t : float_scientific_precision_to_chars_test_cases) {
1023 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1024 }
1025 for (const auto& t : float_general_precision_to_chars_test_cases) {
1026 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1027 }
1028 for (const auto& t : double_hex_precision_to_chars_test_cases) {
1029 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1030 }
1031 for (const auto& t : double_fixed_precision_to_chars_test_cases_1) {
1032 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1033 }
1034 for (const auto& t : double_fixed_precision_to_chars_test_cases_2) {
1035 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1036 }
1037 for (const auto& t : double_fixed_precision_to_chars_test_cases_3) {
1038 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1039 }
1040 for (const auto& t : double_fixed_precision_to_chars_test_cases_4) {
1041 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1042 }
1043 for (const auto& t : double_scientific_precision_to_chars_test_cases_1) {
1044 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1045 }
1046 for (const auto& t : double_scientific_precision_to_chars_test_cases_2) {
1047 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1048 }
1049 for (const auto& t : double_scientific_precision_to_chars_test_cases_3) {
1050 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1051 }
1052 for (const auto& t : double_scientific_precision_to_chars_test_cases_4) {
1053 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: t.correct);
1054 }
1055 for (const auto& t : double_general_precision_to_chars_test_cases) {
1056 test_floating_to_chars(value: t.value, opt_fmt: t.fmt, opt_precision: t.precision, correct: 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>(d: finish - start).count();
1073
1074 puts(s: "PASS");
1075 printf(format: "Randomized test cases: %zu\n", static_cast<std::size_t>(PrefixesToTest * Fractions));
1076 printf(format: "Total time: %lld ms\n", ms);
1077
1078 if (ms < 3'000) {
1079 puts(s: "That was fast. Consider tuning PrefixesToTest and FractionBits to test more cases.");
1080 } else if (ms > 30'000) {
1081 puts(s: "That was slow. Consider tuning PrefixesToTest and FractionBits to test fewer cases.");
1082 }
1083}
1084

source code of libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp