Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/src/include/to_chars_floating_point.h
Line
Count
Source (jump to first uncovered line)
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
// Copyright (c) Microsoft Corporation.
10
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11
12
// This implementation is dedicated to the memory of Mary and Thavatchai.
13
14
#ifndef _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
15
#define _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H
16
17
// Avoid formatting to keep the changes with the original code minimal.
18
// clang-format off
19
20
#include <__algorithm/find.h>
21
#include <__algorithm/find_if.h>
22
#include <__algorithm/lower_bound.h>
23
#include <__algorithm/min.h>
24
#include <__assert>
25
#include <__config>
26
#include <__iterator/access.h>
27
#include <__iterator/size.h>
28
#include <bit>
29
#include <cfloat>
30
#include <climits>
31
32
#include "include/ryu/ryu.h"
33
34
_LIBCPP_BEGIN_NAMESPACE_STD
35
36
namespace __itoa {
37
inline constexpr char _Charconv_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
38
    'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
39
static_assert(_VSTD::size(_Charconv_digits) == 36);
40
} // __itoa
41
42
// vvvvvvvvvv DERIVED FROM corecrt_internal_fltintrn.h vvvvvvvvvv
43
44
template <class _FloatingType>
45
struct _Floating_type_traits;
46
47
template <>
48
struct _Floating_type_traits<float> {
49
    static constexpr int32_t _Mantissa_bits = FLT_MANT_DIG;
50
    static constexpr int32_t _Exponent_bits = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
51
52
    static constexpr int32_t _Maximum_binary_exponent = FLT_MAX_EXP - 1;
53
    static constexpr int32_t _Minimum_binary_exponent = FLT_MIN_EXP - 1;
54
55
    static constexpr int32_t _Exponent_bias = 127;
56
57
    static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
58
    static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
59
60
    using _Uint_type = uint32_t;
61
62
    static constexpr uint32_t _Exponent_mask             = (1u << _Exponent_bits) - 1;
63
    static constexpr uint32_t _Normal_mantissa_mask      = (1u << _Mantissa_bits) - 1;
64
    static constexpr uint32_t _Denormal_mantissa_mask    = (1u << (_Mantissa_bits - 1)) - 1;
65
    static constexpr uint32_t _Special_nan_mantissa_mask = 1u << (_Mantissa_bits - 2);
66
    static constexpr uint32_t _Shifted_sign_mask         = 1u << _Sign_shift;
67
    static constexpr uint32_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
68
};
69
70
template <>
71
struct _Floating_type_traits<double> {
72
    static constexpr int32_t _Mantissa_bits = DBL_MANT_DIG;
73
    static constexpr int32_t _Exponent_bits = sizeof(double) * CHAR_BIT - DBL_MANT_DIG;
74
75
    static constexpr int32_t _Maximum_binary_exponent = DBL_MAX_EXP - 1;
76
    static constexpr int32_t _Minimum_binary_exponent = DBL_MIN_EXP - 1;
77
78
    static constexpr int32_t _Exponent_bias = 1023;
79
80
    static constexpr int32_t _Sign_shift     = _Exponent_bits + _Mantissa_bits - 1;
81
    static constexpr int32_t _Exponent_shift = _Mantissa_bits - 1;
82
83
    using _Uint_type = uint64_t;
84
85
    static constexpr uint64_t _Exponent_mask             = (1ULL << _Exponent_bits) - 1;
86
    static constexpr uint64_t _Normal_mantissa_mask      = (1ULL << _Mantissa_bits) - 1;
87
    static constexpr uint64_t _Denormal_mantissa_mask    = (1ULL << (_Mantissa_bits - 1)) - 1;
88
    static constexpr uint64_t _Special_nan_mantissa_mask = 1ULL << (_Mantissa_bits - 2);
89
    static constexpr uint64_t _Shifted_sign_mask         = 1ULL << _Sign_shift;
90
    static constexpr uint64_t _Shifted_exponent_mask     = _Exponent_mask << _Exponent_shift;
91
};
92
93
// ^^^^^^^^^^ DERIVED FROM corecrt_internal_fltintrn.h ^^^^^^^^^^
94
95
// FUNCTION to_chars (FLOATING-POINT TO STRING)
96
template <class _Floating>
97
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
98
to_chars_result _Floating_to_chars_hex_precision(
99
0
    char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
100
101
    // * Determine the effective _Precision.
102
    // * Later, we'll decrement _Precision when printing each hexit after the decimal point.
103
104
    // The hexits after the decimal point correspond to the explicitly stored fraction bits.
105
    // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, which is 6 hexits.
106
    // double explicitly stores 52 fraction bits. 52 / 4 == 13, which is 13 hexits.
107
0
    constexpr int _Full_precision         = _IsSame<_Floating, float>::value ? 6 : 13;
108
0
    constexpr int _Adjusted_explicit_bits = _Full_precision * 4;
109
110
0
    if (_Precision < 0) {
111
        // C11 7.21.6.1 "The fprintf function"/5: "A negative precision argument is taken as if the precision were
112
        // omitted." /8: "if the precision is missing and FLT_RADIX is a power of 2, then the precision is sufficient
113
        // for an exact representation of the value"
114
0
        _Precision = _Full_precision;
115
0
    }
116
117
    // * Extract the _Ieee_mantissa and _Ieee_exponent.
118
0
    using _Traits    = _Floating_type_traits<_Floating>;
119
0
    using _Uint_type = typename _Traits::_Uint_type;
120
121
0
    const _Uint_type _Uint_value    = _VSTD::bit_cast<_Uint_type>(_Value);
122
0
    const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
123
0
    const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
124
125
    // * Prepare the _Adjusted_mantissa. This is aligned to hexit boundaries,
126
    // * with the implicit bit restored (0 for zero values and subnormal values, 1 for normal values).
127
    // * Also calculate the _Unbiased_exponent. This unifies the processing of zero, subnormal, and normal values.
128
0
    _Uint_type _Adjusted_mantissa;
129
130
0
    if constexpr (_IsSame<_Floating, float>::value) {
131
0
        _Adjusted_mantissa = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
132
0
    } else {
133
0
        _Adjusted_mantissa = _Ieee_mantissa; // already aligned (52 is divisible by 4)
134
0
    }
135
136
0
    int32_t _Unbiased_exponent;
137
138
0
    if (_Ieee_exponent == 0) { // zero or subnormal
139
        // implicit bit is 0
140
141
0
        if (_Ieee_mantissa == 0) { // zero
142
            // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
143
0
            _Unbiased_exponent = 0;
144
0
        } else { // subnormal
145
0
            _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
146
0
        }
147
0
    } else { // normal
148
0
        _Adjusted_mantissa |= _Uint_type{1} << _Adjusted_explicit_bits; // implicit bit is 1
149
0
        _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
150
0
    }
151
152
    // _Unbiased_exponent is within [-126, 127] for float, [-1022, 1023] for double.
153
154
    // * Decompose _Unbiased_exponent into _Sign_character and _Absolute_exponent.
155
0
    char _Sign_character;
156
0
    uint32_t _Absolute_exponent;
157
158
0
    if (_Unbiased_exponent < 0) {
159
0
        _Sign_character    = '-';
160
0
        _Absolute_exponent = static_cast<uint32_t>(-_Unbiased_exponent);
161
0
    } else {
162
0
        _Sign_character    = '+';
163
0
        _Absolute_exponent = static_cast<uint32_t>(_Unbiased_exponent);
164
0
    }
165
166
    // _Absolute_exponent is within [0, 127] for float, [0, 1023] for double.
167
168
    // * Perform a single bounds check.
169
0
    {
170
0
        int32_t _Exponent_length;
171
172
0
        if (_Absolute_exponent < 10) {
173
0
            _Exponent_length = 1;
174
0
        } else if (_Absolute_exponent < 100) {
175
0
            _Exponent_length = 2;
176
0
        } else if constexpr (_IsSame<_Floating, float>::value) {
177
0
            _Exponent_length = 3;
178
0
        } else if (_Absolute_exponent < 1000) {
179
0
            _Exponent_length = 3;
180
0
        } else {
181
0
            _Exponent_length = 4;
182
0
        }
183
184
        // _Precision might be enormous; avoid integer overflow by testing it separately.
185
0
        ptrdiff_t _Buffer_size = _Last - _First;
186
187
0
        if (_Buffer_size < _Precision) {
188
0
            return {_Last, errc::value_too_large};
189
0
        }
190
191
0
        _Buffer_size -= _Precision;
192
193
0
        const int32_t _Length_excluding_precision = 1 // leading hexit
194
0
                                                    + static_cast<int32_t>(_Precision > 0) // possible decimal point
195
                                                    // excluding `+ _Precision`, hexits after decimal point
196
0
                                                    + 2 // "p+" or "p-"
197
0
                                                    + _Exponent_length; // exponent
198
199
0
        if (_Buffer_size < _Length_excluding_precision) {
200
0
            return {_Last, errc::value_too_large};
201
0
        }
202
0
    }
203
204
    // * Perform rounding when we've been asked to omit hexits.
205
0
    if (_Precision < _Full_precision) {
206
        // _Precision is within [0, 5] for float, [0, 12] for double.
207
208
        // _Dropped_bits is within [4, 24] for float, [4, 52] for double.
209
0
        const int _Dropped_bits = (_Full_precision - _Precision) * 4;
210
211
        // Perform rounding by adding an appropriately-shifted bit.
212
213
        // This can propagate carries all the way into the leading hexit. Examples:
214
        // "0.ff9" rounded to a precision of 2 is "1.00".
215
        // "1.ff9" rounded to a precision of 2 is "2.00".
216
217
        // Note that the leading hexit participates in the rounding decision. Examples:
218
        // "0.8" rounded to a precision of 0 is "0".
219
        // "1.8" rounded to a precision of 0 is "2".
220
221
        // Reference implementation with suboptimal codegen:
222
        // bool _Should_round_up(bool _Lsb_bit, bool _Round_bit, bool _Has_tail_bits) {
223
        //    // If there are no insignificant set bits, the value is exactly-representable and should not be rounded.
224
        //    //
225
        //    // If there are insignificant set bits, we need to round according to round_to_nearest.
226
        //    // We need to handle two cases: we round up if either [1] the value is slightly greater
227
        //    // than the midpoint between two exactly-representable values or [2] the value is exactly the midpoint
228
        //    // between two exactly-representable values and the greater of the two is even (this is "round-to-even").
229
        //    return _Round_bit && (_Has_tail_bits || _Lsb_bit);
230
        //}
231
        // const bool _Lsb_bit       = (_Adjusted_mantissa & (_Uint_type{1} << _Dropped_bits)) != 0;
232
        // const bool _Round_bit     = (_Adjusted_mantissa & (_Uint_type{1} << (_Dropped_bits - 1))) != 0;
233
        // const bool _Has_tail_bits = (_Adjusted_mantissa & ((_Uint_type{1} << (_Dropped_bits - 1)) - 1)) != 0;
234
        // const bool _Should_round = _Should_round_up(_Lsb_bit, _Round_bit, _Has_tail_bits);
235
        // _Adjusted_mantissa += _Uint_type{_Should_round} << _Dropped_bits;
236
237
        // Example for optimized implementation: Let _Dropped_bits be 8.
238
        //          Bit index: ...[8]76543210
239
        // _Adjusted_mantissa: ...[L]RTTTTTTT (not depicting known details, like hexit alignment)
240
        // By focusing on the bit at index _Dropped_bits, we can avoid unnecessary branching and shifting.
241
242
        // Bit index: ...[8]76543210
243
        //  _Lsb_bit: ...[L]RTTTTTTT
244
0
        const _Uint_type _Lsb_bit = _Adjusted_mantissa;
245
246
        //  Bit index: ...9[8]76543210
247
        // _Round_bit: ...L[R]TTTTTTT0
248
0
        const _Uint_type _Round_bit = _Adjusted_mantissa << 1;
249
250
        // We can detect (without branching) whether any of the trailing bits are set.
251
        // Due to _Should_round below, this computation will be used if and only if R is 1, so we can assume that here.
252
        //      Bit index: ...9[8]76543210
253
        //     _Round_bit: ...L[1]TTTTTTT0
254
        // _Has_tail_bits: ....[H]........
255
256
        // If all of the trailing bits T are 0, then `_Round_bit - 1` will produce 0 for H (due to R being 1).
257
        // If any of the trailing bits T are 1, then `_Round_bit - 1` will produce 1 for H (due to R being 1).
258
0
        const _Uint_type _Has_tail_bits = _Round_bit - 1;
259
260
        // Finally, we can use _Should_round_up() logic with bitwise-AND and bitwise-OR,
261
        // selecting just the bit at index _Dropped_bits. This is the appropriately-shifted bit that we want.
262
0
        const _Uint_type _Should_round = _Round_bit & (_Has_tail_bits | _Lsb_bit) & (_Uint_type{1} << _Dropped_bits);
263
264
        // This rounding technique is dedicated to the memory of Peppermint. =^..^=
265
0
        _Adjusted_mantissa += _Should_round;
266
0
    }
267
268
    // * Print the leading hexit, then mask it away.
269
0
    {
270
0
        const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Adjusted_explicit_bits);
271
0
        _LIBCPP_ASSERT(_Nibble < 3, "");
272
0
        const char _Leading_hexit = static_cast<char>('0' + _Nibble);
273
274
0
        *_First++ = _Leading_hexit;
275
276
0
        constexpr _Uint_type _Mask = (_Uint_type{1} << _Adjusted_explicit_bits) - 1;
277
0
        _Adjusted_mantissa &= _Mask;
278
0
    }
