File indexing completed on 2026-05-03 08:13:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H
0011 #define _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H
0012
0013 #include <__algorithm/copy_n.h>
0014 #include <__algorithm/find.h>
0015 #include <__algorithm/max.h>
0016 #include <__algorithm/min.h>
0017 #include <__algorithm/rotate.h>
0018 #include <__algorithm/transform.h>
0019 #include <__assert>
0020 #include <__charconv/chars_format.h>
0021 #include <__charconv/to_chars_floating_point.h>
0022 #include <__charconv/to_chars_result.h>
0023 #include <__concepts/arithmetic.h>
0024 #include <__concepts/same_as.h>
0025 #include <__config>
0026 #include <__cstddef/ptrdiff_t.h>
0027 #include <__format/concepts.h>
0028 #include <__format/format_parse_context.h>
0029 #include <__format/formatter.h>
0030 #include <__format/formatter_integral.h>
0031 #include <__format/formatter_output.h>
0032 #include <__format/parser_std_format_spec.h>
0033 #include <__iterator/concepts.h>
0034 #include <__memory/allocator.h>
0035 #include <__system_error/errc.h>
0036 #include <__type_traits/conditional.h>
0037 #include <__utility/move.h>
0038 #include <__utility/unreachable.h>
0039 #include <cmath>
0040
0041 #if _LIBCPP_HAS_LOCALIZATION
0042 # include <__locale>
0043 #endif
0044
0045 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0046 # pragma GCC system_header
0047 #endif
0048
0049 _LIBCPP_PUSH_MACROS
0050 #include <__undef_macros>
0051
0052 _LIBCPP_BEGIN_NAMESPACE_STD
0053
0054 #if _LIBCPP_STD_VER >= 20
0055
0056 namespace __formatter {
0057
0058 template <floating_point _Tp>
0059 _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) {
0060 to_chars_result __r = std::to_chars(__first, __last, __value);
0061 _LIBCPP_ASSERT_INTERNAL(__r.ec == errc(0), "Internal buffer too small");
0062 return __r.ptr;
0063 }
0064
0065 template <floating_point _Tp>
0066 _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) {
0067 to_chars_result __r = std::to_chars(__first, __last, __value, __fmt);
0068 _LIBCPP_ASSERT_INTERNAL(__r.ec == errc(0), "Internal buffer too small");
0069 return __r.ptr;
0070 }
0071
0072 template <floating_point _Tp>
0073 _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) {
0074 to_chars_result __r = std::to_chars(__first, __last, __value, __fmt, __precision);
0075 _LIBCPP_ASSERT_INTERNAL(__r.ec == errc(0), "Internal buffer too small");
0076 return __r.ptr;
0077 }
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 template <class _Tp>
0110 struct __traits;
0111
0112 template <floating_point _Fp>
0113 _LIBCPP_HIDE_FROM_ABI constexpr size_t __float_buffer_size(int __precision) {
0114 using _Traits = __traits<_Fp>;
0115 return 4 + _Traits::__max_integral + __precision + _Traits::__max_fractional_value;
0116 }
0117
0118 template <>
0119 struct __traits<float> {
0120 static constexpr int __max_integral = 38;
0121 static constexpr int __max_fractional = 149;
0122 static constexpr int __max_fractional_value = 3;
0123 static constexpr size_t __stack_buffer_size = 256;
0124
0125 static constexpr int __hex_precision_digits = 3;
0126 };
0127
0128 template <>
0129 struct __traits<double> {
0130 static constexpr int __max_integral = 308;
0131 static constexpr int __max_fractional = 1074;
0132 static constexpr int __max_fractional_value = 4;
0133 static constexpr size_t __stack_buffer_size = 1024;
0134
0135 static constexpr int __hex_precision_digits = 4;
0136 };
0137
0138
0139
0140
0141
0142 template <floating_point _Fp>
0143 class _LIBCPP_TEMPLATE_VIS __float_buffer {
0144 using _Traits _LIBCPP_NODEBUG = __traits<_Fp>;
0145
0146 public:
0147
0148
0149
0150
0151
0152
0153
0154
0155 explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision)
0156 : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) {
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 if (__precision_ > _Traits::__max_fractional) {
0167 __num_trailing_zeros_ = __precision_ - _Traits::__max_fractional;
0168 __precision_ = _Traits::__max_fractional;
0169 }
0170
0171 __size_ = __formatter::__float_buffer_size<_Fp>(__precision_);
0172 if (__size_ > _Traits::__stack_buffer_size)
0173
0174 __begin_ = allocator<char>{}.allocate(__size_);
0175 else
0176 __begin_ = __buffer_;
0177 }
0178
0179 _LIBCPP_HIDE_FROM_ABI ~__float_buffer() {
0180 if (__size_ > _Traits::__stack_buffer_size)
0181 allocator<char>{}.deallocate(__begin_, __size_);
0182 }
0183 _LIBCPP_HIDE_FROM_ABI __float_buffer(const __float_buffer&) = delete;
0184 _LIBCPP_HIDE_FROM_ABI __float_buffer& operator=(const __float_buffer&) = delete;
0185
0186 _LIBCPP_HIDE_FROM_ABI char* begin() const { return __begin_; }
0187 _LIBCPP_HIDE_FROM_ABI char* end() const { return __begin_ + __size_; }
0188
0189 _LIBCPP_HIDE_FROM_ABI int __precision() const { return __precision_; }
0190 _LIBCPP_HIDE_FROM_ABI int __num_trailing_zeros() const { return __num_trailing_zeros_; }
0191 _LIBCPP_HIDE_FROM_ABI void __remove_trailing_zeros() { __num_trailing_zeros_ = 0; }
0192 _LIBCPP_HIDE_FROM_ABI void __add_trailing_zeros(int __zeros) { __num_trailing_zeros_ += __zeros; }
0193
0194 private:
0195 int __precision_;
0196 int __num_trailing_zeros_{0};
0197 size_t __size_;
0198 char* __begin_;
0199 char __buffer_[_Traits::__stack_buffer_size];
0200 };
0201
0202 struct __float_result {
0203
0204
0205
0206 char* __integral;
0207
0208
0209 char* __radix_point;
0210
0211
0212 char* __exponent;
0213
0214
0215 char* __last;
0216 };
0217
0218
0219
0220
0221
0222
0223
0224 constexpr inline _LIBCPP_HIDE_FROM_ABI char* __find_exponent(char* __first, char* __last) {
0225 ptrdiff_t __size = __last - __first;
0226 if (__size >= 4) {
0227 __first = __last - std::min(__size, ptrdiff_t(6));
0228 for (; __first != __last - 3; ++__first) {
0229 if (*__first == 'e')
0230 return __first;
0231 }
0232 }
0233 return __last;
0234 }
0235
0236 template <class _Fp, class _Tp>
0237 _LIBCPP_HIDE_FROM_ABI __float_result
0238 __format_buffer_default(const __float_buffer<_Fp>& __buffer, _Tp __value, char* __integral) {
0239 __float_result __result;
0240 __result.__integral = __integral;
0241 __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value);
0242
0243 __result.__exponent = __formatter::__find_exponent(__result.__integral, __result.__last);
0244
0245
0246
0247
0248 __result.__radix_point = std::find(__result.__integral + 1, __result.__exponent, '.');
0249
0250
0251
0252 if (__result.__radix_point == __result.__exponent)
0253 __result.__radix_point = __result.__last;
0254
0255
0256 _LIBCPP_ASSERT_INTERNAL((__result.__integral != __result.__last) &&
0257 (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
0258 (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
0259 "Post-condition failure.");
0260
0261
0262 return __result;
0263 }
0264
0265 template <class _Fp, class _Tp>
0266 _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(
0267 const __float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0268 __float_result __result;
0269 __result.__integral = __integral;
0270 if (__precision == -1)
0271 __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex);
0272 else
0273 __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex, __precision);
0274
0275
0276
0277
0278
0279
0280
0281 char* __first = __integral + 1;
0282 if (*__first == '.') {
0283 __result.__radix_point = __first;
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297 static_assert(__traits<_Fp>::__hex_precision_digits <= 4, "Guard against possible underflow.");
0298
0299 char* __last = __result.__last - 2;
0300 __first = __last - __traits<_Fp>::__hex_precision_digits;
0301 __result.__exponent = std::find(__first, __last, 'p');
0302 } else {
0303 __result.__radix_point = __result.__last;
0304 __result.__exponent = __first;
0305 }
0306
0307
0308 _LIBCPP_ASSERT_INTERNAL((__result.__integral != __result.__last) &&
0309 (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
0310 (__result.__exponent != __result.__last && *__result.__exponent == 'p'),
0311 "Post-condition failure.");
0312
0313
0314 return __result;
0315 }
0316
0317 template <class _Fp, class _Tp>
0318 _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_upper_case(
0319 const __float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0320 __float_result __result =
0321 __formatter::__format_buffer_hexadecimal_lower_case(__buffer, __value, __precision, __integral);
0322 std::transform(__result.__integral, __result.__exponent, __result.__integral, __hex_to_upper);
0323 *__result.__exponent = 'P';
0324 return __result;
0325 }
0326
0327 template <class _Fp, class _Tp>
0328 _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(
0329 const __float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0330 __float_result __result;
0331 __result.__integral = __integral;
0332 __result.__last =
0333 __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision);
0334
0335 char* __first = __integral + 1;
0336 _LIBCPP_ASSERT_INTERNAL(__first != __result.__last, "No exponent present");
0337 if (*__first == '.') {
0338 __result.__radix_point = __first;
0339 __result.__exponent = __formatter::__find_exponent(__first + 1, __result.__last);
0340 } else {
0341 __result.__radix_point = __result.__last;
0342 __result.__exponent = __first;
0343 }
0344
0345
0346 _LIBCPP_ASSERT_INTERNAL((__result.__integral != __result.__last) &&
0347 (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
0348 (__result.__exponent != __result.__last && *__result.__exponent == 'e'),
0349 "Post-condition failure.");
0350
0351 return __result;
0352 }
0353
0354 template <class _Fp, class _Tp>
0355 _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_upper_case(
0356 const __float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0357 __float_result __result =
0358 __formatter::__format_buffer_scientific_lower_case(__buffer, __value, __precision, __integral);
0359 *__result.__exponent = 'E';
0360 return __result;
0361 }
0362
0363 template <class _Fp, class _Tp>
0364 _LIBCPP_HIDE_FROM_ABI __float_result
0365 __format_buffer_fixed(const __float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0366 __float_result __result;
0367 __result.__integral = __integral;
0368 __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::fixed, __precision);
0369
0370
0371
0372
0373
0374 __result.__radix_point = __result.__last - (__precision + bool(__precision));
0375 __result.__exponent = __result.__last;
0376
0377
0378 _LIBCPP_ASSERT_INTERNAL((__result.__integral != __result.__last) &&
0379 (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
0380 (__result.__exponent == __result.__last),
0381 "Post-condition failure.");
0382
0383 return __result;
0384 }
0385
0386 template <class _Fp, class _Tp>
0387 _LIBCPP_HIDE_FROM_ABI __float_result
0388 __format_buffer_general_lower_case(__float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0389 __buffer.__remove_trailing_zeros();
0390
0391 __float_result __result;
0392 __result.__integral = __integral;
0393 __result.__last = __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision);
0394
0395 char* __first = __integral + 1;
0396 if (__first == __result.__last) {
0397 __result.__radix_point = __result.__last;
0398 __result.__exponent = __result.__last;
0399 } else {
0400 __result.__exponent = __formatter::__find_exponent(__first, __result.__last);
0401 if (__result.__exponent != __result.__last)
0402
0403
0404 __result.__radix_point = *__first == '.' ? __first : __result.__last;
0405 else {
0406
0407
0408
0409 __result.__radix_point = std::find(__first, __result.__last, '.');
0410 }
0411 }
0412
0413
0414 _LIBCPP_ASSERT_INTERNAL((__result.__integral != __result.__last) &&
0415 (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
0416 (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
0417 "Post-condition failure.");
0418
0419
0420 return __result;
0421 }
0422
0423 template <class _Fp, class _Tp>
0424 _LIBCPP_HIDE_FROM_ABI __float_result
0425 __format_buffer_general_upper_case(__float_buffer<_Fp>& __buffer, _Tp __value, int __precision, char* __integral) {
0426 __float_result __result = __formatter::__format_buffer_general_lower_case(__buffer, __value, __precision, __integral);
0427 if (__result.__exponent != __result.__last)
0428 *__result.__exponent = 'E';
0429 return __result;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 template <class _Fp, class _Tp>
0448
0449 _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer(
0450 __float_buffer<_Fp>& __buffer,
0451 _Tp __value,
0452 bool __negative,
0453 bool __has_precision,
0454 __format_spec::__sign __sign,
0455 __format_spec::__type __type) {
0456 char* __first = __formatter::__insert_sign(__buffer.begin(), __negative, __sign);
0457 switch (__type) {
0458 case __format_spec::__type::__default:
0459 if (__has_precision)
0460 return __formatter::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first);
0461 else
0462 return __formatter::__format_buffer_default(__buffer, __value, __first);
0463
0464 case __format_spec::__type::__hexfloat_lower_case:
0465 return __formatter::__format_buffer_hexadecimal_lower_case(
0466 __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
0467
0468 case __format_spec::__type::__hexfloat_upper_case:
0469 return __formatter::__format_buffer_hexadecimal_upper_case(
0470 __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
0471
0472 case __format_spec::__type::__scientific_lower_case:
0473 return __formatter::__format_buffer_scientific_lower_case(__buffer, __value, __buffer.__precision(), __first);
0474
0475 case __format_spec::__type::__scientific_upper_case:
0476 return __formatter::__format_buffer_scientific_upper_case(__buffer, __value, __buffer.__precision(), __first);
0477
0478 case __format_spec::__type::__fixed_lower_case:
0479 case __format_spec::__type::__fixed_upper_case:
0480 return __formatter::__format_buffer_fixed(__buffer, __value, __buffer.__precision(), __first);
0481
0482 case __format_spec::__type::__general_lower_case:
0483 return __formatter::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first);
0484
0485 case __format_spec::__type::__general_upper_case:
0486 return __formatter::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first);
0487
0488 default:
0489 _LIBCPP_ASSERT_INTERNAL(false, "The parser should have validated the type");
0490 __libcpp_unreachable();
0491 }
0492 }
0493
0494 # if _LIBCPP_HAS_LOCALIZATION
0495 template <class _OutIt, class _Fp, class _CharT>
0496 _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(
0497 _OutIt __out_it,
0498 const __float_buffer<_Fp>& __buffer,
0499 const __float_result& __result,
0500 std::locale __loc,
0501 __format_spec::__parsed_specifications<_CharT> __specs) {
0502 const auto& __np = std::use_facet<numpunct<_CharT>>(__loc);
0503 string __grouping = __np.grouping();
0504 char* __first = __result.__integral;
0505
0506 char* __last = std::min(__result.__radix_point, __result.__exponent);
0507
0508 ptrdiff_t __digits = __last - __first;
0509 if (!__grouping.empty()) {
0510 if (__digits <= __grouping[0])
0511 __grouping.clear();
0512 else
0513 __grouping = __formatter::__determine_grouping(__digits, __grouping);
0514 }
0515
0516 ptrdiff_t __size =
0517 __result.__last - __buffer.begin() +
0518 __buffer.__num_trailing_zeros() +
0519 __grouping.size() -
0520 !__grouping.empty();
0521
0522 __formatter::__padding_size_result __padding = {0, 0};
0523 bool __zero_padding = __specs.__alignment_ == __format_spec::__alignment::__zero_padding;
0524 if (__size < __specs.__width_) {
0525 if (__zero_padding) {
0526 __specs.__alignment_ = __format_spec::__alignment::__right;
0527 __specs.__fill_.__data[0] = _CharT('0');
0528 }
0529
0530 __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_);
0531 }
0532
0533
0534 if (__zero_padding && __first != __buffer.begin())
0535 *__out_it++ = *__buffer.begin();
0536 __out_it = __formatter::__fill(std::move(__out_it), __padding.__before_, __specs.__fill_);
0537 if (!__zero_padding && __first != __buffer.begin())
0538 *__out_it++ = *__buffer.begin();
0539
0540
0541 if (__grouping.empty()) {
0542 __out_it = __formatter::__copy(__first, __digits, std::move(__out_it));
0543 } else {
0544 auto __r = __grouping.rbegin();
0545 auto __e = __grouping.rend() - 1;
0546 _CharT __sep = __np.thousands_sep();
0547
0548
0549
0550
0551
0552
0553 while (true) {
0554 __out_it = __formatter::__copy(__first, *__r, std::move(__out_it));
0555 __first += *__r;
0556
0557 if (__r == __e)
0558 break;
0559
0560 ++__r;
0561 *__out_it++ = __sep;
0562 }
0563 }
0564
0565
0566 if (__result.__radix_point != __result.__last) {
0567 *__out_it++ = __np.decimal_point();
0568 __out_it = __formatter::__copy(__result.__radix_point + 1, __result.__exponent, std::move(__out_it));
0569 __out_it = __formatter::__fill(std::move(__out_it), __buffer.__num_trailing_zeros(), _CharT('0'));
0570 }
0571
0572
0573 if (__result.__exponent != __result.__last)
0574 __out_it = __formatter::__copy(__result.__exponent, __result.__last, std::move(__out_it));
0575
0576
0577 return __formatter::__fill(std::move(__out_it), __padding.__after_, __specs.__fill_);
0578 }
0579 # endif
0580
0581 template <class _OutIt, class _CharT>
0582 _LIBCPP_HIDE_FROM_ABI _OutIt __format_floating_point_non_finite(
0583 _OutIt __out_it, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative, bool __isnan) {
0584 char __buffer[4];
0585 char* __last = __formatter::__insert_sign(__buffer, __negative, __specs.__std_.__sign_);
0586
0587
0588
0589
0590 bool __upper_case =
0591 __specs.__std_.__type_ == __format_spec::__type::__hexfloat_upper_case ||
0592 __specs.__std_.__type_ == __format_spec::__type::__scientific_upper_case ||
0593 __specs.__std_.__type_ == __format_spec::__type::__fixed_upper_case ||
0594 __specs.__std_.__type_ == __format_spec::__type::__general_upper_case;
0595 __last = std::copy_n(&("infnanINFNAN"[6 * __upper_case + 3 * __isnan]), 3, __last);
0596
0597
0598
0599
0600
0601 if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding)
0602 __specs.__alignment_ = __format_spec::__alignment::__right;
0603
0604 return __formatter::__write(__buffer, __last, std::move(__out_it), __specs);
0605 }
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 template <class _CharT, class _ParserCharT>
0616 _LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros(
0617 const _CharT* __first,
0618 const _CharT* __last,
0619 output_iterator<const _CharT&> auto __out_it,
0620 __format_spec::__parsed_specifications<_ParserCharT> __specs,
0621 size_t __size,
0622 const _CharT* __exponent,
0623 size_t __num_trailing_zeros) -> decltype(__out_it) {
0624 _LIBCPP_ASSERT_INTERNAL(__first <= __last, "Not a valid range");
0625 _LIBCPP_ASSERT_INTERNAL(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used");
0626
0627 __padding_size_result __padding =
0628 __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_);
0629 __out_it = __formatter::__fill(std::move(__out_it), __padding.__before_, __specs.__fill_);
0630 __out_it = __formatter::__copy(__first, __exponent, std::move(__out_it));
0631 __out_it = __formatter::__fill(std::move(__out_it), __num_trailing_zeros, _CharT('0'));
0632 __out_it = __formatter::__copy(__exponent, __last, std::move(__out_it));
0633 return __formatter::__fill(std::move(__out_it), __padding.__after_, __specs.__fill_);
0634 }
0635
0636 template <floating_point _Tp, class _CharT, class _FormatContext>
0637 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
0638 __format_floating_point(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) {
0639 bool __negative = std::signbit(__value);
0640
0641 if (!std::isfinite(__value)) [[unlikely]]
0642 return __formatter::__format_floating_point_non_finite(__ctx.out(), __specs, __negative, std::isnan(__value));
0643
0644
0645
0646
0647
0648
0649
0650
0651 if (__negative)
0652 __value = -__value;
0653
0654
0655 using _Fp = conditional_t<same_as<_Tp, long double>, double, _Tp>;
0656
0657 __float_buffer<_Fp> __buffer(__specs.__precision_);
0658 __float_result __result = __formatter::__format_buffer(
0659 __buffer, __value, __negative, (__specs.__has_precision()), __specs.__std_.__sign_, __specs.__std_.__type_);
0660
0661 if (__specs.__std_.__alternate_form_) {
0662 if (__result.__radix_point == __result.__last) {
0663 *__result.__last++ = '.';
0664
0665
0666
0667
0668 std::rotate(__result.__exponent, __result.__last - 1, __result.__last);
0669 __result.__radix_point = __result.__exponent;
0670
0671
0672
0673
0674
0675 ++__result.__exponent;
0676 }
0677
0678
0679
0680
0681
0682
0683
0684
0685 bool __is_general = __specs.__std_.__type_ == __format_spec::__type::__general_lower_case ||
0686 __specs.__std_.__type_ == __format_spec::__type::__general_upper_case;
0687
0688 if (__is_general) {
0689
0690
0691
0692
0693 int __p = std::max<int>(1, (__specs.__has_precision() ? __specs.__precision_ : 6));
0694 if (__result.__exponent == __result.__last)
0695
0696
0697 __p -= __result.__radix_point - __result.__integral;
0698 else
0699
0700 --__p;
0701
0702 ptrdiff_t __precision = (__result.__exponent - __result.__radix_point) - 1;
0703 if (__precision < __p)
0704 __buffer.__add_trailing_zeros(__p - __precision);
0705 }
0706 }
0707
0708 # if _LIBCPP_HAS_LOCALIZATION
0709 if (__specs.__std_.__locale_specific_form_)
0710 return __formatter::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(), __specs);
0711 # endif
0712
0713 ptrdiff_t __size = __result.__last - __buffer.begin();
0714 int __num_trailing_zeros = __buffer.__num_trailing_zeros();
0715 if (__size + __num_trailing_zeros >= __specs.__width_) {
0716 if (__num_trailing_zeros && __result.__exponent != __result.__last)
0717
0718 return __formatter::__copy(
0719 __result.__exponent,
0720 __result.__last,
0721 __formatter::__fill(__formatter::__copy(__buffer.begin(), __result.__exponent, __ctx.out()),
0722 __num_trailing_zeros,
0723 _CharT('0')));
0724
0725 return __formatter::__fill(
0726 __formatter::__copy(__buffer.begin(), __result.__last, __ctx.out()), __num_trailing_zeros, _CharT('0'));
0727 }
0728
0729 auto __out_it = __ctx.out();
0730 char* __first = __buffer.begin();
0731 if (__specs.__alignment_ == __format_spec::__alignment ::__zero_padding) {
0732
0733
0734
0735 if (__first != __result.__integral)
0736 *__out_it++ = *__first++;
0737
0738
0739 __specs.__alignment_ = __format_spec::__alignment::__right;
0740 __specs.__fill_.__data[0] = _CharT('0');
0741 }
0742
0743 if (__num_trailing_zeros)
0744 return __formatter::__write_using_trailing_zeros(
0745 __first, __result.__last, std::move(__out_it), __specs, __size, __result.__exponent, __num_trailing_zeros);
0746
0747 return __formatter::__write(__first, __result.__last, std::move(__out_it), __specs, __size);
0748 }
0749
0750 }
0751
0752 template <__fmt_char_type _CharT>
0753 struct _LIBCPP_TEMPLATE_VIS __formatter_floating_point {
0754 public:
0755 template <class _ParseContext>
0756 _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
0757 typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_floating_point);
0758 __format_spec::__process_parsed_floating_point(__parser_, "a floating-point");
0759 return __result;
0760 }
0761
0762 template <floating_point _Tp, class _FormatContext>
0763 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Tp __value, _FormatContext& __ctx) const {
0764 return __formatter::__format_floating_point(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
0765 }
0766
0767 __format_spec::__parser<_CharT> __parser_;
0768 };
0769
0770 template <__fmt_char_type _CharT>
0771 struct _LIBCPP_TEMPLATE_VIS formatter<float, _CharT> : public __formatter_floating_point<_CharT> {};
0772 template <__fmt_char_type _CharT>
0773 struct _LIBCPP_TEMPLATE_VIS formatter<double, _CharT> : public __formatter_floating_point<_CharT> {};
0774 template <__fmt_char_type _CharT>
0775 struct _LIBCPP_TEMPLATE_VIS formatter<long double, _CharT> : public __formatter_floating_point<_CharT> {};
0776
0777 # if _LIBCPP_STD_VER >= 23
0778 template <>
0779 inline constexpr bool enable_nonlocking_formatter_optimization<float> = true;
0780 template <>
0781 inline constexpr bool enable_nonlocking_formatter_optimization<double> = true;
0782 template <>
0783 inline constexpr bool enable_nonlocking_formatter_optimization<long double> = true;
0784 # endif
0785 #endif
0786
0787 _LIBCPP_END_NAMESPACE_STD
0788
0789 _LIBCPP_POP_MACROS
0790
0791 #endif