279
280
    // * Print the decimal point and trailing hexits.
281
282
    // C11 7.21.6.1 "The fprintf function"/8:
283
    // "if the precision is zero and the # flag is not specified, no decimal-point character appears."
284
0
    if (_Precision > 0) {
285
0
        *_First++ = '.';
286
287
0
        int32_t _Number_of_bits_remaining = _Adjusted_explicit_bits; // 24 for float, 52 for double
288
289
0
        for (;;) {
290
0
            _LIBCPP_ASSERT(_Number_of_bits_remaining >= 4, "");
291
0
            _LIBCPP_ASSERT(_Number_of_bits_remaining % 4 == 0, "");
292
0
            _Number_of_bits_remaining -= 4;
293
294
0
            const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
295
0
            _LIBCPP_ASSERT(_Nibble < 16, "");
296
0
            const char _Hexit = __itoa::_Charconv_digits[_Nibble];
297
298
0
            *_First++ = _Hexit;
299
300
            // _Precision is the number of hexits that still need to be printed.
301
0
            --_Precision;
302
0
            if (_Precision == 0) {
303
0
                break; // We're completely done with this phase.
304
0
            }
305
            // Otherwise, we need to keep printing hexits.
306
307
0
            if (_Number_of_bits_remaining == 0) {
308
                // We've finished printing _Adjusted_mantissa, so all remaining hexits are '0'.
309
0
                _VSTD::memset(_First, '0', static_cast<size_t>(_Precision));
310
0
                _First += _Precision;
311
0
                break;
312
0
            }
313
314
            // Mask away the hexit that we just printed, then keep looping.
315
            // (We skip this when breaking out of the loop above, because _Adjusted_mantissa isn't used later.)
316
0
            const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
317
0
            _Adjusted_mantissa &= _Mask;
318
0
        }
319
0
    }
320
321
    // * Print the exponent.
322
323
    // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
324
    // digits as necessary to represent the decimal exponent of 2."
325
326
    // Performance note: We should take advantage of the known ranges of possible exponents.
327
328
0
    *_First++ = 'p';
329
0
    *_First++ = _Sign_character;
330
331
    // We've already printed '-' if necessary, so uint32_t _Absolute_exponent avoids testing that again.
332
0
    return _VSTD::to_chars(_First, _Last, _Absolute_exponent);
333
0
}
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_hex_precision<float>(char*, char*, float, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_hex_precision<double>(char*, char*, double, int)
334
335
template <class _Floating>
336
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
337
to_chars_result _Floating_to_chars_hex_shortest(
338
0
    char* _First, char* const _Last, const _Floating _Value) noexcept {
339
340
    // This prints "1.728p+0" instead of "2.e5p-1".
341
    // This prints "0.000002p-126" instead of "1p-149" for float.
342
    // This prints "0.0000000000001p-1022" instead of "1p-1074" for double.
343
    // This prioritizes being consistent with printf's de facto behavior (and hex-precision's behavior)
344
    // over minimizing the number of characters printed.
345
346
0
    using _Traits    = _Floating_type_traits<_Floating>;
347
0
    using _Uint_type = typename _Traits::_Uint_type;
348
349
0
    const _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
350
351
0
    if (_Uint_value == 0) { // zero detected; write "0p+0" and return
352
        // C11 7.21.6.1 "The fprintf function"/8: "If the value is zero, the exponent is zero."
353
        // Special-casing zero is necessary because of the exponent.
354
0
        const char* const _Str = "0p+0";
355
0
        const size_t _Len      = 4;
356
357
0
        if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
358
0
            return {_Last, errc::value_too_large};
359
0
        }
360
361
0
        _VSTD::memcpy(_First, _Str, _Len);
362
363
0
        return {_First + _Len, errc{}};
364
0
    }
365
366
0
    const _Uint_type _Ieee_mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
367
0
    const int32_t _Ieee_exponent    = static_cast<int32_t>(_Uint_value >> _Traits::_Exponent_shift);
368
369
0
    char _Leading_hexit; // implicit bit
370
0
    int32_t _Unbiased_exponent;
371
372
0
    if (_Ieee_exponent == 0) { // subnormal
373
0
        _Leading_hexit     = '0';
374
0
        _Unbiased_exponent = 1 - _Traits::_Exponent_bias;
375
0
    } else { // normal
376
0
        _Leading_hexit     = '1';
377
0
        _Unbiased_exponent = _Ieee_exponent - _Traits::_Exponent_bias;
378
0
    }
379
380
    // Performance note: Consider avoiding per-character bounds checking when there's plenty of space.
381
382
0
    if (_First == _Last) {
383
0
        return {_Last, errc::value_too_large};
384
0
    }
385
386
0
    *_First++ = _Leading_hexit;
387
388
0
    if (_Ieee_mantissa == 0) {
389
        // The fraction bits are all 0. Trim them away, including the decimal point.
390
0
    } else {
391
0
        if (_First == _Last) {
392
0
            return {_Last, errc::value_too_large};
393
0
        }
394
395
0
        *_First++ = '.';
396
397
        // The hexits after the decimal point correspond to the explicitly stored fraction bits.
398
        // float explicitly stores 23 fraction bits. 23 / 4 == 5.75, so we'll print at most 6 hexits.
399
        // double explicitly stores 52 fraction bits. 52 / 4 == 13, so we'll print at most 13 hexits.
400
0
        _Uint_type _Adjusted_mantissa;
401
0
        int32_t _Number_of_bits_remaining;
402
403
0
        if constexpr (_IsSame<_Floating, float>::value) {
404
0
            _Adjusted_mantissa        = _Ieee_mantissa << 1; // align to hexit boundary (23 isn't divisible by 4)
405
0
            _Number_of_bits_remaining = 24; // 23 fraction bits + 1 alignment bit
406
0
        } else {
407
0
            _Adjusted_mantissa        = _Ieee_mantissa; // already aligned (52 is divisible by 4)
408
0
            _Number_of_bits_remaining = 52; // 52 fraction bits
409
0
        }
410
411
        // do-while: The condition _Adjusted_mantissa != 0 is initially true - we have nonzero fraction bits and we've
412
        // printed the decimal point. Each iteration, we print a hexit, mask it away, and keep looping if we still have
413
        // nonzero fraction bits. If there would be trailing '0' hexits, this trims them. If there wouldn't be trailing
414
        // '0' hexits, the same condition works (as we print the final hexit and mask it away); we don't need to test
415
        // _Number_of_bits_remaining.
416
0
        do {
417
0
            _LIBCPP_ASSERT(_Number_of_bits_remaining >= 4, "");
418
0
            _LIBCPP_ASSERT(_Number_of_bits_remaining % 4 == 0, "");
419
0
            _Number_of_bits_remaining -= 4;
420
421
0
            const uint32_t _Nibble = static_cast<uint32_t>(_Adjusted_mantissa >> _Number_of_bits_remaining);
422
0
            _LIBCPP_ASSERT(_Nibble < 16, "");
423
0
            const char _Hexit = __itoa::_Charconv_digits[_Nibble];
424
425
0
            if (_First == _Last) {
426
0
                return {_Last, errc::value_too_large};
427
0
            }
428
429
0
            *_First++ = _Hexit;
430
431
0
            const _Uint_type _Mask = (_Uint_type{1} << _Number_of_bits_remaining) - 1;
432
0
            _Adjusted_mantissa &= _Mask;
433
434
0
        } while (_Adjusted_mantissa != 0);
435
0
    }
436
437
    // C11 7.21.6.1 "The fprintf function"/8: "The exponent always contains at least one digit, and only as many more
438
    // digits as necessary to represent the decimal exponent of 2."
439
440
    // Performance note: We should take advantage of the known ranges of possible exponents.
441
442
    // float: _Unbiased_exponent is within [-126, 127].
443
    // double: _Unbiased_exponent is within [-1022, 1023].
444
445
0
    if (_Last - _First < 2) {
446
0
        return {_Last, errc::value_too_large};
447
0
    }
448
449
0
    *_First++ = 'p';
450
451
0
    if (_Unbiased_exponent < 0) {
452
0
        *_First++          = '-';
453
0
        _Unbiased_exponent = -_Unbiased_exponent;
454
0
    } else {
455
0
        *_First++ = '+';
456
0
    }
457
458
    // We've already printed '-' if necessary, so static_cast<uint32_t> avoids testing that again.
459
0
    return _VSTD::to_chars(_First, _Last, static_cast<uint32_t>(_Unbiased_exponent));
460
0
}
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_hex_shortest<float>(char*, char*, float)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_hex_shortest<double>(char*, char*, double)
461
462
// For general precision, we can use lookup tables to avoid performing trial formatting.
463
464
// For a simple example, imagine counting the number of digits D in an integer, and needing to know
465
// whether D is less than 3, equal to 3/4/5/6, or greater than 6. We could use a lookup table:
466
// D | Largest integer with D digits
467
// 2 |      99
468
// 3 |     999
469
// 4 |   9'999
470
// 5 |  99'999
471
// 6 | 999'999
472
// 7 | table end
473
// Looking up an integer in this table with lower_bound() will work:
474
// * Too-small integers, like 7, 70, and 99, will cause lower_bound() to return the D == 2 row. (If all we care
475
//   about is whether D is less than 3, then it's okay to smash the D == 1 and D == 2 cases together.)
476
// * Integers in [100, 999] will cause lower_bound() to return the D == 3 row, and so forth.
477
// * Too-large integers, like 1'000'000 and above, will cause lower_bound() to return the end of the table. If we
478
//   compute D from that index, this will be considered D == 7, which will activate any "greater than 6" logic.
479
480
// Floating-point is slightly more complicated.
481
482
// The ordinary lookup tables are for X within [-5, 38] for float, and [-5, 308] for double.
483
// (-5 absorbs too-negative exponents, outside the P > X >= -4 criterion. 38 and 308 are the maximum exponents.)
484
// Due to the P > X condition, we can use a subset of the table for X within [-5, P - 1], suitably clamped.
485
486
// When P is small, rounding can affect X. For example:
487
// For P == 1, the largest double with X == 0 is: 9.4999999999999982236431605997495353221893310546875
488
// For P == 2, the largest double with X == 0 is: 9.949999999999999289457264239899814128875732421875
489
// For P == 3, the largest double with X == 0 is: 9.9949999999999992184029906638897955417633056640625
490
491
// Exponent adjustment is a concern for P within [1, 7] for float, and [1, 15] for double (determined via
492
// brute force). While larger values of P still perform rounding, they can't trigger exponent adjustment.
493
// This is because only values with repeated '9' digits can undergo exponent adjustment during rounding,
494
// and floating-point granularity limits the number of consecutive '9' digits that can appear.
495
496
// So, we need special lookup tables for small values of P.
497
// These tables have varying lengths due to the P > X >= -4 criterion. For example:
498
// For P == 1, need table entries for X: -5, -4, -3, -2, -1, 0
499
// For P == 2, need table entries for X: -5, -4, -3, -2, -1, 0, 1
500
// For P == 3, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2
501
// For P == 4, need table entries for X: -5, -4, -3, -2, -1, 0, 1, 2, 3
502
503
// We can concatenate these tables for compact storage, using triangular numbers to access them.
504
// The table for P begins at index (P - 1) * (P + 10) / 2 with length P + 5.
505
506
// For both the ordinary and special lookup tables, after an index I is returned by lower_bound(), X is I - 5.
507
508
// We need to special-case the floating-point value 0.0, which is considered to have X == 0.
509
// Otherwise, the lookup tables would consider it to have a highly negative X.
510
511
// Finally, because we're working with positive floating-point values,
512
// representation comparisons behave identically to floating-point comparisons.
513
514
// The following code generated the lookup tables for the scientific exponent X. Don't remove this code.
515
#if 0
516
// cl /EHsc /nologo /W4 /MT /O2 /std:c++17 generate_tables.cpp && generate_tables
517
518
#include <algorithm>
519
#include <assert.h>
520
#include <charconv>
521
#include <cmath>
522
#include <limits>
523
#include <map>
524
#include <stdint.h>
525
#include <stdio.h>
526
#include <system_error>
527
#include <type_traits>
528
#include <vector>
529
using namespace std;
530
531
template <typename UInt, typename Pred>
532
[[nodiscard]] UInt uint_partition_point(UInt first, const UInt last, Pred pred) {
533
    // Find the beginning of the false partition in [first, last).
534
    // [first, last) is partitioned when all of the true values occur before all of the false values.
535
536
    static_assert(is_unsigned_v<UInt>);
537
    assert(first <= last);
538
539
    for (UInt n = last - first; n > 0;) {
540
        const UInt n2  = n / 2;
541
        const UInt mid = first + n2;
542
543
        if (pred(mid)) {
544
            first = mid + 1;
545
            n     = n - n2 - 1;
546
        } else {
547
            n = n2;
548
        }
549
    }
550
551
    return first;
552
}
553
554
template <typename Floating>
555
[[nodiscard]] int scientific_exponent_X(const int P, const Floating flt) {
556
    char buf[400]; // more than enough
557
558
    // C11 7.21.6.1 "The fprintf function"/8 performs trial formatting with scientific precision P - 1.
559
    const auto to_result = to_chars(buf, end(buf), flt, chars_format::scientific, P - 1);
560
    assert(to_result.ec == errc{});
561
562
    const char* exp_ptr = find(buf, to_result.ptr, 'e');
563
    assert(exp_ptr != to_result.ptr);
564
565
    ++exp_ptr; // advance past 'e'
566
567
    if (*exp_ptr == '+') {
568
        ++exp_ptr; // advance past '+' which from_chars() won't parse
569
    }
570
571
    int X;
572
    const auto from_result = from_chars(exp_ptr, to_result.ptr, X);
573
    assert(from_result.ec == errc{});
574
    return X;
575
}
576
577
template <typename UInt>
578
void print_table(const vector<UInt>& v, const char* const name) {
579
    constexpr const char* UIntName = _IsSame<UInt, uint32_t>::value ? "uint32_t" : "uint64_t";
580
581
    printf("static constexpr %s %s[%zu] = {\n", UIntName, name, v.size());
582
583
    for (const auto& val : v) {
584
        if constexpr (_IsSame<UInt, uint32_t>::value) {
585
            printf("0x%08Xu,\n", val);
586
        } else {
587
            printf("0x%016llXu,\n", val);
588
        }
589
    }
590
591
    printf("};\n");
592
}
593
594
enum class Mode { Tables, Tests };
595
596
template <typename Floating>
597
void generate_tables(const Mode mode) {
598
    using Limits = numeric_limits<Floating>;
599
    using UInt   = conditional_t<_IsSame<Floating, float>::value, uint32_t, uint64_t>;
600
601
    map<int, map<int, UInt>> P_X_LargestValWithX;
602
603
    constexpr int MaxP = Limits::max_exponent10 + 1; // MaxP performs no rounding during trial formatting
604
605
    for (int P = 1; P <= MaxP; ++P) {
606
        for (int X = -5; X < P; ++X) {
607
            constexpr Floating first = static_cast<Floating>(9e-5); // well below 9.5e-5, otherwise arbitrary
608
            constexpr Floating last  = Limits::infinity(); // one bit above Limits::max()
609
610
            const UInt val_beyond_X = uint_partition_point(reinterpret_cast<const UInt&>(first),
611
                reinterpret_cast<const UInt&>(last),
612
                [P, X](const UInt u) { return scientific_exponent_X(P, reinterpret_cast<const Floating&>(u)) <= X; });
613
614
            P_X_LargestValWithX[P][X] = val_beyond_X - 1;
615
        }
616
    }
617
618
    constexpr const char* FloatingName = _IsSame<Floating, float>::value ? "float" : "double";
619
620
    constexpr int MaxSpecialP = _IsSame<Floating, float>::value ? 7 : 15; // MaxSpecialP is affected by exponent adjustment
621
622
    if (mode == Mode::Tables) {
623
        printf("template <>\n");
624
        printf("struct _General_precision_tables<%s> {\n", FloatingName);
625
626
        printf("static constexpr int _Max_special_P = %d;\n", MaxSpecialP);
627
628
        vector<UInt> special;
629
630
        for (int P = 1; P <= MaxSpecialP; ++P) {
631
            for (int X = -5; X < P; ++X) {
632
                const UInt val = P_X_LargestValWithX[P][X];
633
                special.push_back(val);
634
            }
635
        }
636
637
        print_table(special, "_Special_X_table");
638
639
        for (int P = MaxSpecialP + 1; P < MaxP; ++P) {
640
            for (int X = -5; X < P; ++X) {
641
                const UInt val = P_X_LargestValWithX[P][X];
642
                assert(val == P_X_LargestValWithX[MaxP][X]);
643
            }
644
        }
645
646
        printf("static constexpr int _Max_P = %d;\n", MaxP);
647
648
        vector<UInt> ordinary;
649
650
        for (int X = -5; X < MaxP; ++X) {
651
            const UInt val = P_X_LargestValWithX[MaxP][X];
652
            ordinary.push_back(val);
653
        }
654
655
        print_table(ordinary, "_Ordinary_X_table");
656
657
        printf("};\n");
658
    } else {
659
        printf("==========\n");
660
        printf("Test cases for %s:\n", FloatingName);
661
662
        constexpr int Hexits         = _IsSame<Floating, float>::value ? 6 : 13;
663
        constexpr const char* Suffix = _IsSame<Floating, float>::value ? "f" : "";
664
665
        for (int P = 1; P <= MaxP; ++P) {
666
            for (int X = -5; X < P; ++X) {
667
                if (P <= MaxSpecialP || P == 25 || P == MaxP || X == P - 1) {
668
                    const UInt val1   = P_X_LargestValWithX[P][X];
669
                    const Floating f1 = reinterpret_cast<const Floating&>(val1);
670
                    const UInt val2   = val1 + 1;
671
                    const Floating f2 = reinterpret_cast<const Floating&>(val2);
672
673
                    printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f1, Suffix, P, P, f1);
674
                    if (isfinite(f2)) {
675
                        printf("{%.*a%s, chars_format::general, %d, \"%.*g\"},\n", Hexits, f2, Suffix, P, P, f2);
676
                    }
677
                }
678
            }
679
        }
680
    }
681
}
682
683
int main() {
684
    printf("template <class _Floating>\n");
685
    printf("struct _General_precision_tables;\n");
686
    generate_tables<float>(Mode::Tables);
687
    generate_tables<double>(Mode::Tables);
688
    generate_tables<float>(Mode::Tests);
689
    generate_tables<double>(Mode::Tests);
690
}
691
#endif // 0
692
693
template <class _Floating>
694
struct _General_precision_tables;
695
696
template <>
697
struct _General_precision_tables<float> {
698
    static constexpr int _Max_special_P = 7;
699
700
    static constexpr uint32_t _Special_X_table[63] = {0x38C73ABCu, 0x3A79096Bu, 0x3C1BA5E3u, 0x3DC28F5Cu, 0x3F733333u,
701
        0x4117FFFFu, 0x38D0AAA7u, 0x3A826AA8u, 0x3C230553u, 0x3DCBC6A7u, 0x3F7EB851u, 0x411F3333u, 0x42C6FFFFu,
702
        0x38D19C3Fu, 0x3A8301A7u, 0x3C23C211u, 0x3DCCB295u, 0x3F7FDF3Bu, 0x411FEB85u, 0x42C7E666u, 0x4479DFFFu,
703
        0x38D1B468u, 0x3A8310C1u, 0x3C23D4F1u, 0x3DCCCA2Du, 0x3F7FFCB9u, 0x411FFDF3u, 0x42C7FD70u, 0x4479FCCCu,
704
        0x461C3DFFu, 0x38D1B6D2u, 0x3A831243u, 0x3C23D6D4u, 0x3DCCCC89u, 0x3F7FFFACu, 0x411FFFCBu, 0x42C7FFBEu,
705
        0x4479FFAEu, 0x461C3FCCu, 0x47C34FBFu, 0x38D1B710u, 0x3A83126Au, 0x3C23D704u, 0x3DCCCCC6u, 0x3F7FFFF7u,
706
        0x411FFFFAu, 0x42C7FFF9u, 0x4479FFF7u, 0x461C3FFAu, 0x47C34FF9u, 0x497423F7u, 0x38D1B716u, 0x3A83126Eu,
707
        0x3C23D709u, 0x3DCCCCCCu, 0x3F7FFFFFu, 0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu,
708
        0x497423FFu, 0x4B18967Fu};
709
710
    static constexpr int _Max_P = 39;
711
712
    static constexpr uint32_t _Ordinary_X_table[44] = {0x38D1B717u, 0x3A83126Eu, 0x3C23D70Au, 0x3DCCCCCCu, 0x3F7FFFFFu,
713
        0x411FFFFFu, 0x42C7FFFFu, 0x4479FFFFu, 0x461C3FFFu, 0x47C34FFFu, 0x497423FFu, 0x4B18967Fu, 0x4CBEBC1Fu,
714
        0x4E6E6B27u, 0x501502F8u, 0x51BA43B7u, 0x5368D4A5u, 0x551184E7u, 0x56B5E620u, 0x58635FA9u, 0x5A0E1BC9u,
715
        0x5BB1A2BCu, 0x5D5E0B6Bu, 0x5F0AC723u, 0x60AD78EBu, 0x6258D726u, 0x64078678u, 0x65A96816u, 0x6753C21Bu,
716
        0x69045951u, 0x6AA56FA5u, 0x6C4ECB8Fu, 0x6E013F39u, 0x6FA18F07u, 0x7149F2C9u, 0x72FC6F7Cu, 0x749DC5ADu,
717
        0x76453719u, 0x77F684DFu, 0x799A130Bu, 0x7B4097CEu, 0x7CF0BDC2u, 0x7E967699u, 0x7F7FFFFFu};
718
};
719
720
template <>
721
struct _General_precision_tables<double> {
722
    static constexpr int _Max_special_P = 15;
723
724
    static constexpr uint64_t _Special_X_table[195] = {0x3F18E757928E0C9Du, 0x3F4F212D77318FC5u, 0x3F8374BC6A7EF9DBu,
725
        0x3FB851EB851EB851u, 0x3FEE666666666666u, 0x4022FFFFFFFFFFFFu, 0x3F1A1554FBDAD751u, 0x3F504D551D68C692u,
726
        0x3F8460AA64C2F837u, 0x3FB978D4FDF3B645u, 0x3FEFD70A3D70A3D7u, 0x4023E66666666666u, 0x4058DFFFFFFFFFFFu,
727
        0x3F1A3387ECC8EB96u, 0x3F506034F3FD933Eu, 0x3F84784230FCF80Du, 0x3FB99652BD3C3611u, 0x3FEFFBE76C8B4395u,
728
        0x4023FD70A3D70A3Du, 0x4058FCCCCCCCCCCCu, 0x408F3BFFFFFFFFFFu, 0x3F1A368D04E0BA6Au, 0x3F506218230C7482u,
729
        0x3F847A9E2BCF91A3u, 0x3FB99945B6C3760Bu, 0x3FEFFF972474538Eu, 0x4023FFBE76C8B439u, 0x4058FFAE147AE147u,
730
        0x408F3F9999999999u, 0x40C387BFFFFFFFFFu, 0x3F1A36DA54164F19u, 0x3F506248748DF16Fu, 0x3F847ADA91B16DCBu,
731
        0x3FB99991361DC93Eu, 0x3FEFFFF583A53B8Eu, 0x4023FFF972474538u, 0x4058FFF7CED91687u, 0x408F3FF5C28F5C28u,
732
        0x40C387F999999999u, 0x40F869F7FFFFFFFFu, 0x3F1A36E20F35445Du, 0x3F50624D49814ABAu, 0x3F847AE09BE19D69u,
733
        0x3FB99998C2DA04C3u, 0x3FEFFFFEF39085F4u, 0x4023FFFF583A53B8u, 0x4058FFFF2E48E8A7u, 0x408F3FFEF9DB22D0u,
734
        0x40C387FF5C28F5C2u, 0x40F869FF33333333u, 0x412E847EFFFFFFFFu, 0x3F1A36E2D51EC34Bu, 0x3F50624DC5333A0Eu,
735
        0x3F847AE136800892u, 0x3FB9999984200AB7u, 0x3FEFFFFFE5280D65u, 0x4023FFFFEF39085Fu, 0x4058FFFFEB074A77u,
736
        0x408F3FFFE5C91D14u, 0x40C387FFEF9DB22Du, 0x40F869FFEB851EB8u, 0x412E847FE6666666u, 0x416312CFEFFFFFFFu,
737
        0x3F1A36E2E8E94FFCu, 0x3F50624DD191D1FDu, 0x3F847AE145F6467Du, 0x3FB999999773D81Cu, 0x3FEFFFFFFD50CE23u,
738
        0x4023FFFFFE5280D6u, 0x4058FFFFFDE7210Bu, 0x408F3FFFFD60E94Eu, 0x40C387FFFE5C91D1u, 0x40F869FFFDF3B645u,
739
        0x412E847FFD70A3D7u, 0x416312CFFE666666u, 0x4197D783FDFFFFFFu, 0x3F1A36E2EAE3F7A7u, 0x3F50624DD2CE7AC8u,
740
        0x3F847AE14782197Bu, 0x3FB9999999629FD9u, 0x3FEFFFFFFFBB47D0u, 0x4023FFFFFFD50CE2u, 0x4058FFFFFFCA501Au,
741
        0x408F3FFFFFBCE421u, 0x40C387FFFFD60E94u, 0x40F869FFFFCB923Au, 0x412E847FFFBE76C8u, 0x416312CFFFD70A3Du,
742
        0x4197D783FFCCCCCCu, 0x41CDCD64FFBFFFFFu, 0x3F1A36E2EB16A205u, 0x3F50624DD2EE2543u, 0x3F847AE147A9AE94u,
743
        0x3FB9999999941A39u, 0x3FEFFFFFFFF920C8u, 0x4023FFFFFFFBB47Du, 0x4058FFFFFFFAA19Cu, 0x408F3FFFFFF94A03u,
744
        0x40C387FFFFFBCE42u, 0x40F869FFFFFAC1D2u, 0x412E847FFFF97247u, 0x416312CFFFFBE76Cu, 0x4197D783FFFAE147u,
745
        0x41CDCD64FFF99999u, 0x4202A05F1FFBFFFFu, 0x3F1A36E2EB1BB30Fu, 0x3F50624DD2F14FE9u, 0x3F847AE147ADA3E3u,
746
        0x3FB9999999990CDCu, 0x3FEFFFFFFFFF5014u, 0x4023FFFFFFFF920Cu, 0x4058FFFFFFFF768Fu, 0x408F3FFFFFFF5433u,
747
        0x40C387FFFFFF94A0u, 0x40F869FFFFFF79C8u, 0x412E847FFFFF583Au, 0x416312CFFFFF9724u, 0x4197D783FFFF7CEDu,
748
        0x41CDCD64FFFF5C28u, 0x4202A05F1FFF9999u, 0x42374876E7FF7FFFu, 0x3F1A36E2EB1C34C3u, 0x3F50624DD2F1A0FAu,
749
        0x3F847AE147AE0938u, 0x3FB9999999998B86u, 0x3FEFFFFFFFFFEE68u, 0x4023FFFFFFFFF501u, 0x4058FFFFFFFFF241u,
750
        0x408F3FFFFFFFEED1u, 0x40C387FFFFFFF543u, 0x40F869FFFFFFF294u, 0x412E847FFFFFEF39u, 0x416312CFFFFFF583u,
751
        0x4197D783FFFFF2E4u, 0x41CDCD64FFFFEF9Du, 0x4202A05F1FFFF5C2u, 0x42374876E7FFF333u, 0x426D1A94A1FFEFFFu,
752
        0x3F1A36E2EB1C41BBu, 0x3F50624DD2F1A915u, 0x3F847AE147AE135Au, 0x3FB9999999999831u, 0x3FEFFFFFFFFFFE3Du,
753
        0x4023FFFFFFFFFEE6u, 0x4058FFFFFFFFFEA0u, 0x408F3FFFFFFFFE48u, 0x40C387FFFFFFFEEDu, 0x40F869FFFFFFFEA8u,
754
        0x412E847FFFFFFE52u, 0x416312CFFFFFFEF3u, 0x4197D783FFFFFEB0u, 0x41CDCD64FFFFFE5Cu, 0x4202A05F1FFFFEF9u,
755
        0x42374876E7FFFEB8u, 0x426D1A94A1FFFE66u, 0x42A2309CE53FFEFFu, 0x3F1A36E2EB1C4307u, 0x3F50624DD2F1A9E4u,
756
        0x3F847AE147AE145Eu, 0x3FB9999999999975u, 0x3FEFFFFFFFFFFFD2u, 0x4023FFFFFFFFFFE3u, 0x4058FFFFFFFFFFDCu,
757
        0x408F3FFFFFFFFFD4u, 0x40C387FFFFFFFFE4u, 0x40F869FFFFFFFFDDu, 0x412E847FFFFFFFD5u, 0x416312CFFFFFFFE5u,
758
        0x4197D783FFFFFFDEu, 0x41CDCD64FFFFFFD6u, 0x4202A05F1FFFFFE5u, 0x42374876E7FFFFDFu, 0x426D1A94A1FFFFD7u,
759
        0x42A2309CE53FFFE6u, 0x42D6BCC41E8FFFDFu, 0x3F1A36E2EB1C4328u, 0x3F50624DD2F1A9F9u, 0x3F847AE147AE1477u,
760
        0x3FB9999999999995u, 0x3FEFFFFFFFFFFFFBu, 0x4023FFFFFFFFFFFDu, 0x4058FFFFFFFFFFFCu, 0x408F3FFFFFFFFFFBu,
761
        0x40C387FFFFFFFFFDu, 0x40F869FFFFFFFFFCu, 0x412E847FFFFFFFFBu, 0x416312CFFFFFFFFDu, 0x4197D783FFFFFFFCu,
762
        0x41CDCD64FFFFFFFBu, 0x4202A05F1FFFFFFDu, 0x42374876E7FFFFFCu, 0x426D1A94A1FFFFFBu, 0x42A2309CE53FFFFDu,
763
        0x42D6BCC41E8FFFFCu, 0x430C6BF52633FFFBu};
764
765
    static constexpr int _Max_P = 309;
766
767
    static constexpr uint64_t _Ordinary_X_table[314] = {0x3F1A36E2EB1C432Cu, 0x3F50624DD2F1A9FBu, 0x3F847AE147AE147Au,
768
        0x3FB9999999999999u, 0x3FEFFFFFFFFFFFFFu, 0x4023FFFFFFFFFFFFu, 0x4058FFFFFFFFFFFFu, 0x408F3FFFFFFFFFFFu,
769
        0x40C387FFFFFFFFFFu, 0x40F869FFFFFFFFFFu, 0x412E847FFFFFFFFFu, 0x416312CFFFFFFFFFu, 0x4197D783FFFFFFFFu,
770
        0x41CDCD64FFFFFFFFu, 0x4202A05F1FFFFFFFu, 0x42374876E7FFFFFFu, 0x426D1A94A1FFFFFFu, 0x42A2309CE53FFFFFu,
771
        0x42D6BCC41E8FFFFFu, 0x430C6BF52633FFFFu, 0x4341C37937E07FFFu, 0x4376345785D89FFFu, 0x43ABC16D674EC7FFu,
772
        0x43E158E460913CFFu, 0x4415AF1D78B58C3Fu, 0x444B1AE4D6E2EF4Fu, 0x4480F0CF064DD591u, 0x44B52D02C7E14AF6u,
773
        0x44EA784379D99DB4u, 0x45208B2A2C280290u, 0x4554ADF4B7320334u, 0x4589D971E4FE8401u, 0x45C027E72F1F1281u,
774
        0x45F431E0FAE6D721u, 0x46293E5939A08CE9u, 0x465F8DEF8808B024u, 0x4693B8B5B5056E16u, 0x46C8A6E32246C99Cu,
775
        0x46FED09BEAD87C03u, 0x4733426172C74D82u, 0x476812F9CF7920E2u, 0x479E17B84357691Bu, 0x47D2CED32A16A1B1u,
776
        0x48078287F49C4A1Du, 0x483D6329F1C35CA4u, 0x48725DFA371A19E6u, 0x48A6F578C4E0A060u, 0x48DCB2D6F618C878u,
777
        0x4911EFC659CF7D4Bu, 0x49466BB7F0435C9Eu, 0x497C06A5EC5433C6u, 0x49B18427B3B4A05Bu, 0x49E5E531A0A1C872u,
778
        0x4A1B5E7E08CA3A8Fu, 0x4A511B0EC57E6499u, 0x4A8561D276DDFDC0u, 0x4ABABA4714957D30u, 0x4AF0B46C6CDD6E3Eu,
779
        0x4B24E1878814C9CDu, 0x4B5A19E96A19FC40u, 0x4B905031E2503DA8u, 0x4BC4643E5AE44D12u, 0x4BF97D4DF19D6057u,
780
        0x4C2FDCA16E04B86Du, 0x4C63E9E4E4C2F344u, 0x4C98E45E1DF3B015u, 0x4CCF1D75A5709C1Au, 0x4D03726987666190u,
781
        0x4D384F03E93FF9F4u, 0x4D6E62C4E38FF872u, 0x4DA2FDBB0E39FB47u, 0x4DD7BD29D1C87A19u, 0x4E0DAC74463A989Fu,
782
        0x4E428BC8ABE49F63u, 0x4E772EBAD6DDC73Cu, 0x4EACFA698C95390Bu, 0x4EE21C81F7DD43A7u, 0x4F16A3A275D49491u,
783
        0x4F4C4C8B1349B9B5u, 0x4F81AFD6EC0E1411u, 0x4FB61BCCA7119915u, 0x4FEBA2BFD0D5FF5Bu, 0x502145B7E285BF98u,
784
        0x50559725DB272F7Fu, 0x508AFCEF51F0FB5Eu, 0x50C0DE1593369D1Bu, 0x50F5159AF8044462u, 0x512A5B01B605557Au,
785
        0x516078E111C3556Cu, 0x5194971956342AC7u, 0x51C9BCDFABC13579u, 0x5200160BCB58C16Cu, 0x52341B8EBE2EF1C7u,
786
        0x526922726DBAAE39u, 0x529F6B0F092959C7u, 0x52D3A2E965B9D81Cu, 0x53088BA3BF284E23u, 0x533EAE8CAEF261ACu,
787
        0x53732D17ED577D0Bu, 0x53A7F85DE8AD5C4Eu, 0x53DDF67562D8B362u, 0x5412BA095DC7701Du, 0x5447688BB5394C25u,
788
        0x547D42AEA2879F2Eu, 0x54B249AD2594C37Cu, 0x54E6DC186EF9F45Cu, 0x551C931E8AB87173u, 0x5551DBF316B346E7u,
789
        0x558652EFDC6018A1u, 0x55BBE7ABD3781ECAu, 0x55F170CB642B133Eu, 0x5625CCFE3D35D80Eu, 0x565B403DCC834E11u,
790
        0x569108269FD210CBu, 0x56C54A3047C694FDu, 0x56FA9CBC59B83A3Du, 0x5730A1F5B8132466u, 0x5764CA732617ED7Fu,
791
        0x5799FD0FEF9DE8DFu, 0x57D03E29F5C2B18Bu, 0x58044DB473335DEEu, 0x583961219000356Au, 0x586FB969F40042C5u,
792
        0x58A3D3E2388029BBu, 0x58D8C8DAC6A0342Au, 0x590EFB1178484134u, 0x59435CEAEB2D28C0u, 0x59783425A5F872F1u,
793
        0x59AE412F0F768FADu, 0x59E2E8BD69AA19CCu, 0x5A17A2ECC414A03Fu, 0x5A4D8BA7F519C84Fu, 0x5A827748F9301D31u,
794
        0x5AB7151B377C247Eu, 0x5AECDA62055B2D9Du, 0x5B22087D4358FC82u, 0x5B568A9C942F3BA3u, 0x5B8C2D43B93B0A8Bu,
795
        0x5BC19C4A53C4E697u, 0x5BF6035CE8B6203Du, 0x5C2B843422E3A84Cu, 0x5C6132A095CE492Fu, 0x5C957F48BB41DB7Bu,
796
        0x5CCADF1AEA12525Au, 0x5D00CB70D24B7378u, 0x5D34FE4D06DE5056u, 0x5D6A3DE04895E46Cu, 0x5DA066AC2D5DAEC3u,
797
        0x5DD4805738B51A74u, 0x5E09A06D06E26112u, 0x5E400444244D7CABu, 0x5E7405552D60DBD6u, 0x5EA906AA78B912CBu,
798
        0x5EDF485516E7577Eu, 0x5F138D352E5096AFu, 0x5F48708279E4BC5Au, 0x5F7E8CA3185DEB71u, 0x5FB317E5EF3AB327u,
799
        0x5FE7DDDF6B095FF0u, 0x601DD55745CBB7ECu, 0x6052A5568B9F52F4u, 0x60874EAC2E8727B1u, 0x60BD22573A28F19Du,
800
        0x60F2357684599702u, 0x6126C2D4256FFCC2u, 0x615C73892ECBFBF3u, 0x6191C835BD3F7D78u, 0x61C63A432C8F5CD6u,
801
        0x61FBC8D3F7B3340Bu, 0x62315D847AD00087u, 0x6265B4E5998400A9u, 0x629B221EFFE500D3u, 0x62D0F5535FEF2084u,
802
        0x630532A837EAE8A5u, 0x633A7F5245E5A2CEu, 0x63708F936BAF85C1u, 0x63A4B378469B6731u, 0x63D9E056584240FDu,
803
        0x64102C35F729689Eu, 0x6444374374F3C2C6u, 0x647945145230B377u, 0x64AF965966BCE055u, 0x64E3BDF7E0360C35u,
804
        0x6518AD75D8438F43u, 0x654ED8D34E547313u, 0x6583478410F4C7ECu, 0x65B819651531F9E7u, 0x65EE1FBE5A7E7861u,
805
        0x6622D3D6F88F0B3Cu, 0x665788CCB6B2CE0Cu, 0x668D6AFFE45F818Fu, 0x66C262DFEEBBB0F9u, 0x66F6FB97EA6A9D37u,
806
        0x672CBA7DE5054485u, 0x6761F48EAF234AD3u, 0x679671B25AEC1D88u, 0x67CC0E1EF1A724EAu, 0x680188D357087712u,
807
        0x6835EB082CCA94D7u, 0x686B65CA37FD3A0Du, 0x68A11F9E62FE4448u, 0x68D56785FBBDD55Au, 0x690AC1677AAD4AB0u,
808
        0x6940B8E0ACAC4EAEu, 0x6974E718D7D7625Au, 0x69AA20DF0DCD3AF0u, 0x69E0548B68A044D6u, 0x6A1469AE42C8560Cu,
809
        0x6A498419D37A6B8Fu, 0x6A7FE52048590672u, 0x6AB3EF342D37A407u, 0x6AE8EB0138858D09u, 0x6B1F25C186A6F04Cu,
810
        0x6B537798F428562Fu, 0x6B88557F31326BBBu, 0x6BBE6ADEFD7F06AAu, 0x6BF302CB5E6F642Au, 0x6C27C37E360B3D35u,
811
        0x6C5DB45DC38E0C82u, 0x6C9290BA9A38C7D1u, 0x6CC734E940C6F9C5u, 0x6CFD022390F8B837u, 0x6D3221563A9B7322u,
812
        0x6D66A9ABC9424FEBu, 0x6D9C5416BB92E3E6u, 0x6DD1B48E353BCE6Fu, 0x6E0621B1C28AC20Bu, 0x6E3BAA1E332D728Eu,
813
        0x6E714A52DFFC6799u, 0x6EA59CE797FB817Fu, 0x6EDB04217DFA61DFu, 0x6F10E294EEBC7D2Bu, 0x6F451B3A2A6B9C76u,
814
        0x6F7A6208B5068394u, 0x6FB07D457124123Cu, 0x6FE49C96CD6D16CBu, 0x7019C3BC80C85C7Eu, 0x70501A55D07D39CFu,
815
        0x708420EB449C8842u, 0x70B9292615C3AA53u, 0x70EF736F9B3494E8u, 0x7123A825C100DD11u, 0x7158922F31411455u,
816
        0x718EB6BAFD91596Bu, 0x71C33234DE7AD7E2u, 0x71F7FEC216198DDBu, 0x722DFE729B9FF152u, 0x7262BF07A143F6D3u,
817
        0x72976EC98994F488u, 0x72CD4A7BEBFA31AAu, 0x73024E8D737C5F0Au, 0x7336E230D05B76CDu, 0x736C9ABD04725480u,
818
        0x73A1E0B622C774D0u, 0x73D658E3AB795204u, 0x740BEF1C9657A685u, 0x74417571DDF6C813u, 0x7475D2CE55747A18u,
819
        0x74AB4781EAD1989Eu, 0x74E10CB132C2FF63u, 0x75154FDD7F73BF3Bu, 0x754AA3D4DF50AF0Au, 0x7580A6650B926D66u,
820
        0x75B4CFFE4E7708C0u, 0x75EA03FDE214CAF0u, 0x7620427EAD4CFED6u, 0x7654531E58A03E8Bu, 0x768967E5EEC84E2Eu,
821
        0x76BFC1DF6A7A61BAu, 0x76F3D92BA28C7D14u, 0x7728CF768B2F9C59u, 0x775F03542DFB8370u, 0x779362149CBD3226u,
822
        0x77C83A99C3EC7EAFu, 0x77FE494034E79E5Bu, 0x7832EDC82110C2F9u, 0x7867A93A2954F3B7u, 0x789D9388B3AA30A5u,
823
        0x78D27C35704A5E67u, 0x79071B42CC5CF601u, 0x793CE2137F743381u, 0x79720D4C2FA8A030u, 0x79A6909F3B92C83Du,
824
        0x79DC34C70A777A4Cu, 0x7A11A0FC668AAC6Fu, 0x7A46093B802D578Bu, 0x7A7B8B8A6038AD6Eu, 0x7AB137367C236C65u,
825
        0x7AE585041B2C477Eu, 0x7B1AE64521F7595Eu, 0x7B50CFEB353A97DAu, 0x7B8503E602893DD1u, 0x7BBA44DF832B8D45u,
826
        0x7BF06B0BB1FB384Bu, 0x7C2485CE9E7A065Eu, 0x7C59A742461887F6u, 0x7C9008896BCF54F9u, 0x7CC40AABC6C32A38u,
827
        0x7CF90D56B873F4C6u, 0x7D2F50AC6690F1F8u, 0x7D63926BC01A973Bu, 0x7D987706B0213D09u, 0x7DCE94C85C298C4Cu,
828
        0x7E031CFD3999F7AFu, 0x7E37E43C8800759Bu, 0x7E6DDD4BAA009302u, 0x7EA2AA4F4A405BE1u, 0x7ED754E31CD072D9u,
829
        0x7F0D2A1BE4048F90u, 0x7F423A516E82D9BAu, 0x7F76C8E5CA239028u, 0x7FAC7B1F3CAC7433u, 0x7FE1CCF385EBC89Fu,
830
        0x7FEFFFFFFFFFFFFFu};
831
};
832
833
template <class _Floating>
834
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
835
to_chars_result _Floating_to_chars_general_precision(
836
0
    char* _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
837
838
0
    using _Traits    = _Floating_type_traits<_Floating>;
839
0
    using _Uint_type = typename _Traits::_Uint_type;
840
841
0
    const _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
842
843
0
    if (_Uint_value == 0) { // zero detected; write "0" and return; _Precision is irrelevant due to zero-trimming
844
0
        if (_First == _Last) {
845
0
            return {_Last, errc::value_too_large};
846
0
        }
847
848
0
        *_First++ = '0';
849
850
0
        return {_First, errc{}};
851
0
    }
852
853
    // C11 7.21.6.1 "The fprintf function"/5:
854
    // "A negative precision argument is taken as if the precision were omitted."
855
    // /8: "g,G [...] Let P equal the precision if nonzero, 6 if the precision is omitted,
856
    // or 1 if the precision is zero."
857
858
    // Performance note: It's possible to rewrite this for branchless codegen,
859
    // but profiling will be necessary to determine whether that's faster.
860
0
    if (_Precision < 0) {
861
0
        _Precision = 6;
862
0
    } else if (_Precision == 0) {
863
0
        _Precision = 1;
864
0
    } else if (_Precision < 1'000'000) {
865
        // _Precision is ok.
866
0
    } else {
867
        // Avoid integer overflow.
868
        // Due to general notation's zero-trimming behavior, we can simply clamp _Precision.
869
        // This is further clamped below.
870
0
        _Precision = 1'000'000;
871
0
    }
872
873
    // _Precision is now the Standard's P.
874
875
    // /8: "Then, if a conversion with style E would have an exponent of X:
876
    // - if P > X >= -4, the conversion is with style f (or F) and precision P - (X + 1).
877
    // - otherwise, the conversion is with style e (or E) and precision P - 1."
878
879
    // /8: "Finally, [...] any trailing zeros are removed from the fractional portion of the result
880
    // and the decimal-point character is removed if there is no fractional portion remaining."
881
882
0
    using _Tables = _General_precision_tables<_Floating>;
883
884
0
    const _Uint_type* _Table_begin;
885
0
    const _Uint_type* _Table_end;
886
887
0
    if (_Precision <= _Tables::_Max_special_P) {
888
0
        _Table_begin = _Tables::_Special_X_table + (_Precision - 1) * (_Precision + 10) / 2;
889
0
        _Table_end   = _Table_begin + _Precision + 5;
890
0
    } else {
891
0
        _Table_begin = _Tables::_Ordinary_X_table;
892
0
        _Table_end   = _Table_begin + _VSTD::min(_Precision, _Tables::_Max_P) + 5;
893
0
    }
894
895
    // Profiling indicates that linear search is faster than binary search for small tables.
896
    // Performance note: lambda captures may have a small performance cost.
897
0
    const _Uint_type* const _Table_lower_bound = [=] {
898
0
        if constexpr (!_IsSame<_Floating, float>::value) {
899
0
            if (_Precision > 155) { // threshold determined via profiling
900
0
                return _VSTD::lower_bound(_Table_begin, _Table_end, _Uint_value, less{});
901
0
            }
902
0
        }
903
904
0
        return _VSTD::find_if(_Table_begin, _Table_end, [=](const _Uint_type _Elem) { return _Uint_value <= _Elem; });
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<float>(char*, char*, float, int)::'lambda'()::operator()() const::'lambda'(unsigned int)::operator()(unsigned int) const
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<double>(char*, char*, double, int)::'lambda'()::operator()() const::'lambda'(unsigned long long)::operator()(unsigned long long) const
905
0
    }();
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<float>(char*, char*, float, int)::'lambda'()::operator()() const
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<double>(char*, char*, double, int)::'lambda'()::operator()() const
906
907
0
    const ptrdiff_t _Table_index     = _Table_lower_bound - _Table_begin;
908
0
    const int _Scientific_exponent_X = static_cast<int>(_Table_index - 5);
909
0
    const bool _Use_fixed_notation   = _Precision > _Scientific_exponent_X && _Scientific_exponent_X >= -4;
910
911
    // Performance note: it might (or might not) be faster to modify Ryu Printf to perform zero-trimming.
912
    // Such modifications would involve a fairly complicated state machine (notably, both '0' and '9' digits would
913
    // need to be buffered, due to rounding), and that would have performance costs due to increased branching.
914
    // Here, we're using a simpler approach: writing into a local buffer, manually zero-trimming, and then copying into
915
    // the output range. The necessary buffer size is reasonably small, the zero-trimming logic is simple and fast,
916
    // and the final copying is also fast.
917
918
0
    constexpr int _Max_output_length =
919
0
        _IsSame<_Floating, float>::value ? 117 : 773; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
920
0
    constexpr int _Max_fixed_precision =
921
0
        _IsSame<_Floating, float>::value ? 37 : 66; // cases: 0x1.fffffep-14f and 0x1.fffffffffffffp-14
922
0
    constexpr int _Max_scientific_precision =
923
0
        _IsSame<_Floating, float>::value ? 111 : 766; // cases: 0x1.fffffep-126f and 0x1.fffffffffffffp-1022
924
925
    // Note that _Max_output_length is determined by scientific notation and is more than enough for fixed notation.
926
    // 0x1.fffffep+127f is 39 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 77.
927
    // 0x1.fffffffffffffp+1023 is 309 digits, plus 1 for '.', plus _Max_fixed_precision for '0' digits, equals 376.
928
929
0
    char _Buffer[_Max_output_length];
930
0
    const char* const _Significand_first = _Buffer; // e.g. "1.234"
931
0
    const char* _Significand_last        = nullptr;
932
0
    const char* _Exponent_first          = nullptr; // e.g. "e-05"
933
0
    const char* _Exponent_last           = nullptr;
934
0
    int _Effective_precision; // number of digits printed after the decimal point, before trimming
935
936
    // Write into the local buffer.
937
    // Clamping _Effective_precision allows _Buffer to be as small as possible, and increases efficiency.
938
0
    if (_Use_fixed_notation) {
939
0
        _Effective_precision = _VSTD::min(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision);
940
0
        const to_chars_result _Buf_result =
941
0
            _Floating_to_chars_fixed_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision);
942
0
        _LIBCPP_ASSERT(_Buf_result.ec == errc{}, "");
943
0
        _Significand_last = _Buf_result.ptr;
944
0
    } else {
945
0
        _Effective_precision = _VSTD::min(_Precision - 1, _Max_scientific_precision);
946
0
        const to_chars_result _Buf_result =
947
0
            _Floating_to_chars_scientific_precision(_Buffer, _VSTD::end(_Buffer), _Value, _Effective_precision);
948
0
        _LIBCPP_ASSERT(_Buf_result.ec == errc{}, "");
949
0
        _Significand_last = _VSTD::find(_Buffer, _Buf_result.ptr, 'e');
950
0
        _Exponent_first   = _Significand_last;
951
0
        _Exponent_last    = _Buf_result.ptr;
952
0
    }
953
954
    // If we printed a decimal point followed by digits, perform zero-trimming.
955
0
    if (_Effective_precision > 0) {
956
0
        while (_Significand_last[-1] == '0') { // will stop at '.' or a nonzero digit
957
0
            --_Significand_last;
958
0
        }
959
960
0
        if (_Significand_last[-1] == '.') {
961
0
            --_Significand_last;
962
0
        }
963
0
    }
964
965
    // Copy the significand to the output range.
966
0
    const ptrdiff_t _Significand_distance = _Significand_last - _Significand_first;
967
0
    if (_Last - _First < _Significand_distance) {
968
0
        return {_Last, errc::value_too_large};
969
0
    }
970
0
    _VSTD::memcpy(_First, _Significand_first, static_cast<size_t>(_Significand_distance));
971
0
    _First += _Significand_distance;
972
973
    // Copy the exponent to the output range.
974
0
    if (!_Use_fixed_notation) {
975
0
        const ptrdiff_t _Exponent_distance = _Exponent_last - _Exponent_first;
976
0
        if (_Last - _First < _Exponent_distance) {
977
0
            return {_Last, errc::value_too_large};
978
0
        }
979
0
        _VSTD::memcpy(_First, _Exponent_first, static_cast<size_t>(_Exponent_distance));
980
0
        _First += _Exponent_distance;
981
0
    }
982
983
0
    return {_First, errc{}};
984
0
}
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<float>(char*, char*, float, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars_general_precision<double>(char*, char*, double, int)
985
986
enum class _Floating_to_chars_overload { _Plain, _Format_only, _Format_precision };
987
988
template <_Floating_to_chars_overload _Overload, class _Floating>
989
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
990
to_chars_result _Floating_to_chars(
991
0
    char* _First, char* const _Last, _Floating _Value, const chars_format _Fmt, const int _Precision) noexcept {
992
993
0
    if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
994
0
        _LIBCPP_ASSERT(_Fmt == chars_format{}, ""); // plain overload must pass chars_format{} internally
995
0
    } else {
996
0
        _LIBCPP_ASSERT(_Fmt == chars_format::general || _Fmt == chars_format::scientific || _Fmt == chars_format::fixed
997
0
                         || _Fmt == chars_format::hex,
998
0
            "invalid format in to_chars()");
999
0
    }
1000
1001
0
    using _Traits    = _Floating_type_traits<_Floating>;
1002
0
    using _Uint_type = typename _Traits::_Uint_type;
1003
1004
0
    _Uint_type _Uint_value = _VSTD::bit_cast<_Uint_type>(_Value);
1005
1006
0
    const bool _Was_negative = (_Uint_value & _Traits::_Shifted_sign_mask) != 0;
1007
1008
0
    if (_Was_negative) { // sign bit detected; write minus sign and clear sign bit
1009
0
        if (_First == _Last) {
1010
0
            return {_Last, errc::value_too_large};
1011
0
        }
1012
1013
0
        *_First++ = '-';
1014
1015
0
        _Uint_value &= ~_Traits::_Shifted_sign_mask;
1016
0
        _Value = _VSTD::bit_cast<_Floating>(_Uint_value);
1017
0
    }
1018
1019
0
    if ((_Uint_value & _Traits::_Shifted_exponent_mask) == _Traits::_Shifted_exponent_mask) {
1020
        // inf/nan detected; write appropriate string and return
1021
0
        const char* _Str;
1022
0
        size_t _Len;
1023
1024
0
        const _Uint_type _Mantissa = _Uint_value & _Traits::_Denormal_mantissa_mask;
1025
1026
0
        if (_Mantissa == 0) {
1027
0
            _Str = "inf";
1028
0
            _Len = 3;
1029
0
        } else if (_Was_negative && _Mantissa == _Traits::_Special_nan_mantissa_mask) {
1030
            // When a NaN value has the sign bit set, the quiet bit set, and all other mantissa bits cleared,
1031
            // the UCRT interprets it to mean "indeterminate", and indicates this by printing "-nan(ind)".
1032
0
            _Str = "nan(ind)";
1033
0
            _Len = 8;
1034
0
        } else if ((_Mantissa & _Traits::_Special_nan_mantissa_mask) != 0) {
1035
0
            _Str = "nan";
1036
0
            _Len = 3;
1037
0
        } else {
1038
0
            _Str = "nan(snan)";
1039
0
            _Len = 9;
1040
0
        }
1041
1042
0
        if (_Last - _First < static_cast<ptrdiff_t>(_Len)) {
1043
0
            return {_Last, errc::value_too_large};
1044
0
        }
1045
1046
0
        _VSTD::memcpy(_First, _Str, _Len);
1047
1048
0
        return {_First + _Len, errc{}};
1049
0
    }
1050
1051
0
    if constexpr (_Overload == _Floating_to_chars_overload::_Plain) {
1052
0
        return _Floating_to_chars_ryu(_First, _Last, _Value, chars_format{});
1053
0
    } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_only) {
1054
0
        if (_Fmt == chars_format::hex) {
1055
0
            return _Floating_to_chars_hex_shortest(_First, _Last, _Value);
1056
0
        }
1057
1058
0
        return _Floating_to_chars_ryu(_First, _Last, _Value, _Fmt);
1059
0
    } else if constexpr (_Overload == _Floating_to_chars_overload::_Format_precision) {
1060
0
        switch (_Fmt) {
1061
0
        case chars_format::scientific:
1062
0
            return _Floating_to_chars_scientific_precision(_First, _Last, _Value, _Precision);
1063
0
        case chars_format::fixed:
1064
0
            return _Floating_to_chars_fixed_precision(_First, _Last, _Value, _Precision);
1065
0
        case chars_format::general:
1066
0
            return _Floating_to_chars_general_precision(_First, _Last, _Value, _Precision);
1067
0
        case chars_format::hex:
1068
0
        default: // avoid MSVC warning C4715: not all control paths return a value
1069
0
            return _Floating_to_chars_hex_precision(_First, _Last, _Value, _Precision);
1070
0
        }
1071
0
    }
1072
0
}
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)0, float>(char*, char*, float, std::__1::chars_format, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)0, double>(char*, char*, double, std::__1::chars_format, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)1, float>(char*, char*, float, std::__1::chars_format, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)1, double>(char*, char*, double, std::__1::chars_format, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)2, float>(char*, char*, float, std::__1::chars_format, int)
Unexecuted instantiation: std::__1::to_chars_result std::__1::_Floating_to_chars<(std::__1::_Floating_to_chars_overload)2, double>(char*, char*, double, std::__1::chars_format, int)
1073
1074
// clang-format on
1075
1076
_LIBCPP_END_NAMESPACE_STD
1077
1078
#endif // _LIBCPP_SRC_INCLUDE_TO_CHARS_FLOATING_POINT_H