38 #pragma GCC system_header
42 #pragma clang system_header
48 #include <initializer_list>
52 #include <system_error>
54 #ifdef __cpp_lib_bit_cast
61 #define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
63 #define FMT_GCC_VISIBILITY_HIDDEN
67 #define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
69 #define FMT_CUDA_VERSION 0
73 #define FMT_HAS_BUILTIN(x) __has_builtin(x)
75 #define FMT_HAS_BUILTIN(x) 0
78 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
79 #define FMT_NOINLINE __attribute__((noinline))
85 #define FMT_MSC_DEFAULT = default
87 #define FMT_MSC_DEFAULT
92 #if FMT_MSC_VERSION || defined(__NVCC__)
95 template <
typename Exception>
inline void do_throw(
const Exception &x) {
98 volatile bool b =
true;
104 #define FMT_THROW(x) detail::do_throw(x)
106 #define FMT_THROW(x) throw x
109 #define FMT_THROW(x) \
111 FMT_ASSERT(false, (x).what()); \
118 #define FMT_CATCH(x) catch (x)
120 #define FMT_TRY if (true)
121 #define FMT_CATCH(x) if (false)
124 #ifndef FMT_MAYBE_UNUSED
125 #if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
126 #define FMT_MAYBE_UNUSED [[maybe_unused]]
128 #define FMT_MAYBE_UNUSED
132 #ifndef FMT_USE_USER_DEFINED_LITERALS
134 #if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
135 FMT_MSC_VERSION >= 1900) && \
136 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 480)
137 #define FMT_USE_USER_DEFINED_LITERALS 1
139 #define FMT_USE_USER_DEFINED_LITERALS 0
147 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
148 #define FMT_REDUCE_INT_INSTANTIATIONS 0
154 #if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
155 #define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
157 #if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
158 #define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
165 #if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
166 defined(__NVCOMPILER)
167 #define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
169 #if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
170 defined(__NVCOMPILER)
171 #define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
182 #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
183 !defined(FMT_BUILTIN_CTZLL)
187 #if !defined(__clang__)
188 #pragma intrinsic(_BitScanForward)
189 #pragma intrinsic(_BitScanReverse)
191 #pragma intrinsic(_BitScanForward64)
192 #pragma intrinsic(_BitScanReverse64)
196 inline auto clz(uint32_t x) ->
int {
198 _BitScanReverse(&r, x);
199 FMT_ASSERT(x != 0,
"");
203 FMT_MSC_WARNING(suppress : 6102)
204 return 31 ^
static_cast<int>(r);
206 #define FMT_BUILTIN_CLZ(n) detail::clz(n)
208 inline auto clzll(uint64_t x) ->
int {
211 _BitScanReverse64(&r, x);
214 if (_BitScanReverse(&r,
static_cast<uint32_t
>(x >> 32)))
215 return 63 ^ (r + 32);
217 _BitScanReverse(&r,
static_cast<uint32_t
>(x));
219 FMT_ASSERT(x != 0,
"");
220 FMT_MSC_WARNING(suppress : 6102)
221 return 63 ^
static_cast<int>(r);
223 #define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
225 inline auto ctz(uint32_t x) ->
int {
227 _BitScanForward(&r, x);
228 FMT_ASSERT(x != 0,
"");
229 FMT_MSC_WARNING(suppress : 6102)
230 return static_cast<int>(r);
232 #define FMT_BUILTIN_CTZ(n) detail::ctz(n)
234 inline auto ctzll(uint64_t x) ->
int {
236 FMT_ASSERT(x != 0,
"");
237 FMT_MSC_WARNING(suppress : 6102)
239 _BitScanForward64(&r, x);
242 if (_BitScanForward(&r,
static_cast<uint32_t
>(x)))
243 return static_cast<int>(r);
245 _BitScanForward(&r,
static_cast<uint32_t
>(x >> 32));
248 return static_cast<int>(r);
250 #define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
257 template <
typename...>
struct disjunction : std::false_type {};
258 template <
typename P>
struct disjunction<P> : P {};
259 template <
typename P1,
typename... Pn>
260 struct disjunction<P1, Pn...>
261 : conditional_t<bool(P1::value), P1, disjunction<Pn...>> {};
263 template <
typename...>
struct conjunction : std::true_type {};
264 template <
typename P>
struct conjunction<P> : P {};
265 template <
typename P1,
typename... Pn>
266 struct conjunction<P1, Pn...>
267 : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
271 FMT_CONSTEXPR
inline void abort_fuzzing_if(
bool condition) {
272 ignore_unused(condition);
275 throw std::runtime_error(
"fuzzing limit reached");
279 template <
typename CharT, CharT... C>
struct string_literal {
280 static constexpr CharT value[
sizeof...(C)] = {C...};
282 return {value,
sizeof...(C)};
286 #if FMT_CPLUSPLUS < 201703L
287 template <
typename CharT, CharT... C>
288 constexpr CharT string_literal<CharT, C...>::value[
sizeof...(C)];
291 template <
typename Streambuf>
class formatbuf :
public Streambuf {
293 using char_type =
typename Streambuf::char_type;
294 using streamsize = decltype(std::declval<Streambuf>().sputn(
nullptr, 0));
295 using int_type =
typename Streambuf::int_type;
296 using traits_type =
typename Streambuf::traits_type;
310 auto overflow(int_type ch) -> int_type
override {
311 if (!traits_type::eq_int_type(ch, traits_type::eof()))
312 buffer_.push_back(
static_cast<char_type
>(ch));
316 auto xsputn(
const char_type *s, streamsize count) -> streamsize
override {
317 buffer_.
append(s, s + count);
323 template <
typename To,
typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
324 FMT_CONSTEXPR20
auto bit_cast(
const From &from) -> To {
325 #ifdef __cpp_lib_bit_cast
326 if (is_constant_evaluated())
327 return std::bit_cast<To>(from);
331 std::memcpy(
static_cast<void *
>(&to), &from,
sizeof(to));
335 inline auto is_big_endian() ->
bool {
338 #elif defined(__BIG_ENDIAN__)
340 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
341 return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
344 char data[
sizeof(int)];
346 return bit_cast<bytes>(1).data[0] == 0;
350 class uint128_fallback {
354 friend uint128_fallback umul128(uint64_t x, uint64_t y) noexcept;
357 constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
358 constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
360 constexpr uint64_t high() const noexcept {
return hi_; }
361 constexpr uint64_t low() const noexcept {
return lo_; }
363 template <
typename T, FMT_ENABLE_IF(std::is_
integral<T>::value)>
364 constexpr
explicit operator T()
const {
365 return static_cast<T
>(lo_);
368 friend constexpr
auto operator==(
const uint128_fallback &lhs,
369 const uint128_fallback &rhs) ->
bool {
370 return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
372 friend constexpr
auto operator!=(
const uint128_fallback &lhs,
373 const uint128_fallback &rhs) ->
bool {
374 return !(lhs == rhs);
376 friend constexpr
auto operator>(
const uint128_fallback &lhs,
377 const uint128_fallback &rhs) ->
bool {
378 return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
380 friend constexpr
auto operator|(
const uint128_fallback &lhs,
381 const uint128_fallback &rhs)
382 -> uint128_fallback {
383 return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
385 friend constexpr
auto operator&(
const uint128_fallback &lhs,
386 const uint128_fallback &rhs)
387 -> uint128_fallback {
388 return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
390 friend constexpr
auto operator~(
const uint128_fallback &n)
391 -> uint128_fallback {
392 return {~n.hi_, ~n.lo_};
394 friend auto operator+(
const uint128_fallback &lhs,
395 const uint128_fallback &rhs) -> uint128_fallback {
396 auto result = uint128_fallback(lhs);
400 friend auto operator*(
const uint128_fallback &lhs, uint32_t rhs)
401 -> uint128_fallback {
402 FMT_ASSERT(lhs.hi_ == 0,
"");
403 uint64_t hi = (lhs.lo_ >> 32) * rhs;
404 uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
405 uint64_t new_lo = (hi << 32) + lo;
406 return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
408 friend auto operator-(
const uint128_fallback &lhs, uint64_t rhs)
409 -> uint128_fallback {
410 return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
412 FMT_CONSTEXPR
auto operator>>(
int shift)
const -> uint128_fallback {
416 return uint128_fallback(0, hi_) >> (shift - 64);
417 return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
419 FMT_CONSTEXPR
auto operator<<(
int shift)
const -> uint128_fallback {
423 return uint128_fallback(lo_, 0) << (shift - 64);
424 return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
426 FMT_CONSTEXPR
auto operator>>=(
int shift) -> uint128_fallback & {
427 return *
this = *
this >> shift;
429 FMT_CONSTEXPR
void operator+=(uint128_fallback n) {
430 uint64_t new_lo = lo_ + n.lo_;
431 uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
432 FMT_ASSERT(new_hi >= hi_,
"");
436 FMT_CONSTEXPR
void operator&=(uint128_fallback n) {
441 FMT_CONSTEXPR20 uint128_fallback &
operator+=(uint64_t n) noexcept {
442 if (is_constant_evaluated()) {
444 hi_ += (lo_ < n ? 1 : 0);
447 #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
448 unsigned long long carry;
449 lo_ = __builtin_addcll(lo_, n, 0, &carry);
451 #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
452 unsigned long long result;
453 auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
456 #elif defined(_MSC_VER) && defined(_M_X64)
457 auto carry = _addcarry_u64(0, lo_, n, &lo_);
458 _addcarry_u64(carry, hi_, 0, &hi_);
461 hi_ += (lo_ < n ? 1 : 0);
467 using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>;
470 using uintptr_t = ::uintptr_t;
472 using uintptr_t = uint128_t;
477 template <
typename T> constexpr
auto max_value() -> T {
478 return (std::numeric_limits<T>::max)();
480 template <
typename T> constexpr
auto num_bits() ->
int {
481 return std::numeric_limits<T>::digits;
484 template <> constexpr
auto num_bits<int128_opt>() ->
int {
return 128; }
485 template <> constexpr
auto num_bits<uint128_t>() ->
int {
return 128; }
489 template <
typename To,
typename From, FMT_ENABLE_IF(sizeof(To) >
sizeof(From))>
490 inline auto bit_cast(
const From &from) -> To {
491 constexpr
auto size =
static_cast<int>(
sizeof(From) /
sizeof(
unsigned));
493 unsigned value[
static_cast<unsigned>(size)];
494 } data = bit_cast<data_t>(from);
496 if (const_check(is_big_endian())) {
497 for (
int i = 0; i < size; ++i)
498 result = (result << num_bits<unsigned>()) | data.value[i];
500 for (
int i = size - 1; i >= 0; --i)
501 result = (result << num_bits<unsigned>()) | data.value[i];
506 template <
class UInt>
507 FMT_CONSTEXPR20
inline auto countl_zero_fallback(UInt n) ->
int {
509 constexpr UInt msb_mask =
static_cast<UInt
>(1) << (num_bits<UInt>() - 1);
510 for (; (n & msb_mask) == 0; n <<= 1)
515 FMT_CONSTEXPR20
inline auto countl_zero(uint32_t n) ->
int {
516 #ifdef FMT_BUILTIN_CLZ
517 if (!is_constant_evaluated())
518 return FMT_BUILTIN_CLZ(n);
520 return countl_zero_fallback(n);
523 FMT_CONSTEXPR20
inline auto countl_zero(uint64_t n) ->
int {
524 #ifdef FMT_BUILTIN_CLZLL
525 if (!is_constant_evaluated())
526 return FMT_BUILTIN_CLZLL(n);
528 return countl_zero_fallback(n);
531 FMT_INLINE
void assume(
bool condition) {
533 #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
534 __builtin_assume(condition);
539 template <
typename T>
540 using iterator_t = decltype(std::begin(std::declval<T &>()));
541 template <
typename T>
542 using sentinel_t = decltype(std::end(std::declval<T &>()));
545 template <
typename Char>
546 inline auto get_data(std::basic_string<Char> &s) -> Char * {
549 template <
typename Container>
550 inline auto get_data(Container &c) ->
typename Container::value_type * {
554 #if defined(_SECURE_SCL) && _SECURE_SCL
556 template <
typename T>
using checked_ptr = stdext::checked_array_iterator<T *>;
557 template <
typename T>
558 constexpr
auto make_checked(T *p,
size_t size) -> checked_ptr<T> {
562 template <
typename T>
using checked_ptr = T *;
563 template <
typename T> constexpr
auto make_checked(T *p,
size_t) -> T * {
570 template <
typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
571 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
572 __attribute__((no_sanitize(
"undefined")))
575 reserve(std::back_insert_iterator<Container> it,
size_t n)
576 -> checked_ptr<typename Container::value_type> {
577 Container &
c = get_container(it);
578 size_t size =
c.size();
580 return make_checked(get_data(c) + size, n);
583 template <
typename T>
584 inline auto reserve(buffer_appender<T> it,
size_t n) -> buffer_appender<T> {
586 buf.try_reserve(buf.
size() + n);
590 template <
typename Iterator>
591 constexpr
auto reserve(Iterator &it,
size_t) -> Iterator & {
595 template <
typename OutputIt>
596 using reserve_iterator =
597 remove_reference_t<decltype(reserve(std::declval<OutputIt &>(), 0))>;
599 template <
typename T,
typename OutputIt>
600 constexpr
auto to_pointer(OutputIt,
size_t) -> T * {
603 template <
typename T>
auto to_pointer(buffer_appender<T> it,
size_t n) -> T * {
605 auto size = buf.
size();
608 buf.try_resize(size + n);
609 return buf.
data() + size;
612 template <
typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
613 inline auto base_iterator(std::back_insert_iterator<Container> &it,
614 checked_ptr<typename Container::value_type>)
615 -> std::back_insert_iterator<Container> {
619 template <
typename Iterator>
620 constexpr
auto base_iterator(Iterator, Iterator it) -> Iterator {
626 template <
typename OutputIt,
typename Size,
typename T>
627 FMT_CONSTEXPR
auto fill_n(OutputIt out, Size count,
const T &value)
629 for (Size i = 0; i < count; ++i)
633 template <
typename T,
typename Size>
634 FMT_CONSTEXPR20
auto fill_n(T *out, Size count,
char value) -> T * {
635 if (is_constant_evaluated()) {
636 return fill_n<T *, Size, T>(out, count, value);
638 std::memset(out, value, to_unsigned(count));
643 using char8_type = char8_t;
645 enum char8_type :
unsigned char {};
648 template <
typename OutChar,
typename InputIt,
typename OutputIt>
649 FMT_CONSTEXPR FMT_NOINLINE
auto copy_str_noinline(InputIt begin, InputIt end,
650 OutputIt out) -> OutputIt {
651 return copy_str<OutChar>(begin, end, out);
671 FMT_CONSTEXPR
inline auto utf8_decode(
const char *s, uint32_t *c,
int *e)
673 constexpr
const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
674 constexpr
const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
675 constexpr
const int shiftc[] = {0, 18, 12, 6, 0};
676 constexpr
const int shifte[] = {0, 6, 4, 2, 0};
678 int len = code_point_length_impl(*s);
682 const char *next = s + len + !len;
684 using uchar =
unsigned char;
688 *
c = uint32_t(uchar(s[0]) & masks[len]) << 18;
689 *
c |= uint32_t(uchar(s[1]) & 0x3f) << 12;
690 *
c |= uint32_t(uchar(s[2]) & 0x3f) << 6;
691 *
c |= uint32_t(uchar(s[3]) & 0x3f) << 0;
695 *e = (*
c < mins[len]) << 6;
696 *e |= ((*
c >> 11) == 0x1b) << 7;
697 *e |= (*
c > 0x10FFFF) << 8;
698 *e |= (uchar(s[1]) & 0xc0) >> 2;
699 *e |= (uchar(s[2]) & 0xc0) >> 4;
700 *e |= uchar(s[3]) >> 6;
707 constexpr uint32_t invalid_code_point = ~uint32_t();
711 template <
typename F>
712 FMT_CONSTEXPR
void for_each_codepoint(
string_view s, F f) {
713 auto decode = [
f](
const char *buf_ptr,
const char *ptr) {
714 auto cp = uint32_t();
716 auto end = utf8_decode(buf_ptr, &cp, &error);
717 bool result =
f(error ? invalid_code_point : cp,
718 string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr)));
719 return result ? (error ? buf_ptr + 1 : end) :
nullptr;
722 const size_t block_size = 4;
723 if (s.
size() >= block_size) {
724 for (
auto end = p + s.
size() - block_size + 1; p < end;) {
730 if (
auto num_chars_left = s.
data() + s.
size() - p) {
731 char buf[2 * block_size - 1] = {};
732 copy_str<char>(p, p + num_chars_left, buf);
733 const char *buf_ptr = buf;
735 auto end = decode(buf_ptr, p);
740 }
while (buf_ptr - buf < num_chars_left);
744 template <
typename Char>
750 FMT_CONSTEXPR
inline size_t compute_width(
string_view s) {
751 size_t num_code_points = 0;
753 struct count_code_points {
755 FMT_CONSTEXPR
auto operator()(uint32_t cp,
string_view)
const ->
bool {
756 *count += detail::to_unsigned(
763 (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
764 (cp >= 0xac00 && cp <= 0xd7a3) ||
765 (cp >= 0xf900 && cp <= 0xfaff) ||
766 (cp >= 0xfe10 && cp <= 0xfe19) ||
767 (cp >= 0xfe30 && cp <= 0xfe6f) ||
768 (cp >= 0xff00 && cp <= 0xff60) ||
769 (cp >= 0xffe0 && cp <= 0xffe6) ||
770 (cp >= 0x20000 && cp <= 0x2fffd) ||
771 (cp >= 0x30000 && cp <= 0x3fffd) ||
773 (cp >= 0x1f300 && cp <= 0x1f64f) ||
775 (cp >= 0x1f900 && cp <= 0x1f9ff))));
780 for_each_codepoint(s, count_code_points{&num_code_points});
781 return num_code_points;
785 return compute_width(
789 template <
typename Char>
791 size_t size = s.
size();
792 return n < size ? n : size;
796 inline auto code_point_index(
string_view s,
size_t n) ->
size_t {
797 const char *data = s.
data();
798 size_t num_code_points = 0;
799 for (
size_t i = 0, size = s.
size(); i != size; ++i) {
800 if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n)
808 return code_point_index(
812 template <
typename T>
struct is_integral : std::is_integral<T> {};
813 template <>
struct is_integral<int128_opt> : std::true_type {};
814 template <>
struct is_integral<uint128_t> : std::true_type {};
816 template <
typename T>
818 std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
819 std::is_same<T, int128_opt>::value>;
821 template <
typename T>
823 bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
824 !std::is_same<T, char>::value &&
825 !std::is_same<T, wchar_t>::value>;
827 #ifndef FMT_USE_FLOAT128
828 #ifdef __SIZEOF_FLOAT128__
829 #define FMT_USE_FLOAT128 1
831 #define FMT_USE_FLOAT128 0
835 using float128 = __float128;
837 using float128 = void;
839 template <
typename T>
using is_float128 = std::is_same<T, float128>;
841 template <
typename T>
842 using is_floating_point =
843 bool_constant<std::is_floating_point<T>::value || is_float128<T>::value>;
845 template <typename T, bool = std::is_floating_point<T>::value>
846 struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
847 sizeof(T) <= sizeof(double)> {};
848 template <typename T> struct is_fast_float<T, false> : std::false_type {};
850 template <typename T>
851 using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
853 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
854 #define FMT_USE_FULL_CACHE_DRAGONBOX 0
857 template <typename T>
858 template <typename U>
859 void buffer<T>::append(const U *begin, const U *end) {
860 while (begin != end) {
861 auto count = to_unsigned(end - begin);
862 try_reserve(size_ + count);
863 auto free_cap = capacity_ - size_;
864 if (free_cap < count)
866 std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
872 template <typename T, typename Enable = void>
873 struct is_locale : std::false_type {};
874 template <typename T>
875 struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
878 FMT_MODULE_EXPORT_BEGIN
882 enum { inline_buffer_size = 500 };
905 template <typename T, size_t SIZE = inline_buffer_size,
906 typename Allocator = std::allocator<T>>
907 class basic_memory_buffer final : public detail::buffer<T> {
915 FMT_CONSTEXPR20 void deallocate() {
916 T *data = this->data();
918 alloc_.deallocate(data, this->capacity());
922 FMT_CONSTEXPR20 void grow(size_t size) override;
925 using value_type = T;
926 using const_reference = const T &;
929 const Allocator &alloc = Allocator())
931 this->set(store_, SIZE);
932 if (detail::is_constant_evaluated())
933 detail::fill_n(store_, SIZE, T());
940 alloc_ = std::move(other.alloc_);
941 T *data = other.data();
942 size_t size = other.size(), capacity = other.capacity();
943 if (data == other.store_) {
944 this->set(store_, capacity);
945 detail::copy_str<T>(other.store_, other.store_ + size,
946 detail::make_checked(store_, capacity));
948 this->set(data, capacity);
951 other.set(other.store_, 0);
975 FMT_ASSERT(
this != &other,
"");
982 auto get_allocator() const -> Allocator {
return alloc_; }
988 FMT_CONSTEXPR20
void resize(
size_t count) { this->try_resize(count); }
991 void reserve(
size_t new_capacity) { this->try_reserve(new_capacity); }
994 using detail::buffer<T>::append;
995 template <
typename ContiguousRange>
996 void append(
const ContiguousRange &range) {
997 append(range.data(), range.data() + range.size());
1001 template <
typename T,
size_t SIZE,
typename Allocator>
1002 FMT_CONSTEXPR20
void
1004 detail::abort_fuzzing_if(size > 5000);
1005 const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
1006 size_t old_capacity = this->capacity();
1007 size_t new_capacity = old_capacity + old_capacity / 2;
1008 if (size > new_capacity)
1009 new_capacity = size;
1010 else if (new_capacity > max_size)
1011 new_capacity = size > max_size ? size : max_size;
1012 T *old_data = this->data();
1014 std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
1016 std::uninitialized_copy(old_data, old_data + this->size(),
1017 detail::make_checked(new_data, new_capacity));
1018 this->set(new_data, new_capacity);
1022 if (old_data != store_)
1023 alloc_.deallocate(old_data, old_capacity);
1028 template <
typename T,
size_t SIZE,
typename Allocator>
1034 FMT_API
bool write_console(std::FILE *f,
string_view text);
1043 using std::runtime_error::runtime_error;
1051 namespace detail_exported {
1052 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
1053 template <
typename Char,
size_t N>
struct fixed_string {
1054 constexpr fixed_string(
const Char (&str)[N]) {
1055 detail::copy_str<Char, const Char *, Char *>(
static_cast<const Char *
>(str),
1063 template <
typename Char,
size_t N>
1064 constexpr
auto compile_string_to_view(
const Char (&s)[N])
1068 return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
1070 template <
typename Char>
1071 constexpr
auto compile_string_to_view(detail::std_string_view<Char> s)
1079 basic_format_arg<format_context> value_;
1082 template <
typename T, FMT_ENABLE_IF(!detail::is_
float128<T>::value)>
1083 loc_value(T value) : value_(detail::make_arg<format_context>(value)) {}
1085 template <
typename T, FMT_ENABLE_IF(detail::is_
float128<T>::value)>
1088 template <
typename Visitor>
auto visit(Visitor &&vis) -> decltype(vis(0)) {
1089 return visit_format_arg(vis, value_);
1095 template <
typename Locale>
class format_facet :
public Locale::facet {
1097 std::string separator_;
1098 std::string grouping_;
1099 std::string decimal_point_;
1102 virtual auto do_put(appender out, loc_value val,
1103 const format_specs<> &specs)
const -> bool;
1106 static FMT_API
typename Locale::id id;
1108 explicit format_facet(Locale &loc);
1110 std::initializer_list<unsigned char> g = {3},
1111 std::string decimal_point =
".")
1112 : separator_(sep.data(), sep.size()),
1113 grouping_(
g.begin(),
g.end()),
1114 decimal_point_(decimal_point) {}
1116 auto put(appender out, loc_value val,
const format_specs<> &specs)
const
1118 return do_put(out, val, specs);
1122 FMT_BEGIN_DETAIL_NAMESPACE
1126 template <
typename T, FMT_ENABLE_IF(is_
signed<T>::value)>
1127 constexpr
auto is_negative(T value) ->
bool {
1130 template <
typename T, FMT_ENABLE_IF(!is_
signed<T>::value)>
1131 constexpr
auto is_negative(T) ->
bool {
1135 template <
typename T>
1136 FMT_CONSTEXPR
auto is_supported_floating_point(T) ->
bool {
1137 if (std::is_same<T, float>())
1138 return FMT_USE_FLOAT;
1139 if (std::is_same<T, double>())
1140 return FMT_USE_DOUBLE;
1141 if (std::is_same<T, long double>())
1142 return FMT_USE_LONG_DOUBLE;
1148 template <
typename T>
1149 using uint32_or_64_or_128_t =
1150 conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,
1152 conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
1153 template <
typename T>
1154 using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;
1156 #define FMT_POWERS_OF_10(factor) \
1157 factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
1158 (factor)*1000000, (factor)*10000000, (factor)*100000000, \
1162 constexpr
const char *digits2(
size_t value) {
1164 return &
"0001020304050607080910111213141516171819"
1165 "2021222324252627282930313233343536373839"
1166 "4041424344454647484950515253545556575859"
1167 "6061626364656667686970717273747576777879"
1168 "8081828384858687888990919293949596979899"[value * 2];
1172 template <
typename Char,
typename Sign> constexpr Char sign(Sign s) {
1173 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1174 static_assert(std::is_same<Sign, sign_t>::value,
"");
1176 return static_cast<Char
>(
"\0-+ "[s]);
1179 template <
typename T> FMT_CONSTEXPR
auto count_digits_fallback(T n) ->
int {
1198 FMT_CONSTEXPR
inline auto count_digits(uint128_opt n) ->
int {
1199 return count_digits_fallback(n);
1203 #ifdef FMT_BUILTIN_CLZLL
1206 inline auto do_count_digits(uint64_t n) ->
int {
1211 static constexpr uint8_t bsr2log10[] = {
1212 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1213 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1214 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1215 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1216 auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1217 static constexpr
const uint64_t zero_or_powers_of_10[] = {
1218 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1219 10000000000000000000ULL};
1220 return t - (n < zero_or_powers_of_10[t]);
1226 FMT_CONSTEXPR20
inline auto count_digits(uint64_t n) ->
int {
1227 #ifdef FMT_BUILTIN_CLZLL
1228 if (!is_constant_evaluated()) {
1229 return do_count_digits(n);
1232 return count_digits_fallback(n);
1236 template <
int BITS,
typename UInt>
1237 FMT_CONSTEXPR
auto count_digits(UInt n) ->
int {
1238 #ifdef FMT_BUILTIN_CLZ
1239 if (!is_constant_evaluated() && num_bits<UInt>() == 32)
1240 return (FMT_BUILTIN_CLZ(
static_cast<uint32_t
>(n) | 1) ^ 31) / BITS + 1;
1247 }
while ((m >>= BITS) != 0);
1252 #ifdef FMT_BUILTIN_CLZ
1255 FMT_INLINE
auto do_count_digits(uint32_t n) ->
int {
1258 #define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1259 static constexpr uint64_t table[] = {
1260 FMT_INC(0), FMT_INC(0), FMT_INC(0),
1261 FMT_INC(10), FMT_INC(10), FMT_INC(10),
1262 FMT_INC(100), FMT_INC(100), FMT_INC(100),
1263 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000),
1264 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000),
1265 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000),
1266 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000),
1267 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000),
1268 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000),
1269 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000),
1270 FMT_INC(1000000000), FMT_INC(1000000000)
1272 auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1273 return static_cast<int>((n + inc) >> 32);
1278 FMT_CONSTEXPR20
inline auto count_digits(uint32_t n) ->
int {
1279 #ifdef FMT_BUILTIN_CLZ
1280 if (!is_constant_evaluated()) {
1281 return do_count_digits(n);
1284 return count_digits_fallback(n);
1287 template <
typename Int> constexpr
auto digits10() noexcept ->
int {
1288 return std::numeric_limits<Int>::digits10;
1290 template <> constexpr
auto digits10<int128_opt>() noexcept ->
int {
return 38; }
1291 template <> constexpr
auto digits10<uint128_t>() noexcept ->
int {
return 38; }
1293 template <
typename Char>
struct thousands_sep_result {
1294 std::string grouping;
1298 template <
typename Char>
1299 FMT_API
auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
1300 template <
typename Char>
1301 inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {
1302 auto result = thousands_sep_impl<char>(loc);
1303 return {result.grouping, Char(result.thousands_sep)};
1306 inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
1307 return thousands_sep_impl<wchar_t>(loc);
1310 template <
typename Char>
1311 FMT_API
auto decimal_point_impl(locale_ref loc) -> Char;
1312 template <
typename Char>
inline auto decimal_point(locale_ref loc) -> Char {
1313 return Char(decimal_point_impl<char>(loc));
1315 template <>
inline auto decimal_point(locale_ref loc) ->
wchar_t {
1316 return decimal_point_impl<wchar_t>(loc);
1320 template <
typename Char>
auto equal2(
const Char *lhs,
const char *rhs) ->
bool {
1321 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1323 inline auto equal2(
const char *lhs,
const char *rhs) ->
bool {
1324 return memcmp(lhs, rhs, 2) == 0;
1328 template <
typename Char>
1329 FMT_CONSTEXPR20 FMT_INLINE
void copy2(Char *dst,
const char *src) {
1330 if (!is_constant_evaluated() &&
sizeof(Char) ==
sizeof(
char)) {
1331 memcpy(dst, src, 2);
1334 *dst++ =
static_cast<Char
>(*src++);
1335 *dst =
static_cast<Char
>(*src);
1338 template <
typename Iterator>
struct format_decimal_result {
1346 template <
typename Char,
typename UInt>
1347 FMT_CONSTEXPR20
auto format_decimal(Char *out, UInt value,
int size)
1348 -> format_decimal_result<Char *> {
1349 FMT_ASSERT(size >= count_digits(value),
"invalid digit count");
1352 while (value >= 100) {
1357 copy2(out, digits2(
static_cast<size_t>(value % 100)));
1361 *--out =
static_cast<Char
>(
'0' + value);
1365 copy2(out, digits2(
static_cast<size_t>(value)));
1369 template <
typename Char,
typename UInt,
typename Iterator,
1370 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1371 FMT_CONSTEXPR
inline auto format_decimal(Iterator out, UInt value,
int size)
1372 -> format_decimal_result<Iterator> {
1374 Char
buffer[digits10<UInt>() + 1] = {};
1375 auto end = format_decimal(
buffer, value, size).end;
1376 return {out, detail::copy_str_noinline<Char>(
buffer, end, out)};
1379 template <
unsigned BASE_BITS,
typename Char,
typename UInt>
1380 FMT_CONSTEXPR
auto format_uint(Char *
buffer, UInt value,
int num_digits,
1381 bool upper =
false) -> Char * {
1385 const char *digits = upper ?
"0123456789ABCDEF" :
"0123456789abcdef";
1386 unsigned digit =
static_cast<unsigned>(value & ((1 << BASE_BITS) - 1));
1387 *--
buffer =
static_cast<Char
>(
1388 BASE_BITS < 4 ? static_cast<char>(
'0' + digit) : digits[digit]);
1389 }
while ((value >>= BASE_BITS) != 0);
1393 template <
unsigned BASE_BITS,
typename Char,
typename It,
typename UInt>
1394 inline auto format_uint(It out, UInt value,
int num_digits,
bool upper =
false)
1396 if (
auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1397 format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1401 char buffer[num_bits<UInt>() / BASE_BITS + 1];
1402 format_uint<BASE_BITS>(
buffer, value, num_digits, upper);
1403 return detail::copy_str_noinline<Char>(
buffer,
buffer + num_digits, out);
1407 class utf8_to_utf16 {
1414 auto size() const ->
size_t {
return buffer_.size() - 1; }
1415 auto c_str() const -> const
wchar_t * {
return &buffer_[0]; }
1416 auto str() const -> std::wstring {
return {&buffer_[0], size()}; }
1420 inline uint128_fallback umul128(uint64_t x, uint64_t y) noexcept {
1422 auto p =
static_cast<uint128_opt
>(x) *
static_cast<uint128_opt
>(y);
1423 return {
static_cast<uint64_t
>(p >> 64),
static_cast<uint64_t
>(p)};
1424 #elif defined(_MSC_VER) && defined(_M_X64)
1425 auto result = uint128_fallback();
1426 result.lo_ = _umul128(x, y, &result.hi_);
1429 const uint64_t mask =
static_cast<uint64_t
>(max_value<uint32_t>());
1431 uint64_t a = x >> 32;
1432 uint64_t b = x & mask;
1433 uint64_t
c = y >> 32;
1434 uint64_t d = y & mask;
1436 uint64_t ac = a *
c;
1437 uint64_t bc = b *
c;
1438 uint64_t ad = a * d;
1439 uint64_t bd = b * d;
1441 uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
1443 return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
1444 (intermediate << 32) + (bd & mask)};
1448 namespace dragonbox {
1451 inline int floor_log10_pow2(
int e) noexcept {
1452 FMT_ASSERT(e <= 2620 && e >= -2620,
"too large exponent");
1453 static_assert((-1 >> 1) == -1,
"right shift is not arithmetic");
1454 return (e * 315653) >> 20;
1457 inline int floor_log2_pow10(
int e) noexcept {
1458 FMT_ASSERT(e <= 1233 && e >= -1233,
"too large exponent");
1459 return (e * 1741647) >> 19;
1463 inline uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept {
1465 auto p =
static_cast<uint128_opt
>(x) *
static_cast<uint128_opt
>(y);
1466 return static_cast<uint64_t
>(p >> 64);
1467 #elif defined(_MSC_VER) && defined(_M_X64)
1468 return __umulh(x, y);
1470 return umul128(x, y).high();
1476 inline uint128_fallback umul192_upper128(uint64_t x,
1477 uint128_fallback y) noexcept {
1478 uint128_fallback r = umul128(x, y.high());
1479 r += umul128_upper64(x, y.low());
1483 FMT_API uint128_fallback get_cached_power(
int k) noexcept;
1486 template <
typename T,
typename Enable =
void>
struct float_info;
1488 template <>
struct float_info<float> {
1489 using carrier_uint = uint32_t;
1490 static const int exponent_bits = 8;
1491 static const int kappa = 1;
1492 static const int big_divisor = 100;
1493 static const int small_divisor = 10;
1494 static const int min_k = -31;
1495 static const int max_k = 46;
1496 static const int shorter_interval_tie_lower_threshold = -35;
1497 static const int shorter_interval_tie_upper_threshold = -35;
1500 template <>
struct float_info<double> {
1501 using carrier_uint = uint64_t;
1502 static const int exponent_bits = 11;
1503 static const int kappa = 2;
1504 static const int big_divisor = 1000;
1505 static const int small_divisor = 100;
1506 static const int min_k = -292;
1507 static const int max_k = 341;
1508 static const int shorter_interval_tie_lower_threshold = -77;
1509 static const int shorter_interval_tie_upper_threshold = -77;
1513 template <
typename T>
1514 struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 ||
1515 std::numeric_limits<T>::digits == 113 ||
1516 is_float128<T>::value>> {
1517 using carrier_uint = detail::uint128_t;
1518 static const int exponent_bits = 15;
1522 template <
typename T>
1523 struct float_info<T, enable_if_t<is_double_double<T>::value>> {
1524 using carrier_uint = detail::uint128_t;
1527 template <
typename T>
struct decimal_fp {
1528 using significand_type =
typename float_info<T>::carrier_uint;
1529 significand_type significand;
1533 template <
typename T> FMT_API
auto to_decimal(T x) noexcept -> decimal_fp<T>;
1537 template <
typename Float> constexpr
bool has_implicit_bit() {
1539 return std::numeric_limits<Float>::digits != 64;
1544 template <
typename Float> constexpr
int num_significand_bits() {
1546 return is_float128<Float>() ? 112 :
1547 (std::numeric_limits<Float>::digits -
1548 (has_implicit_bit<Float>() ? 1 : 0));
1551 template <
typename Float>
1552 constexpr
auto exponent_mask() ->
1553 typename dragonbox::float_info<Float>::carrier_uint {
1554 using float_uint =
typename dragonbox::float_info<Float>::carrier_uint;
1555 return ((float_uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
1556 << num_significand_bits<Float>();
1558 template <
typename Float> constexpr
auto exponent_bias() ->
int {
1560 return is_float128<Float>() ? 16383 :
1561 std::numeric_limits<Float>::max_exponent - 1;
1565 template <
typename Char,
typename It>
1566 FMT_CONSTEXPR
auto write_exponent(
int exp, It it) -> It {
1567 FMT_ASSERT(-10000 < exp && exp < 10000,
"exponent out of range");
1569 *it++ =
static_cast<Char
>(
'-');
1572 *it++ =
static_cast<Char
>(
'+');
1575 const char *top = digits2(to_unsigned(exp / 100));
1577 *it++ =
static_cast<Char
>(top[0]);
1578 *it++ =
static_cast<Char
>(top[1]);
1581 const char *d = digits2(to_unsigned(exp));
1582 *it++ =
static_cast<Char
>(d[0]);
1583 *it++ =
static_cast<Char
>(d[1]);
1588 template <
typename F>
struct basic_fp {
1592 static constexpr
const int num_significand_bits =
1593 static_cast<int>(
sizeof(F) * num_bits<unsigned char>());
1595 constexpr basic_fp() :
f(0), e(0) {}
1596 constexpr basic_fp(uint64_t f_val,
int e_val) :
f(f_val), e(e_val) {}
1599 template <
typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
1602 template <
typename Float, FMT_ENABLE_IF(!is_
double_
double<Float>::value)>
1603 FMT_CONSTEXPR
auto assign(Float n) ->
bool {
1604 static_assert(std::numeric_limits<Float>::digits <= 113,
"unsupported FP");
1606 using carrier_uint =
typename dragonbox::float_info<Float>::carrier_uint;
1607 const auto num_float_significand_bits =
1608 detail::num_significand_bits<Float>();
1609 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
1610 const auto significand_mask = implicit_bit - 1;
1611 auto u = bit_cast<carrier_uint>(n);
1612 f =
static_cast<F
>(u & significand_mask);
1613 auto biased_e =
static_cast<int>((u & exponent_mask<Float>()) >>
1614 num_float_significand_bits);
1617 auto is_predecessor_closer =
f == 0 && biased_e > 1;
1620 else if (has_implicit_bit<Float>())
1621 f +=
static_cast<F
>(implicit_bit);
1622 e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
1623 if (!has_implicit_bit<Float>())
1625 return is_predecessor_closer;
1628 template <
typename Float, FMT_ENABLE_IF(is_
double_
double<Float>::value)>
1629 FMT_CONSTEXPR
auto assign(Float n) ->
bool {
1630 static_assert(std::numeric_limits<double>::is_iec559,
"unsupported FP");
1631 return assign(
static_cast<double>(n));
1635 using fp = basic_fp<unsigned long long>;
1638 template <
int SHIFT = 0,
typename F>
1639 FMT_CONSTEXPR basic_fp<F> normalize(basic_fp<F> value) {
1641 const auto implicit_bit = F(1) << num_significand_bits<double>();
1642 const auto shifted_implicit_bit = implicit_bit << SHIFT;
1643 while ((value.f & shifted_implicit_bit) == 0) {
1648 const auto offset = basic_fp<F>::num_significand_bits -
1649 num_significand_bits<double>() - SHIFT - 1;
1656 FMT_CONSTEXPR
inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
1658 auto product =
static_cast<__uint128_t
>(lhs) * rhs;
1659 auto f =
static_cast<uint64_t
>(
product >> 64);
1660 return (
static_cast<uint64_t
>(product) & (1ULL << 63)) != 0 ?
f + 1 :
f;
1663 uint64_t mask = (1ULL << 32) - 1;
1664 uint64_t a = lhs >> 32, b = lhs & mask;
1665 uint64_t
c = rhs >> 32, d = rhs & mask;
1666 uint64_t ac = a *
c, bc = b *
c, ad = a * d, bd = b * d;
1668 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
1669 return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
1673 FMT_CONSTEXPR
inline fp operator*(fp x, fp y) {
1674 return {multiply(x.f, y.f), x.e + y.e + 64};
1677 template <
typename T =
void>
struct basic_data {
1680 static constexpr uint64_t pow10_significands[87] = {
1681 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
1682 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
1683 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
1684 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
1685 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
1686 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
1687 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
1688 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
1689 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
1690 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
1691 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
1692 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
1693 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
1694 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
1695 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
1696 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
1697 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
1698 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
1699 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
1700 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
1701 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
1702 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
1703 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
1704 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
1705 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
1706 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
1707 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
1708 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
1709 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
1712 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1713 #pragma GCC diagnostic push
1714 #pragma GCC diagnostic ignored "-Wnarrowing"
1718 static constexpr int16_t pow10_exponents[87] = {
1719 -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
1720 -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
1721 -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
1722 -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
1723 -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
1724 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
1725 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
1726 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
1727 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1728 #pragma GCC diagnostic pop
1731 static constexpr uint64_t power_of_10_64[20] = {
1732 1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
1733 10000000000000000000ULL};
1738 static constexpr uint32_t fractional_part_rounding_thresholds[8] = {
1750 #if FMT_CPLUSPLUS < 201703L
1751 template <
typename T> constexpr uint64_t basic_data<T>::pow10_significands[];
1752 template <
typename T> constexpr int16_t basic_data<T>::pow10_exponents[];
1753 template <
typename T> constexpr uint64_t basic_data<T>::power_of_10_64[];
1754 template <
typename T>
1755 constexpr uint32_t basic_data<T>::fractional_part_rounding_thresholds[];
1759 struct data : basic_data<> {};
1763 FMT_CONSTEXPR
inline fp get_cached_power(
int min_exponent,
1764 int &pow10_exponent) {
1765 const int shift = 32;
1767 const int64_t significand = 0x4d104d427de7fbcc;
1768 int index =
static_cast<int>(
1769 ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
1770 ((int64_t(1) << shift) - 1))
1774 const int first_dec_exp = -348;
1776 const int dec_exp_step = 8;
1777 index = (index - first_dec_exp - 1) / dec_exp_step + 1;
1778 pow10_exponent = first_dec_exp + index * dec_exp_step;
1781 return {*(data::pow10_significands + index),
1782 *(data::pow10_exponents + index)};
1785 template <
typename T>
1786 using convert_float_result =
1787 conditional_t<std::is_same<T, float>::value ||
1788 std::numeric_limits<T>::digits ==
1789 std::numeric_limits<double>::digits,
1792 template <
typename T>
1793 constexpr
auto convert_float(T value) -> convert_float_result<T> {
1794 return static_cast<convert_float_result<T>
>(value);
1797 template <
typename OutputIt,
typename Char>
1798 FMT_NOINLINE FMT_CONSTEXPR
auto fill(OutputIt it,
size_t n,
1799 const fill_t<Char> &fill) -> OutputIt {
1800 auto fill_size = fill.size();
1802 return detail::fill_n(it, n, fill[0]);
1803 auto data = fill.data();
1804 for (
size_t i = 0; i < n; ++i)
1805 it = copy_str<Char>(data, data + fill_size, it);
1812 template <align::type align = align::left,
typename OutputIt,
typename Char,
1814 FMT_CONSTEXPR
auto write_padded(OutputIt out,
const format_specs<Char> &specs,
1815 size_t size,
size_t width, F &&f) -> OutputIt {
1816 static_assert(align == align::left || align == align::right,
"");
1817 unsigned spec_width = to_unsigned(specs.width);
1818 size_t padding = spec_width > width ? spec_width - width : 0;
1821 auto *shifts = align == align::left ?
"\x1f\x1f\x00\x01" :
"\x00\x1f\x00\x01";
1822 size_t left_padding = padding >> shifts[specs.align];
1823 size_t right_padding = padding - left_padding;
1824 auto it = reserve(out, size + padding * specs.fill.size());
1825 if (left_padding != 0)
1826 it = fill(it, left_padding, specs.fill);
1828 if (right_padding != 0)
1829 it = fill(it, right_padding, specs.fill);
1830 return base_iterator(out, it);
1833 template <align::type align = align::left,
typename OutputIt,
typename Char,
1835 constexpr
auto write_padded(OutputIt out,
const format_specs<Char> &specs,
1836 size_t size, F &&f) -> OutputIt {
1837 return write_padded<align>(out, specs, size, size, f);
1840 template <align::type align = align::left,
typename Char,
typename OutputIt>
1841 FMT_CONSTEXPR
auto write_bytes(OutputIt out,
string_view bytes,
1842 const format_specs<Char> &specs) -> OutputIt {
1843 return write_padded<align>(
1844 out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1845 const char *data = bytes.data();
1846 return copy_str<Char>(data, data + bytes.size(), it);
1850 template <
typename Char,
typename OutputIt,
typename UIntPtr>
1851 auto write_ptr(OutputIt out, UIntPtr value,
const format_specs<Char> *specs)
1853 int num_digits = count_digits<4>(value);
1854 auto size = to_unsigned(num_digits) + size_t(2);
1855 auto write = [=](reserve_iterator<OutputIt> it) {
1856 *it++ =
static_cast<Char
>(
'0');
1857 *it++ =
static_cast<Char
>(
'x');
1858 return format_uint<4, Char>(it, value, num_digits);
1860 return specs ? write_padded<align::right>(out, *specs, size, write) :
1861 base_iterator(out, write(reserve(out, size)));
1865 FMT_API
auto is_printable(uint32_t cp) -> bool;
1867 inline auto needs_escape(uint32_t cp) ->
bool {
1868 return cp < 0x20 || cp == 0x7f || cp ==
'"' || cp ==
'\\' ||
1872 template <
typename Char>
struct find_escape_result {
1878 template <
typename Char>
1879 using make_unsigned_char =
1880 typename conditional_t<std::is_integral<Char>::value,
1881 std::make_unsigned<Char>,
1882 type_identity<uint32_t>>::type;
1884 template <
typename Char>
1885 auto find_escape(
const Char *begin,
const Char *end)
1886 -> find_escape_result<Char> {
1887 for (; begin != end; ++begin) {
1888 uint32_t cp =
static_cast<make_unsigned_char<Char>
>(*begin);
1889 if (const_check(
sizeof(Char) == 1) && cp >= 0x80)
1891 if (needs_escape(cp))
1892 return {begin, begin + 1, cp};
1894 return {begin,
nullptr, 0};
1897 inline auto find_escape(
const char *begin,
const char *end)
1898 -> find_escape_result<char> {
1900 return find_escape<char>(begin, end);
1901 auto result = find_escape_result<char>{end,
nullptr, 0};
1902 for_each_codepoint(
string_view(begin, to_unsigned(end - begin)),
1904 if (needs_escape(cp)) {
1905 result = {sv.begin(), sv.end(), cp};
1913 #define FMT_STRING_IMPL(s, base, explicit) \
1917 struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \
1918 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1919 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1920 operator fmt::basic_string_view<char_type>() const { \
1921 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1924 return FMT_COMPILE_STRING(); \
1937 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1939 template <
size_t w
idth,
typename Char,
typename OutputIt>
1940 auto write_codepoint(OutputIt out,
char prefix, uint32_t cp) -> OutputIt {
1941 *out++ =
static_cast<Char
>(
'\\');
1942 *out++ =
static_cast<Char
>(prefix);
1944 fill_n(buf, width,
static_cast<Char
>(
'0'));
1945 format_uint<4>(buf, cp, width);
1946 return copy_str<Char>(buf, buf + width, out);
1949 template <
typename OutputIt,
typename Char>
1950 auto write_escaped_cp(OutputIt out,
const find_escape_result<Char> &escape)
1952 auto c =
static_cast<Char
>(escape.cp);
1953 switch (escape.cp) {
1955 *out++ =
static_cast<Char
>(
'\\');
1956 c =
static_cast<Char
>(
'n');
1959 *out++ =
static_cast<Char
>(
'\\');
1960 c =
static_cast<Char
>(
'r');
1963 *out++ =
static_cast<Char
>(
'\\');
1964 c =
static_cast<Char
>(
't');
1971 *out++ =
static_cast<Char
>(
'\\');
1975 if (escape.cp < 0x100) {
1976 return write_codepoint<2, Char>(out,
'x', escape.cp);
1978 if (escape.cp < 0x10000) {
1979 return write_codepoint<4, Char>(out,
'u', escape.cp);
1981 if (escape.cp < 0x110000) {
1982 return write_codepoint<8, Char>(out,
'U', escape.cp);
1986 escape.begin, to_unsigned(escape.end - escape.begin))) {
1987 out = write_codepoint<2, Char>(out,
'x',
1988 static_cast<uint32_t
>(escape_char) & 0xFF);
1996 template <
typename Char,
typename OutputIt>
1999 *out++ =
static_cast<Char
>(
'"');
2000 auto begin = str.begin(), end = str.end();
2002 auto escape = find_escape(begin, end);
2003 out = copy_str<Char>(begin, escape.begin, out);
2007 out = write_escaped_cp<OutputIt, Char>(out, escape);
2008 }
while (begin != end);
2009 *out++ =
static_cast<Char
>(
'"');
2013 template <
typename Char,
typename OutputIt>
2014 auto write_escaped_char(OutputIt out, Char v) -> OutputIt {
2015 *out++ =
static_cast<Char
>(
'\'');
2016 if ((needs_escape(
static_cast<uint32_t
>(v)) && v !=
static_cast<Char
>(
'"')) ||
2017 v ==
static_cast<Char
>(
'\'')) {
2018 out = write_escaped_cp(
2019 out, find_escape_result<Char>{&v, &v + 1,
static_cast<uint32_t
>(v)});
2023 *out++ =
static_cast<Char
>(
'\'');
2027 template <
typename Char,
typename OutputIt>
2028 FMT_CONSTEXPR
auto write_char(OutputIt out, Char value,
2029 const format_specs<Char> &specs) -> OutputIt {
2030 bool is_debug = specs.type == presentation_type::debug;
2031 return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
2033 return write_escaped_char(it, value);
2038 template <
typename Char,
typename OutputIt>
2039 FMT_CONSTEXPR
auto write(OutputIt out, Char value,
2040 const format_specs<Char> &specs, locale_ref loc = {})
2043 using unsigned_type =
2044 conditional_t<std::is_same<Char, char>::value,
unsigned char,
unsigned>;
2045 return check_char_specs(specs) ?
2046 write_char(out, value, specs) :
2047 write(out, static_cast<unsigned_type>(value), specs, loc);
2052 template <
typename Char>
struct write_int_data {
2056 FMT_CONSTEXPR write_int_data(
int num_digits,
unsigned prefix,
2057 const format_specs<Char> &specs)
2058 : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
2059 if (specs.align == align::numeric) {
2060 auto width = to_unsigned(specs.width);
2062 padding = width - size;
2065 }
else if (specs.precision > num_digits) {
2066 size = (prefix >> 24) + to_unsigned(specs.precision);
2067 padding = to_unsigned(specs.precision - num_digits);
2076 template <
typename OutputIt,
typename Char,
typename W>
2077 FMT_CONSTEXPR FMT_INLINE
auto
2078 write_int(OutputIt out,
int num_digits,
unsigned prefix,
2079 const format_specs<Char> &specs, W write_digits) -> OutputIt {
2081 if ((specs.width | (specs.precision + 1)) == 0) {
2082 auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
2084 for (
unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2085 *it++ =
static_cast<Char
>(p & 0xff);
2087 return base_iterator(out, write_digits(it));
2089 auto data = write_int_data<Char>(num_digits, prefix, specs);
2090 return write_padded<align::right>(
2091 out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
2092 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2093 *it++ = static_cast<Char>(p & 0xff);
2094 it = detail::fill_n(it, data.padding, static_cast<Char>(
'0'));
2095 return write_digits(it);
2099 template <
typename Char>
class digit_grouping {
2101 std::string grouping_;
2102 std::basic_string<Char> thousands_sep_;
2105 std::string::const_iterator group;
2108 next_state initial_state()
const {
return {grouping_.begin(), 0}; }
2111 int next(next_state &state)
const {
2112 if (thousands_sep_.empty())
2113 return max_value<int>();
2114 if (state.group == grouping_.end())
2115 return state.pos += grouping_.back();
2116 if (*state.group <= 0 || *state.group == max_value<char>())
2117 return max_value<int>();
2118 state.pos += *state.group++;
2123 explicit digit_grouping(locale_ref loc,
bool localized =
true) {
2126 auto sep = thousands_sep<Char>(loc);
2127 grouping_ = sep.grouping;
2128 if (sep.thousands_sep)
2129 thousands_sep_.assign(1, sep.thousands_sep);
2131 digit_grouping(std::string grouping, std::basic_string<Char> sep)
2132 : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {}
2134 bool has_separator()
const {
return !thousands_sep_.empty(); }
2136 int count_separators(
int num_digits)
const {
2138 auto state = initial_state();
2139 while (num_digits > next(state))
2145 template <
typename Out,
typename C>
2147 auto num_digits =
static_cast<int>(digits.
size());
2149 separators.push_back(0);
2150 auto state = initial_state();
2151 while (
int i = next(state)) {
2152 if (i >= num_digits)
2154 separators.push_back(i);
2156 for (
int i = 0, sep_index =
static_cast<int>(separators.size() - 1);
2157 i < num_digits; ++i) {
2158 if (num_digits - i == separators[sep_index]) {
2160 copy_str<Char>(thousands_sep_.data(),
2161 thousands_sep_.data() + thousands_sep_.size(), out);
2164 *out++ =
static_cast<Char
>(digits[to_unsigned(i)]);
2171 template <
typename OutputIt,
typename UInt,
typename Char>
2172 auto write_int(OutputIt out, UInt value,
unsigned prefix,
2173 const format_specs<Char> &specs,
2174 const digit_grouping<Char> &grouping) -> OutputIt {
2175 static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value,
"");
2176 int num_digits = count_digits(value);
2178 format_decimal(digits, value, num_digits);
2179 unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits +
2180 grouping.count_separators(num_digits));
2181 return write_padded<align::right>(
2182 out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
2184 char sign =
static_cast<char>(prefix);
2185 *it++ =
static_cast<Char
>(sign);
2187 return grouping.apply(it,
string_view(digits, to_unsigned(num_digits)));
2192 FMT_API
auto write_loc(appender out, loc_value value,
2193 const format_specs<> &specs, locale_ref loc) -> bool;
2194 template <
typename OutputIt,
typename Char>
2195 inline auto write_loc(OutputIt, loc_value,
const format_specs<Char> &,
2196 locale_ref) ->
bool {
2200 FMT_CONSTEXPR
inline void prefix_append(
unsigned &prefix,
unsigned value) {
2201 prefix |= prefix != 0 ? value << 8 : value;
2202 prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
2205 template <
typename UInt>
struct write_int_arg {
2210 template <
typename T>
2211 FMT_CONSTEXPR
auto make_write_int_arg(T value, sign_t sign)
2212 -> write_int_arg<uint32_or_64_or_128_t<T>> {
2214 auto abs_value =
static_cast<uint32_or_64_or_128_t<T>
>(value);
2215 if (is_negative(value)) {
2216 prefix = 0x01000000 |
'-';
2217 abs_value = 0 - abs_value;
2219 constexpr
const unsigned prefixes[4] = {0, 0, 0x1000000u |
'+',
2221 prefix = prefixes[sign];
2223 return {abs_value, prefix};
2226 template <
typename Char =
char>
struct loc_writer {
2227 buffer_appender<Char> out;
2228 const format_specs<Char> &specs;
2229 std::basic_string<Char> sep;
2230 std::string grouping;
2231 std::basic_string<Char> decimal_point;
2233 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
2234 auto operator()(T value) ->
bool {
2235 auto arg = make_write_int_arg(value, specs.sign);
2236 write_int(out,
static_cast<uint64_or_128_t<T>
>(arg.abs_value), arg.prefix,
2237 specs, digit_grouping<Char>(grouping, sep));
2241 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
2242 auto operator()(T) ->
bool {
2247 template <
typename Char,
typename OutputIt,
typename T>
2248 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out, write_int_arg<T> arg,
2249 const format_specs<Char> &specs,
2250 locale_ref) -> OutputIt {
2251 static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value,
"");
2252 auto abs_value = arg.abs_value;
2253 auto prefix = arg.prefix;
2254 switch (specs.type) {
2255 case presentation_type::none:
2256 case presentation_type::dec: {
2257 auto num_digits = count_digits(abs_value);
2259 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2260 return format_decimal<Char>(it, abs_value, num_digits).end;
2263 case presentation_type::hex_lower:
2264 case presentation_type::hex_upper: {
2265 bool upper = specs.type == presentation_type::hex_upper;
2267 prefix_append(prefix,
unsigned(upper ?
'X' :
'x') << 8 |
'0');
2268 int num_digits = count_digits<4>(abs_value);
2270 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2271 return format_uint<4, Char>(it, abs_value, num_digits, upper);
2274 case presentation_type::bin_lower:
2275 case presentation_type::bin_upper: {
2276 bool upper = specs.type == presentation_type::bin_upper;
2278 prefix_append(prefix,
unsigned(upper ?
'B' :
'b') << 8 |
'0');
2279 int num_digits = count_digits<1>(abs_value);
2280 return write_int(out, num_digits, prefix, specs,
2281 [=](reserve_iterator<OutputIt> it) {
2282 return format_uint<1, Char>(it, abs_value, num_digits);
2285 case presentation_type::oct: {
2286 int num_digits = count_digits<3>(abs_value);
2289 if (specs.alt && specs.precision <= num_digits && abs_value != 0)
2290 prefix_append(prefix,
'0');
2291 return write_int(out, num_digits, prefix, specs,
2292 [=](reserve_iterator<OutputIt> it) {
2293 return format_uint<3, Char>(it, abs_value, num_digits);
2296 case presentation_type::chr:
2297 return write_char(out,
static_cast<Char
>(abs_value), specs);
2299 throw_format_error(
"invalid format specifier");
2303 template <
typename Char,
typename OutputIt,
typename T>
2304 FMT_CONSTEXPR FMT_NOINLINE
auto
2305 write_int_noinline(OutputIt out, write_int_arg<T> arg,
2306 const format_specs<Char> &specs, locale_ref loc)
2308 return write_int(out, arg, specs, loc);
2310 template <
typename Char,
typename OutputIt,
typename T,
2311 FMT_ENABLE_IF(is_integral<T>::value &&
2312 !std::is_same<T, bool>::value &&
2313 std::is_same<OutputIt, buffer_appender<Char>>::value)>
2314 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out, T value,
2315 const format_specs<Char> &specs,
2316 locale_ref loc) -> OutputIt {
2317 if (specs.localized && write_loc(out, value, specs, loc))
2319 return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,
2323 template <
typename Char,
typename OutputIt,
typename T,
2324 FMT_ENABLE_IF(is_integral<T>::value &&
2325 !std::is_same<T, bool>::value &&
2326 !std::is_same<OutputIt, buffer_appender<Char>>::value)>
2327 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out, T value,
2328 const format_specs<Char> &specs,
2329 locale_ref loc) -> OutputIt {
2330 if (specs.localized && write_loc(out, value, specs, loc))
2332 return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
2337 class counting_iterator {
2342 using iterator_category = std::output_iterator_tag;
2343 using difference_type = std::ptrdiff_t;
2344 using pointer = void;
2345 using reference = void;
2346 FMT_UNCHECKED_ITERATOR(counting_iterator);
2349 template <
typename T> FMT_CONSTEXPR
void operator=(
const T &) {}
2352 FMT_CONSTEXPR counting_iterator() : count_(0) {}
2354 FMT_CONSTEXPR
size_t count()
const {
return count_; }
2356 FMT_CONSTEXPR counting_iterator &operator++() {
2360 FMT_CONSTEXPR counting_iterator operator++(
int) {
2366 FMT_CONSTEXPR
friend counting_iterator operator+(counting_iterator it,
2367 difference_type n) {
2368 it.count_ +=
static_cast<size_t>(n);
2372 FMT_CONSTEXPR value_type operator*()
const {
return {}; }
2375 template <
typename Char,
typename OutputIt>
2377 const format_specs<Char> &specs) -> OutputIt {
2378 auto data = s.
data();
2379 auto size = s.
size();
2380 if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
2381 size = code_point_index(s, to_unsigned(specs.precision));
2382 bool is_debug = specs.type == presentation_type::debug;
2384 if (specs.width != 0) {
2386 width = write_escaped_string(counting_iterator{}, s).count();
2390 return write_padded(out, specs, size, width,
2391 [=](reserve_iterator<OutputIt> it) {
2393 return write_escaped_string(it, s);
2394 return copy_str<Char>(data, data + size, it);
2397 template <
typename Char,
typename OutputIt>
2398 FMT_CONSTEXPR
auto write(OutputIt out,
2400 const format_specs<Char> &specs, locale_ref)
2402 return write(out, s, specs);
2404 template <
typename Char,
typename OutputIt>
2405 FMT_CONSTEXPR
auto write(OutputIt out,
const Char *s,
2406 const format_specs<Char> &specs, locale_ref)
2408 return specs.type != presentation_type::pointer ?
2410 write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
2413 template <
typename Char,
typename OutputIt,
typename T,
2414 FMT_ENABLE_IF(is_integral<T>::value &&
2415 !std::is_same<T, bool>::value &&
2416 !std::is_same<T, Char>::value)>
2417 FMT_CONSTEXPR
auto write(OutputIt out, T value) -> OutputIt {
2418 auto abs_value =
static_cast<uint32_or_64_or_128_t<T>
>(value);
2419 bool negative = is_negative(value);
2422 abs_value = ~abs_value + 1;
2423 int num_digits = count_digits(abs_value);
2424 auto size = (negative ? 1 : 0) +
static_cast<size_t>(num_digits);
2425 auto it = reserve(out, size);
2426 if (
auto ptr = to_pointer<Char>(it, size)) {
2428 *ptr++ =
static_cast<Char
>(
'-');
2429 format_decimal<Char>(ptr, abs_value, num_digits);
2433 *it++ =
static_cast<Char
>(
'-');
2434 it = format_decimal<Char>(it, abs_value, num_digits).end;
2435 return base_iterator(out, it);
2439 enum class float_format : unsigned char {
2446 struct float_specs {
2448 float_format format : 8;
2456 template <
typename ErrorHandler = error_handler,
typename Char>
2457 FMT_CONSTEXPR
auto parse_float_type_spec(
const format_specs<Char> &specs,
2458 ErrorHandler &&eh = {})
2460 auto result = float_specs();
2461 result.showpoint = specs.alt;
2462 result.locale = specs.localized;
2463 switch (specs.type) {
2464 case presentation_type::none:
2465 result.format = float_format::general;
2467 case presentation_type::general_upper:
2468 result.upper =
true;
2470 case presentation_type::general_lower:
2471 result.format = float_format::general;
2473 case presentation_type::exp_upper:
2474 result.upper =
true;
2476 case presentation_type::exp_lower:
2477 result.format = float_format::exp;
2478 result.showpoint |= specs.precision != 0;
2480 case presentation_type::fixed_upper:
2481 result.upper =
true;
2483 case presentation_type::fixed_lower:
2484 result.format = float_format::fixed;
2485 result.showpoint |= specs.precision != 0;
2487 case presentation_type::hexfloat_upper:
2488 result.upper =
true;
2490 case presentation_type::hexfloat_lower:
2491 result.format = float_format::hex;
2494 eh.on_error(
"invalid format specifier");
2500 template <
typename Char,
typename OutputIt>
2501 FMT_CONSTEXPR20
auto write_nonfinite(OutputIt out,
bool isnan,
2502 format_specs<Char> specs,
2503 const float_specs &fspecs) -> OutputIt {
2505 isnan ? (fspecs.upper ?
"NAN" :
"nan") : (fspecs.upper ?
"INF" :
"inf");
2506 constexpr
size_t str_size = 3;
2507 auto sign = fspecs.sign;
2508 auto size = str_size + (sign ? 1 : 0);
2510 const bool is_zero_fill =
2511 specs.fill.size() == 1 && *specs.fill.data() ==
static_cast<Char
>(
'0');
2513 specs.fill[0] =
static_cast<Char
>(
' ');
2514 return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
2516 *it++ = detail::sign<Char>(sign);
2517 return copy_str<Char>(str, str + str_size, it);
2522 struct big_decimal_fp {
2523 const char *significand;
2524 int significand_size;
2528 constexpr
auto get_significand_size(
const big_decimal_fp &f) ->
int {
2529 return f.significand_size;
2531 template <
typename T>
2532 inline auto get_significand_size(
const dragonbox::decimal_fp<T> &f) ->
int {
2533 return count_digits(
f.significand);
2536 template <
typename Char,
typename OutputIt>
2537 constexpr
auto write_significand(OutputIt out,
const char *significand,
2538 int significand_size) -> OutputIt {
2539 return copy_str<Char>(significand, significand + significand_size, out);
2541 template <
typename Char,
typename OutputIt,
typename UInt>
2542 inline auto write_significand(OutputIt out, UInt significand,
2543 int significand_size) -> OutputIt {
2544 return format_decimal<Char>(out, significand, significand_size).end;
2546 template <
typename Char,
typename OutputIt,
typename T,
typename Grouping>
2547 FMT_CONSTEXPR20
auto write_significand(OutputIt out, T significand,
2548 int significand_size,
int exponent,
2549 const Grouping &grouping) -> OutputIt {
2550 if (!grouping.has_separator()) {
2551 out = write_significand<Char>(out, significand, significand_size);
2552 return detail::fill_n(out, exponent,
static_cast<Char
>(
'0'));
2555 write_significand<char>(appender(
buffer), significand, significand_size);
2556 detail::fill_n(appender(
buffer), exponent,
'0');
2560 template <
typename Char,
typename UInt,
2561 FMT_ENABLE_IF(std::is_integral<UInt>::value)>
2562 inline auto write_significand(Char *out, UInt significand,
int significand_size,
2563 int integral_size, Char decimal_point) -> Char * {
2565 return format_decimal(out, significand, significand_size).end;
2566 out += significand_size + 1;
2568 int floating_size = significand_size - integral_size;
2569 for (
int i = floating_size / 2; i > 0; --i) {
2571 copy2(out, digits2(
static_cast<std::size_t
>(significand % 100)));
2574 if (floating_size % 2 != 0) {
2575 *--out =
static_cast<Char
>(
'0' + significand % 10);
2578 *--out = decimal_point;
2579 format_decimal(out - integral_size, significand, integral_size);
2583 template <
typename OutputIt,
typename UInt,
typename Char,
2584 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
2585 inline auto write_significand(OutputIt out, UInt significand,
2586 int significand_size,
int integral_size,
2587 Char decimal_point) -> OutputIt {
2589 Char
buffer[digits10<UInt>() + 2];
2590 auto end = write_significand(
buffer, significand, significand_size,
2591 integral_size, decimal_point);
2592 return detail::copy_str_noinline<Char>(
buffer, end, out);
2595 template <
typename OutputIt,
typename Char>
2596 FMT_CONSTEXPR
auto write_significand(OutputIt out,
const char *significand,
2597 int significand_size,
int integral_size,
2598 Char decimal_point) -> OutputIt {
2599 out = detail::copy_str_noinline<Char>(significand,
2600 significand + integral_size, out);
2603 *out++ = decimal_point;
2604 return detail::copy_str_noinline<Char>(significand + integral_size,
2605 significand + significand_size, out);
2608 template <
typename OutputIt,
typename Char,
typename T,
typename Grouping>
2609 FMT_CONSTEXPR20
auto write_significand(OutputIt out, T significand,
2610 int significand_size,
int integral_size,
2612 const Grouping &grouping) -> OutputIt {
2613 if (!grouping.has_separator()) {
2614 return write_significand(out, significand, significand_size, integral_size,
2618 write_significand(buffer_appender<Char>(
buffer), significand,
2619 significand_size, integral_size, decimal_point);
2622 return detail::copy_str_noinline<Char>(
buffer.
data() + integral_size,
2626 template <
typename OutputIt,
typename DecimalFP,
typename Char,
2627 typename Grouping = digit_grouping<Char>>
2628 FMT_CONSTEXPR20
auto do_write_float(OutputIt out,
const DecimalFP &f,
2629 const format_specs<Char> &specs,
2630 float_specs fspecs, locale_ref loc)
2632 auto significand =
f.significand;
2633 int significand_size = get_significand_size(f);
2634 const Char zero =
static_cast<Char
>(
'0');
2635 auto sign = fspecs.sign;
2636 size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
2637 using iterator = reserve_iterator<OutputIt>;
2639 Char decimal_point =
2640 fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>(
'.');
2642 int output_exp =
f.exponent + significand_size - 1;
2643 auto use_exp_format = [=]() {
2644 if (fspecs.format == float_format::exp)
2646 if (fspecs.format != float_format::general)
2650 const int exp_lower = -4, exp_upper = 16;
2651 return output_exp < exp_lower ||
2652 output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
2654 if (use_exp_format()) {
2656 if (fspecs.showpoint) {
2657 num_zeros = fspecs.precision - significand_size;
2660 size += to_unsigned(num_zeros);
2661 }
else if (significand_size == 1) {
2662 decimal_point = Char();
2664 auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
2666 if (abs_output_exp >= 100)
2667 exp_digits = abs_output_exp >= 1000 ? 4 : 3;
2669 size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
2670 char exp_char = fspecs.upper ?
'E' :
'e';
2671 auto write = [=](iterator it) {
2673 *it++ = detail::sign<Char>(sign);
2675 it = write_significand(it, significand, significand_size, 1,
2678 it = detail::fill_n(it, num_zeros, zero);
2679 *it++ =
static_cast<Char
>(exp_char);
2680 return write_exponent<Char>(output_exp, it);
2682 return specs.width > 0 ?
2683 write_padded<align::right>(out, specs, size, write) :
2684 base_iterator(out, write(reserve(out, size)));
2687 int exp =
f.exponent + significand_size;
2688 if (
f.exponent >= 0) {
2690 size += to_unsigned(
f.exponent);
2691 int num_zeros = fspecs.precision - exp;
2692 abort_fuzzing_if(num_zeros > 5000);
2693 if (fspecs.showpoint) {
2695 if (num_zeros <= 0 && fspecs.format != float_format::fixed)
2698 size += to_unsigned(num_zeros);
2700 auto grouping = Grouping(loc, fspecs.locale);
2701 size += to_unsigned(grouping.count_separators(exp));
2702 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2704 *it++ = detail::sign<Char>(sign);
2705 it = write_significand<Char>(it, significand, significand_size,
2706 f.exponent, grouping);
2707 if (!fspecs.showpoint)
2709 *it++ = decimal_point;
2710 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2712 }
else if (exp > 0) {
2714 int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
2715 size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
2716 auto grouping = Grouping(loc, fspecs.locale);
2717 size += to_unsigned(grouping.count_separators(exp));
2718 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2720 *it++ = detail::sign<Char>(sign);
2721 it = write_significand(it, significand, significand_size, exp,
2722 decimal_point, grouping);
2723 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2727 int num_zeros = -exp;
2728 if (significand_size == 0 && fspecs.precision >= 0 &&
2729 fspecs.precision < num_zeros) {
2730 num_zeros = fspecs.precision;
2732 bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
2733 size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
2734 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2736 *it++ = detail::sign<Char>(sign);
2740 *it++ = decimal_point;
2741 it = detail::fill_n(it, num_zeros, zero);
2742 return write_significand<Char>(it, significand, significand_size);
2746 template <
typename Char>
class fallback_digit_grouping {
2748 constexpr fallback_digit_grouping(locale_ref,
bool) {}
2750 constexpr
bool has_separator()
const {
return false; }
2752 constexpr
int count_separators(
int)
const {
return 0; }
2754 template <
typename Out,
typename C>
2760 template <
typename OutputIt,
typename DecimalFP,
typename Char>
2761 FMT_CONSTEXPR20
auto write_float(OutputIt out,
const DecimalFP &f,
2762 const format_specs<Char> &specs,
2763 float_specs fspecs, locale_ref loc)
2765 if (is_constant_evaluated()) {
2766 return do_write_float<OutputIt, DecimalFP, Char,
2767 fallback_digit_grouping<Char>>(out,
f, specs, fspecs,
2770 return do_write_float(out, f, specs, fspecs, loc);
2774 template <
typename T> constexpr
bool isnan(T value) {
2775 return !(value >= value);
2778 template <
typename T,
typename Enable =
void>
2779 struct has_isfinite : std::false_type {};
2781 template <
typename T>
2782 struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>>
2783 : std::true_type {};
2785 template <
typename T, FMT_ENABLE_IF(std::is_
floating_po
int<T>::value
2786 &&has_isfinite<T>::value)>
2787 FMT_CONSTEXPR20
bool isfinite(T value) {
2788 constexpr T inf = T(std::numeric_limits<double>::infinity());
2789 if (is_constant_evaluated())
2790 return !detail::isnan(value) && value < inf && value > -inf;
2791 return std::isfinite(value);
2793 template <
typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
2794 FMT_CONSTEXPR
bool isfinite(T value) {
2795 T inf = T(std::numeric_limits<double>::infinity());
2797 return !detail::isnan(value) && value < inf && value > -inf;
2800 template <
typename T, FMT_ENABLE_IF(is_
floating_po
int<T>::value)>
2801 FMT_INLINE FMT_CONSTEXPR
bool signbit(T value) {
2802 if (is_constant_evaluated()) {
2803 #ifdef __cpp_if_constexpr
2804 if constexpr (std::numeric_limits<double>::is_iec559) {
2805 auto bits = detail::bit_cast<uint64_t>(
static_cast<double>(value));
2806 return (bits >> (num_bits<uint64_t>() - 1)) != 0;
2810 return std::signbit(
static_cast<double>(value));
2813 enum class round_direction { unknown, up, down };
2819 FMT_CONSTEXPR
inline round_direction
2820 get_round_direction(uint64_t divisor, uint64_t remainder, uint64_t error) {
2821 FMT_ASSERT(remainder < divisor,
"");
2822 FMT_ASSERT(error < divisor,
"");
2823 FMT_ASSERT(error < divisor - error,
"");
2825 if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)
2826 return round_direction::down;
2828 if (remainder >= error &&
2829 remainder - error >= divisor - (remainder - error)) {
2830 return round_direction::up;
2832 return round_direction::unknown;
2843 struct gen_digits_handler {
2850 FMT_CONSTEXPR digits::result on_digit(
char digit, uint64_t divisor,
2851 uint64_t remainder, uint64_t error,
2853 FMT_ASSERT(remainder < divisor,
"");
2854 buf[size++] = digit;
2855 if (!integral && error >= remainder)
2856 return digits::error;
2857 if (size < precision)
2858 return digits::more;
2863 if (error >= divisor || error >= divisor - error)
2864 return digits::error;
2866 FMT_ASSERT(error == 1 && divisor > 2,
"");
2868 auto dir = get_round_direction(divisor, remainder, error);
2869 if (dir != round_direction::up)
2870 return dir == round_direction::down ? digits::done : digits::error;
2872 for (
int i = size - 1; i > 0 && buf[i] >
'9'; --i) {
2883 return digits::done;
2887 inline FMT_CONSTEXPR20
void adjust_precision(
int &precision,
int exp10) {
2890 if (exp10 > 0 && precision > max_value<int>() - exp10)
2898 FMT_INLINE FMT_CONSTEXPR20
auto grisu_gen_digits(fp value, uint64_t error,
2900 gen_digits_handler &handler)
2902 const fp one(1ULL << -value.e, value.e);
2906 auto integral =
static_cast<uint32_t
>(value.f >> -one.e);
2907 FMT_ASSERT(integral != 0,
"");
2908 FMT_ASSERT(integral == value.f >> -one.e,
"");
2910 uint64_t fractional = value.f & (one.f - 1);
2911 exp = count_digits(integral);
2913 if (handler.fixed) {
2914 adjust_precision(handler.precision, exp + handler.exp10);
2917 if (handler.precision <= 0) {
2918 if (handler.precision < 0)
2919 return digits::done;
2921 uint64_t divisor = data::power_of_10_64[exp - 1] << -one.e;
2922 auto dir = get_round_direction(divisor, value.f / 10, error * 10);
2923 if (dir == round_direction::unknown)
2924 return digits::error;
2925 handler.buf[handler.size++] = dir == round_direction::up ?
'1' :
'0';
2926 return digits::done;
2932 auto divmod_integral = [&](uint32_t divisor) {
2933 digit = integral / divisor;
2934 integral %= divisor;
2940 divmod_integral(1000000000);
2943 divmod_integral(100000000);
2946 divmod_integral(10000000);
2949 divmod_integral(1000000);
2952 divmod_integral(100000);
2955 divmod_integral(10000);
2958 divmod_integral(1000);
2961 divmod_integral(100);
2964 divmod_integral(10);
2971 FMT_ASSERT(
false,
"invalid number of digits");
2974 auto remainder = (
static_cast<uint64_t
>(integral) << -one.e) + fractional;
2975 auto result = handler.on_digit(
static_cast<char>(
'0' + digit),
2976 data::power_of_10_64[exp] << -one.e,
2977 remainder, error,
true);
2978 if (result != digits::more)
2985 char digit =
static_cast<char>(
'0' + (fractional >> -one.e));
2986 fractional &= one.f - 1;
2988 auto result = handler.on_digit(digit, one.f, fractional, error,
false);
2989 if (result != digits::more)
2998 using bigit = uint32_t;
2999 using double_bigit = uint64_t;
3000 enum { bigits_capacity = 32 };
3004 FMT_CONSTEXPR20 bigit operator[](
int index)
const {
3005 return bigits_[to_unsigned(index)];
3007 FMT_CONSTEXPR20 bigit &operator[](
int index) {
3008 return bigits_[to_unsigned(index)];
3011 static constexpr
const int bigit_bits = num_bits<bigit>();
3013 friend struct formatter<bigint>;
3015 FMT_CONSTEXPR20
void subtract_bigits(
int index, bigit other, bigit &borrow) {
3016 auto result =
static_cast<double_bigit
>((*this)[index]) - other - borrow;
3017 (*this)[index] =
static_cast<bigit
>(result);
3018 borrow =
static_cast<bigit
>(result >> (bigit_bits * 2 - 1));
3021 FMT_CONSTEXPR20
void remove_leading_zeros() {
3022 int num_bigits =
static_cast<int>(bigits_.size()) - 1;
3023 while (num_bigits > 0 && (*
this)[num_bigits] == 0)
3025 bigits_.
resize(to_unsigned(num_bigits + 1));
3029 FMT_CONSTEXPR20
void subtract_aligned(
const bigint &other) {
3030 FMT_ASSERT(other.exp_ >= exp_,
"unaligned bigints");
3031 FMT_ASSERT(
compare(*
this, other) >= 0,
"");
3033 int i = other.exp_ - exp_;
3034 for (
size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
3035 subtract_bigits(i, other.bigits_[j], borrow);
3037 subtract_bigits(i, 0, borrow);
3038 remove_leading_zeros();
3041 FMT_CONSTEXPR20
void multiply(uint32_t value) {
3042 const double_bigit wide_value = value;
3044 for (
size_t i = 0, n = bigits_.size(); i < n; ++i) {
3045 double_bigit result = bigits_[i] * wide_value + carry;
3046 bigits_[i] =
static_cast<bigit
>(result);
3047 carry =
static_cast<bigit
>(result >> bigit_bits);
3050 bigits_.push_back(carry);
3053 template <
typename UInt, FMT_ENABLE_IF(std::is_same<UInt, u
int64_t>::value ||
3054 std::is_same<UInt, u
int128_t>::value)>
3055 FMT_CONSTEXPR20
void multiply(UInt value) {
3057 conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>;
3058 const int shift = num_bits<half_uint>() - bigit_bits;
3059 const UInt lower =
static_cast<half_uint
>(value);
3060 const UInt upper = value >> num_bits<half_uint>();
3062 for (
size_t i = 0, n = bigits_.size(); i < n; ++i) {
3063 UInt result = lower * bigits_[i] +
static_cast<bigit
>(carry);
3064 carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
3065 (carry >> bigit_bits);
3066 bigits_[i] =
static_cast<bigit
>(result);
3068 while (carry != 0) {
3069 bigits_.push_back(
static_cast<bigit
>(carry));
3070 carry >>= bigit_bits;
3074 template <
typename UInt, FMT_ENABLE_IF(std::is_same<UInt, u
int64_t>::value ||
3075 std::is_same<UInt, u
int128_t>::value)>
3076 FMT_CONSTEXPR20
void assign(UInt n) {
3077 size_t num_bigits = 0;
3079 bigits_[num_bigits++] =
static_cast<bigit
>(n);
3082 bigits_.
resize(num_bigits);
3087 FMT_CONSTEXPR20 bigint() : exp_(0) {}
3088 explicit bigint(uint64_t n) { assign(n); }
3090 bigint(
const bigint &) =
delete;
3091 void operator=(
const bigint &) =
delete;
3093 FMT_CONSTEXPR20
void assign(
const bigint &other) {
3094 auto size = other.bigits_.size();
3096 auto data = other.bigits_.data();
3097 std::copy(data, data + size, make_checked(bigits_.data(), size));
3101 template <
typename Int> FMT_CONSTEXPR20
void operator=(Int n) {
3102 FMT_ASSERT(n > 0,
"");
3103 assign(uint64_or_128_t<Int>(n));
3106 FMT_CONSTEXPR20
int num_bigits()
const {
3107 return static_cast<int>(bigits_.size()) + exp_;
3110 FMT_NOINLINE FMT_CONSTEXPR20 bigint &operator<<=(
int shift) {
3111 FMT_ASSERT(shift >= 0,
"");
3112 exp_ += shift / bigit_bits;
3113 shift %= bigit_bits;
3117 for (
size_t i = 0, n = bigits_.size(); i < n; ++i) {
3118 bigit
c = bigits_[i] >> (bigit_bits - shift);
3119 bigits_[i] = (bigits_[i] << shift) + carry;
3123 bigits_.push_back(carry);
3127 template <
typename Int> FMT_CONSTEXPR20 bigint &operator*=(Int value) {
3128 FMT_ASSERT(value > 0,
"");
3129 multiply(uint32_or_64_or_128_t<Int>(value));
3133 friend FMT_CONSTEXPR20
int compare(
const bigint &lhs,
const bigint &rhs) {
3134 int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
3135 if (num_lhs_bigits != num_rhs_bigits)
3136 return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
3137 int i =
static_cast<int>(lhs.bigits_.size()) - 1;
3138 int j =
static_cast<int>(rhs.bigits_.size()) - 1;
3142 for (; i >= end; --i, --j) {
3143 bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
3144 if (lhs_bigit != rhs_bigit)
3145 return lhs_bigit > rhs_bigit ? 1 : -1;
3148 return i > j ? 1 : -1;
3153 friend FMT_CONSTEXPR20
int add_compare(
const bigint &lhs1,
const bigint &lhs2,
3154 const bigint &rhs) {
3155 auto minimum = [](
int a,
int b) {
return a < b ? a : b; };
3156 auto maximum = [](
int a,
int b) {
return a > b ? a : b; };
3157 int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits());
3158 int num_rhs_bigits = rhs.num_bigits();
3159 if (max_lhs_bigits + 1 < num_rhs_bigits)
3161 if (max_lhs_bigits > num_rhs_bigits)
3163 auto get_bigit = [](
const bigint &n,
int i) -> bigit {
3164 return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
3166 double_bigit borrow = 0;
3167 int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_);
3168 for (
int i = num_rhs_bigits - 1; i >= min_exp; --i) {
3170 static_cast<double_bigit
>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
3171 bigit rhs_bigit = get_bigit(rhs, i);
3172 if (sum > rhs_bigit + borrow)
3174 borrow = rhs_bigit + borrow - sum;
3177 borrow <<= bigit_bits;
3179 return borrow != 0 ? -1 : 0;
3183 FMT_CONSTEXPR20
void assign_pow10(
int exp) {
3184 FMT_ASSERT(exp >= 0,
"");
3189 while (exp >= bitmask)
3196 while (bitmask != 0) {
3198 if ((exp & bitmask) != 0)
3205 FMT_CONSTEXPR20
void square() {
3206 int num_bigits =
static_cast<int>(bigits_.size());
3207 int num_result_bigits = 2 * num_bigits;
3209 bigits_.
resize(to_unsigned(num_result_bigits));
3210 auto sum = uint128_t();
3211 for (
int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
3214 for (
int i = 0, j = bigit_index; j >= 0; ++i, --j) {
3216 sum +=
static_cast<double_bigit
>(n[i]) * n[j];
3218 (*this)[bigit_index] =
static_cast<bigit
>(sum);
3219 sum >>= num_bits<bigit>();
3222 for (
int bigit_index = num_bigits; bigit_index < num_result_bigits;
3224 for (
int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
3225 sum +=
static_cast<double_bigit
>(n[i++]) * n[j--];
3226 (*this)[bigit_index] =
static_cast<bigit
>(sum);
3227 sum >>= num_bits<bigit>();
3229 remove_leading_zeros();
3235 FMT_CONSTEXPR20
void align(
const bigint &other) {
3236 int exp_difference = exp_ - other.exp_;
3237 if (exp_difference <= 0)
3239 int num_bigits =
static_cast<int>(bigits_.size());
3240 bigits_.
resize(to_unsigned(num_bigits + exp_difference));
3241 for (
int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
3242 bigits_[j] = bigits_[i];
3243 std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
3244 exp_ -= exp_difference;
3249 FMT_CONSTEXPR20
int divmod_assign(
const bigint &divisor) {
3250 FMT_ASSERT(
this != &divisor,
"");
3251 if (
compare(*
this, divisor) < 0)
3253 FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0,
"");
3257 subtract_aligned(divisor);
3259 }
while (
compare(*
this, divisor) >= 0);
3266 predecessor_closer = 1,
3274 FMT_CONSTEXPR20
inline void format_dragon(basic_fp<uint128_t> value,
3275 unsigned flags,
int num_digits,
3282 bigint *upper =
nullptr;
3286 bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
3287 int shift = is_predecessor_closer ? 2 : 1;
3289 numerator = value.f;
3290 numerator <<= value.e + shift;
3293 if (is_predecessor_closer) {
3295 upper_store <<= value.e + 1;
3296 upper = &upper_store;
3298 denominator.assign_pow10(exp10);
3299 denominator <<= shift;
3300 }
else if (exp10 < 0) {
3301 numerator.assign_pow10(-exp10);
3302 lower.assign(numerator);
3303 if (is_predecessor_closer) {
3304 upper_store.assign(numerator);
3306 upper = &upper_store;
3308 numerator *= value.f;
3309 numerator <<= shift;
3311 denominator <<= shift - value.e;
3313 numerator = value.f;
3314 numerator <<= shift;
3315 denominator.assign_pow10(exp10);
3316 denominator <<= shift - value.e;
3318 if (is_predecessor_closer) {
3319 upper_store = 1ULL << 1;
3320 upper = &upper_store;
3323 int even =
static_cast<int>((value.f & 1) == 0);
3326 if ((flags & dragon::fixup) != 0) {
3327 if (add_compare(numerator, *upper, denominator) + even <= 0) {
3330 if (num_digits < 0) {
3332 if (upper != &lower)
3336 if ((flags & dragon::fixed) != 0)
3337 adjust_precision(num_digits, exp10 + 1);
3340 if (num_digits < 0) {
3343 char *data = buf.
data();
3345 int digit = numerator.divmod_assign(denominator);
3346 bool low =
compare(numerator, lower) - even < 0;
3348 bool high = add_compare(numerator, *upper, denominator) + even > 0;
3349 data[num_digits++] =
static_cast<char>(
'0' + digit);
3352 ++data[num_digits - 1];
3354 int result = add_compare(numerator, numerator, denominator);
3356 if (result > 0 || (result == 0 && (digit % 2) != 0))
3357 ++data[num_digits - 1];
3359 buf.try_resize(to_unsigned(num_digits));
3360 exp10 -= num_digits - 1;
3365 if (upper != &lower)
3370 exp10 -= num_digits - 1;
3371 if (num_digits == 0) {
3373 auto digit = add_compare(numerator, numerator, denominator) > 0 ?
'1' :
'0';
3374 buf.push_back(digit);
3377 buf.try_resize(to_unsigned(num_digits));
3378 for (
int i = 0; i < num_digits - 1; ++i) {
3379 int digit = numerator.divmod_assign(denominator);
3380 buf[i] =
static_cast<char>(
'0' + digit);
3383 int digit = numerator.divmod_assign(denominator);
3384 auto result = add_compare(numerator, numerator, denominator);
3385 if (result > 0 || (result == 0 && (digit % 2) != 0)) {
3387 const auto overflow =
'0' + 10;
3388 buf[num_digits - 1] = overflow;
3390 for (
int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
3394 if (buf[0] == overflow) {
3402 buf[num_digits - 1] =
static_cast<char>(
'0' + digit);
3406 template <
typename Float>
3407 FMT_CONSTEXPR20
void format_hexfloat(Float value,
int precision,
3411 static_assert(!std::is_same<Float, float>::value,
"");
3413 using info = dragonbox::float_info<Float>;
3416 using carrier_uint =
typename info::carrier_uint;
3418 constexpr
auto num_float_significand_bits =
3419 detail::num_significand_bits<Float>();
3421 basic_fp<carrier_uint>
f(value);
3422 f.e += num_float_significand_bits;
3423 if (!has_implicit_bit<Float>())
3426 constexpr
auto num_fraction_bits =
3427 num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0);
3428 constexpr
auto num_xdigits = (num_fraction_bits + 3) / 4;
3430 constexpr
auto leading_shift = ((num_xdigits - 1) * 4);
3431 const auto leading_mask = carrier_uint(0xF) << leading_shift;
3432 const auto leading_xdigit =
3433 static_cast<uint32_t
>((
f.f & leading_mask) >> leading_shift);
3434 if (leading_xdigit > 1)
3435 f.e -= (32 - countl_zero(leading_xdigit) - 1);
3437 int print_xdigits = num_xdigits - 1;
3438 if (precision >= 0 && print_xdigits > precision) {
3439 const int shift = ((print_xdigits - precision - 1) * 4);
3440 const auto mask = carrier_uint(0xF) << shift;
3441 const auto v =
static_cast<uint32_t
>((
f.f & mask) >> shift);
3444 const auto inc = carrier_uint(1) << (shift + 4);
3450 if (!has_implicit_bit<Float>()) {
3451 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
3452 if ((
f.f & implicit_bit) == implicit_bit) {
3458 print_xdigits = precision;
3461 char xdigits[num_bits<carrier_uint>() / 4];
3462 detail::fill_n(xdigits,
sizeof(xdigits),
'0');
3463 format_uint<4>(xdigits,
f.f, num_xdigits, specs.upper);
3466 while (print_xdigits > 0 && xdigits[print_xdigits] ==
'0')
3470 buf.push_back(specs.upper ?
'X' :
'x');
3471 buf.push_back(xdigits[0]);
3472 if (specs.showpoint || print_xdigits > 0 || print_xdigits < precision)
3474 buf.
append(xdigits + 1, xdigits + 1 + print_xdigits);
3475 for (; print_xdigits < precision; ++print_xdigits)
3478 buf.push_back(specs.upper ?
'P' :
'p');
3483 abs_e =
static_cast<uint32_t
>(-
f.e);
3486 abs_e =
static_cast<uint32_t
>(
f.e);
3488 format_decimal<char>(appender(buf), abs_e, detail::count_digits(abs_e));
3491 template <
typename Float>
3492 FMT_CONSTEXPR20
auto format_float(Float value,
int precision, float_specs specs,
3495 static_assert(!std::is_same<Float, float>::value,
"");
3496 FMT_ASSERT(value >= 0,
"value is negative");
3497 auto converted_value = convert_float(value);
3499 const bool fixed = specs.format == float_format::fixed;
3501 if (precision <= 0 || !fixed) {
3505 buf.try_resize(to_unsigned(precision));
3506 fill_n(buf.
data(), precision,
'0');
3511 bool use_dragon =
true;
3512 unsigned dragon_flags = 0;
3513 if (!is_fast_float<Float>()) {
3514 const auto inv_log2_10 = 0.3010299956639812;
3515 using info = dragonbox::float_info<decltype(converted_value)>;
3516 const auto f = basic_fp<typename info::carrier_uint>(converted_value);
3521 exp =
static_cast<int>(
3522 std::ceil((
f.e + count_digits<1>(
f.f) - 1) * inv_log2_10 - 1e-10));
3523 dragon_flags = dragon::fixup;
3524 }
else if (!is_constant_evaluated() && precision < 0) {
3526 if (specs.binary32) {
3527 auto dec = dragonbox::to_decimal(
static_cast<float>(value));
3528 write<char>(buffer_appender<char>(buf), dec.significand);
3529 return dec.exponent;
3531 auto dec = dragonbox::to_decimal(
static_cast<double>(value));
3532 write<char>(buffer_appender<char>(buf), dec.significand);
3533 return dec.exponent;
3534 }
else if (is_constant_evaluated()) {
3537 const int min_exp = -60;
3538 int cached_exp10 = 0;
3539 fp normalized = normalize(fp(converted_value));
3540 const auto cached_pow = get_cached_power(
3541 min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
3542 normalized = normalized * cached_pow;
3543 gen_digits_handler handler{buf.
data(), 0, precision, -cached_exp10, fixed};
3544 if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
3545 !is_constant_evaluated()) {
3546 exp += handler.exp10;
3547 buf.try_resize(to_unsigned(handler.size));
3550 exp += handler.size - cached_exp10 - 1;
3551 precision = handler.precision;
3555 using info = dragonbox::float_info<double>;
3556 auto br = bit_cast<uint64_t>(
static_cast<double>(value));
3558 const uint64_t significand_mask =
3559 (
static_cast<uint64_t
>(1) << num_significand_bits<double>()) - 1;
3560 uint64_t significand = (br & significand_mask);
3561 int exponent =
static_cast<int>((br & exponent_mask<double>()) >>
3562 num_significand_bits<double>());
3564 if (exponent != 0) {
3565 exponent -= exponent_bias<double>() + num_significand_bits<double>();
3567 (
static_cast<uint64_t
>(1) << num_significand_bits<double>());
3571 FMT_ASSERT(significand != 0,
"zeros should not appear hear");
3572 int shift = countl_zero(significand);
3573 FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(),
3575 shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2);
3576 exponent = (std::numeric_limits<double>::min_exponent -
3577 num_significand_bits<double>()) -
3579 significand <<= shift;
3584 const int k = info::kappa - dragonbox::floor_log10_pow2(exponent);
3586 const int beta = exponent + dragonbox::floor_log2_pow10(k);
3587 uint64_t first_segment;
3588 bool has_more_segments;
3589 int digits_in_the_first_segment;
3591 const auto r = dragonbox::umul192_upper128(
3592 significand << beta, dragonbox::get_cached_power(k));
3593 first_segment = r.high();
3594 has_more_segments = r.low() != 0;
3597 if (first_segment >= 1000000000000000000ULL) {
3598 digits_in_the_first_segment = 19;
3602 digits_in_the_first_segment = 18;
3603 first_segment *= 10;
3609 adjust_precision(precision, exp + digits_in_the_first_segment);
3614 if (digits_in_the_first_segment > precision) {
3617 if (precision <= 0) {
3618 exp += digits_in_the_first_segment;
3620 if (precision < 0) {
3626 if ((first_segment |
static_cast<uint64_t
>(has_more_segments)) >
3627 5000000000000000000ULL) {
3635 exp += digits_in_the_first_segment - precision;
3644 const uint32_t first_subsegment =
static_cast<uint32_t
>(
3645 dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >>
3647 const uint64_t second_third_subsegments =
3648 first_segment - first_subsegment * 10000000000ULL;
3652 bool should_round_up;
3653 int number_of_digits_to_print = precision > 9 ? 9 : precision;
3656 auto print_subsegment = [&](uint32_t subsegment,
char *
buffer) {
3657 int number_of_digits_printed = 0;
3660 if ((number_of_digits_to_print & 1) != 0) {
3666 prod = ((subsegment *
static_cast<uint64_t
>(720575941)) >> 24) + 1;
3667 digits =
static_cast<uint32_t
>(prod >> 32);
3668 *
buffer =
static_cast<char>(
'0' + digits);
3669 number_of_digits_printed++;
3679 prod = ((subsegment *
static_cast<uint64_t
>(450359963)) >> 20) + 1;
3680 digits =
static_cast<uint32_t
>(prod >> 32);
3681 copy2(
buffer, digits2(digits));
3682 number_of_digits_printed += 2;
3686 while (number_of_digits_printed < number_of_digits_to_print) {
3687 prod =
static_cast<uint32_t
>(prod) *
static_cast<uint64_t
>(100);
3688 digits =
static_cast<uint32_t
>(prod >> 32);
3689 copy2(
buffer + number_of_digits_printed, digits2(digits));
3690 number_of_digits_printed += 2;
3695 print_subsegment(first_subsegment, buf.
data());
3699 if (precision <= 9) {
3713 if (precision < 9) {
3714 uint32_t fractional_part =
static_cast<uint32_t
>(prod);
3715 should_round_up = fractional_part >=
3716 data::fractional_part_rounding_thresholds
3717 [8 - number_of_digits_to_print] ||
3718 ((fractional_part >> 31) &
3719 ((digits & 1) | (second_third_subsegments != 0) |
3720 has_more_segments)) != 0;
3728 should_round_up = second_third_subsegments > 5000000000ULL ||
3729 (second_third_subsegments == 5000000000ULL &&
3730 ((digits & 1) != 0 || has_more_segments));
3739 const uint32_t second_subsegment =
3740 static_cast<uint32_t
>(dragonbox::umul128_upper64(
3741 second_third_subsegments, 1844674407370955162ULL));
3742 const uint32_t third_subsegment =
3743 static_cast<uint32_t
>(second_third_subsegments) -
3744 second_subsegment * 10;
3746 number_of_digits_to_print = precision - 9;
3747 print_subsegment(second_subsegment, buf.
data() + 9);
3750 if (precision < 18) {
3754 uint32_t fractional_part =
static_cast<uint32_t
>(prod);
3755 should_round_up = fractional_part >=
3756 data::fractional_part_rounding_thresholds
3757 [8 - number_of_digits_to_print] ||
3758 ((fractional_part >> 31) &
3759 ((digits & 1) | (third_subsegment != 0) |
3760 has_more_segments)) != 0;
3767 should_round_up = third_subsegment > 5 ||
3768 (third_subsegment == 5 &&
3769 ((digits & 1) != 0 || has_more_segments));
3774 if (should_round_up) {
3775 ++buf[precision - 1];
3776 for (
int i = precision - 1; i > 0 && buf[i] >
'9'; --i) {
3783 buf[precision++] =
'0';
3788 buf.try_resize(to_unsigned(precision));
3793 exp += digits_in_the_first_segment - 1;
3797 auto f = basic_fp<uint128_t>();
3798 bool is_predecessor_closer = specs.binary32 ?
3799 f.assign(
static_cast<float>(value)) :
3800 f.assign(converted_value);
3801 if (is_predecessor_closer)
3802 dragon_flags |= dragon::predecessor_closer;
3804 dragon_flags |= dragon::fixed;
3807 const int max_double_digits = 767;
3808 if (precision > max_double_digits)
3809 precision = max_double_digits;
3810 format_dragon(f, dragon_flags, precision, buf, exp);
3812 if (!fixed && !specs.showpoint) {
3814 auto num_digits = buf.size();
3815 while (num_digits > 0 && buf[num_digits - 1] ==
'0') {
3819 buf.try_resize(num_digits);
3823 template <
typename Char,
typename OutputIt,
typename T>
3824 FMT_CONSTEXPR20
auto write_float(OutputIt out, T value,
3825 format_specs<Char> specs, locale_ref loc)
3827 float_specs fspecs = parse_float_type_spec(specs);
3828 fspecs.sign = specs.sign;
3829 if (detail::signbit(value)) {
3830 fspecs.sign = sign::minus;
3832 }
else if (fspecs.sign == sign::minus) {
3833 fspecs.sign = sign::none;
3836 if (!detail::isfinite(value))
3837 return write_nonfinite(out, detail::isnan(value), specs, fspecs);
3839 if (specs.align == align::numeric && fspecs.sign) {
3840 auto it = reserve(out, 1);
3841 *it++ = detail::sign<Char>(fspecs.sign);
3842 out = base_iterator(out, it);
3843 fspecs.sign = sign::none;
3844 if (specs.width != 0)
3849 if (fspecs.format == float_format::hex) {
3851 buffer.push_back(detail::sign<char>(fspecs.sign));
3852 format_hexfloat(convert_float(value), specs.precision, fspecs,
buffer);
3857 specs.precision >= 0 || specs.type == presentation_type::none ?
3860 if (fspecs.format == float_format::exp) {
3861 if (precision == max_value<int>())
3862 throw_format_error(
"number is too big");
3865 }
else if (fspecs.format != float_format::fixed && precision == 0) {
3868 if (const_check(std::is_same<T, float>()))
3869 fspecs.binary32 =
true;
3870 int exp = format_float(convert_float(value), precision, fspecs,
buffer);
3871 fspecs.precision = precision;
3873 return write_float(out, f, specs, fspecs, loc);
3876 template <
typename Char,
typename OutputIt,
typename T,
3877 FMT_ENABLE_IF(is_floating_point<T>::value)>
3878 FMT_CONSTEXPR20
auto write(OutputIt out, T value, format_specs<Char> specs,
3879 locale_ref loc = {}) -> OutputIt {
3880 if (const_check(!is_supported_floating_point(value)))
3882 return specs.localized && write_loc(out, value, specs, loc) ?
3884 write_float(out, value, specs, loc);
3887 template <
typename Char,
typename OutputIt,
typename T,
3888 FMT_ENABLE_IF(is_fast_float<T>::value)>
3889 FMT_CONSTEXPR20
auto write(OutputIt out, T value) -> OutputIt {
3890 if (is_constant_evaluated())
3891 return write(out, value, format_specs<Char>());
3892 if (const_check(!is_supported_floating_point(value)))
3895 auto fspecs = float_specs();
3896 if (detail::signbit(value)) {
3897 fspecs.sign = sign::minus;
3901 constexpr
auto specs = format_specs<Char>();
3902 using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
3903 using floaty_uint =
typename dragonbox::float_info<floaty>::carrier_uint;
3904 floaty_uint mask = exponent_mask<floaty>();
3905 if ((bit_cast<floaty_uint>(value) & mask) == mask)
3906 return write_nonfinite(out, std::isnan(value), specs, fspecs);
3908 auto dec = dragonbox::to_decimal(
static_cast<floaty
>(value));
3909 return write_float(out, dec, specs, fspecs, {});
3912 template <
typename Char,
typename OutputIt,
typename T,
3913 FMT_ENABLE_IF(is_floating_point<T>::value &&
3914 !is_fast_float<T>::value)>
3915 inline auto write(OutputIt out, T value) -> OutputIt {
3916 return write(out, value, format_specs<Char>());
3919 template <
typename Char,
typename OutputIt>
3920 auto write(OutputIt out, monostate, format_specs<Char> = {}, locale_ref = {})
3922 FMT_ASSERT(
false,
"");
3926 template <
typename Char,
typename OutputIt>
3929 auto it = reserve(out, value.size());
3930 it = copy_str_noinline<Char>(value.begin(), value.end(), it);
3931 return base_iterator(out, it);
3934 template <
typename Char,
typename OutputIt,
typename T,
3935 FMT_ENABLE_IF(is_string<T>::value)>
3936 constexpr
auto write(OutputIt out,
const T &value) -> OutputIt {
3937 return write<Char>(out, to_string_view(value));
3942 typename Char,
typename OutputIt,
typename T,
3944 std::is_enum<T>::value && !std::is_same<T, Char>::value &&
3945 mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=
3947 FMT_ENABLE_IF(check)>
3948 FMT_CONSTEXPR
auto write(OutputIt out, T value) -> OutputIt {
3949 return write<Char>(out,
static_cast<underlying_t<T>
>(value));
3952 template <
typename Char,
typename OutputIt,
typename T,
3953 FMT_ENABLE_IF(std::is_same<T, bool>::value)>
3954 FMT_CONSTEXPR
auto write(OutputIt out, T value,
3955 const format_specs<Char> &specs = {}, locale_ref = {})
3957 return specs.type != presentation_type::none &&
3958 specs.type != presentation_type::string ?
3959 write(out, value ? 1 : 0, specs, {}) :
3960 write_bytes(out, value ?
"true" :
"false", specs);
3963 template <
typename Char,
typename OutputIt>
3964 FMT_CONSTEXPR
auto write(OutputIt out, Char value) -> OutputIt {
3965 auto it = reserve(out, 1);
3967 return base_iterator(out, it);
3970 template <
typename Char,
typename OutputIt>
3971 FMT_CONSTEXPR_CHAR_TRAITS
auto write(OutputIt out,
const Char *value)
3975 throw_format_error(
"string pointer is null");
3979 template <
typename Char,
typename OutputIt,
typename T,
3980 FMT_ENABLE_IF(std::is_same<T, void>::value)>
3981 auto write(OutputIt out,
const T *value,
const format_specs<Char> &specs = {},
3982 locale_ref = {}) -> OutputIt {
3983 return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
3987 template <
typename Char,
typename OutputIt,
typename T,
3988 typename Context = basic_format_context<OutputIt, Char>>
3989 FMT_CONSTEXPR
auto write(OutputIt out,
const T &value) -> enable_if_t<
3990 std::is_class<T>::value && !is_string<T>::value &&
3991 !is_floating_point<T>::value && !std::is_same<T, Char>::value &&
3992 !std::is_same<T, remove_cvref_t<decltype(arg_mapper<Context>().map(
3995 return write<Char>(out, arg_mapper<Context>().map(value));
3998 template <
typename Char,
typename OutputIt,
typename T,
3999 typename Context = basic_format_context<OutputIt, Char>>
4000 FMT_CONSTEXPR
auto write(OutputIt out,
const T &value)
4001 -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,
4003 using formatter_type =
4004 conditional_t<has_formatter<T, Context>::value,
4005 typename Context::template formatter_type<T>,
4006 fallback_formatter<T, Char>>;
4007 auto ctx = Context(out, {}, {});
4008 return formatter_type().format(value, ctx);
4013 template <
typename Char>
struct default_arg_formatter {
4014 using iterator = buffer_appender<Char>;
4015 using context = buffer_context<Char>;
4021 template <
typename T>
auto operator()(T value) -> iterator {
4022 return write<Char>(out, value);
4024 auto operator()(
typename basic_format_arg<context>::handle h) -> iterator {
4026 context format_ctx(out, args, loc);
4027 h.format(parse_ctx, format_ctx);
4028 return format_ctx.out();
4032 template <
typename Char>
struct arg_formatter {
4033 using iterator = buffer_appender<Char>;
4034 using context = buffer_context<Char>;
4037 const format_specs<Char> &specs;
4040 template <
typename T>
4041 FMT_CONSTEXPR FMT_INLINE
auto operator()(T value) -> iterator {
4042 return detail::write(out, value, specs, locale);
4044 auto operator()(
typename basic_format_arg<context>::handle) -> iterator {
4051 template <
typename Char>
struct custom_formatter {
4053 buffer_context<Char> &ctx;
4056 operator()(
typename basic_format_arg<buffer_context<Char>>::handle h)
const {
4057 h.format(parse_ctx, ctx);
4059 template <
typename T>
void operator()(T)
const {}
4062 template <
typename ErrorHandler>
class width_checker {
4064 explicit FMT_CONSTEXPR width_checker(ErrorHandler &eh) : handler_(eh) {}
4066 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
4067 FMT_CONSTEXPR
auto operator()(T value) ->
unsigned long long {
4068 if (is_negative(value))
4069 handler_.on_error(
"negative width");
4070 return static_cast<unsigned long long>(value);
4073 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
4074 FMT_CONSTEXPR
auto operator()(T) ->
unsigned long long {
4075 handler_.on_error(
"width is not integer");
4080 ErrorHandler &handler_;
4083 template <
typename ErrorHandler>
class precision_checker {
4085 explicit FMT_CONSTEXPR precision_checker(ErrorHandler &eh) : handler_(eh) {}
4087 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
4088 FMT_CONSTEXPR
auto operator()(T value) ->
unsigned long long {
4089 if (is_negative(value))
4090 handler_.on_error(
"negative precision");
4091 return static_cast<unsigned long long>(value);
4094 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
4095 FMT_CONSTEXPR
auto operator()(T) ->
unsigned long long {
4096 handler_.on_error(
"precision is not integer");
4101 ErrorHandler &handler_;
4104 template <
template <
typename>
class Handler,
typename FormatArg,
4105 typename ErrorHandler>
4106 FMT_CONSTEXPR
auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) ->
int {
4107 unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
4108 if (value > to_unsigned(max_value<int>()))
4109 eh.on_error(
"number is too big");
4110 return static_cast<int>(value);
4113 template <
typename Context,
typename ID>
4114 FMT_CONSTEXPR
auto get_arg(Context &ctx, ID
id) ->
4115 typename Context::format_arg {
4116 auto arg = ctx.arg(
id);
4118 ctx.on_error(
"argument not found");
4122 template <
template <
typename>
class Handler,
typename Context>
4123 FMT_CONSTEXPR
void handle_dynamic_spec(
int &value,
4124 arg_ref<typename Context::char_type> ref,
4127 case arg_id_kind::none:
4129 case arg_id_kind::index:
4130 value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.index),
4131 ctx.error_handler());
4133 case arg_id_kind::name:
4134 value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.name),
4135 ctx.error_handler());
4140 #if FMT_USE_USER_DEFINED_LITERALS
4141 template <
typename Char>
struct udl_formatter {
4144 template <
typename... T>
4145 auto operator()(T &&...args)
const -> std::basic_string<Char> {
4146 return vformat(str, fmt::make_format_args<buffer_context<Char>>(args...));
4150 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
4151 template <
typename T,
typename Char,
size_t N,
4152 fmt::detail_exported::fixed_string<Char, N> Str>
4153 struct statically_named_arg : view {
4154 static constexpr
auto name = Str.data;
4157 statically_named_arg(
const T &v) : value(v) {}
4160 template <
typename T,
typename Char,
size_t N,
4161 fmt::detail_exported::fixed_string<Char, N> Str>
4162 struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
4164 template <
typename T,
typename Char,
size_t N,
4165 fmt::detail_exported::fixed_string<Char, N> Str>
4166 struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
4167 : std::true_type {};
4169 template <
typename Char,
size_t N,
4170 fmt::detail_exported::fixed_string<Char, N> Str>
4172 template <
typename T>
auto operator=(T &&value)
const {
4173 return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
4177 template <
typename Char>
struct udl_arg {
4180 template <
typename T>
auto operator=(T &&value)
const -> named_arg<Char, T> {
4181 return {str, std::forward<T>(value)};
4187 template <
typename Locale,
typename Char>
4190 -> std::basic_string<Char> {
4192 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4193 return {buf.data(), buf.size()};
4196 using format_func = void (*)(detail::buffer<char> &, int,
const char *);
4198 FMT_API
void format_error_code(
buffer<char> &out,
int error_code,
4201 FMT_API
void report_error(format_func func,
int error_code,
4202 const char *message) noexcept;
4203 FMT_END_DETAIL_NAMESPACE
4205 FMT_API
auto vsystem_error(
int error_code,
string_view format_str,
4225 template <
typename... T>
4227 -> std::system_error {
4228 return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
4247 FMT_API
void format_system_error(detail::buffer<char> &out,
int error_code,
4248 const char *message) noexcept;
4252 FMT_API
void report_system_error(
int error_code,
const char *message) noexcept;
4259 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
4260 mutable char buffer_[buffer_size];
4263 template <
typename UInt>
auto format_unsigned(UInt value) ->
char * {
4264 auto n =
static_cast<detail::uint32_or_64_or_128_t<UInt>
>(value);
4265 return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
4268 template <
typename Int>
auto format_signed(Int value) ->
char * {
4269 auto abs_value =
static_cast<detail::uint32_or_64_or_128_t<Int>
>(value);
4270 bool negative = value < 0;
4272 abs_value = 0 - abs_value;
4273 auto begin = format_unsigned(abs_value);
4280 explicit format_int(
int value) : str_(format_signed(value)) {}
4281 explicit format_int(
long value) : str_(format_signed(value)) {}
4282 explicit format_int(
long long value) : str_(format_signed(value)) {}
4283 explicit format_int(
unsigned value) : str_(format_unsigned(value)) {}
4284 explicit format_int(
unsigned long value) : str_(format_unsigned(value)) {}
4285 explicit format_int(
unsigned long long value)
4286 : str_(format_unsigned(value)) {}
4290 return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
4297 auto data() const -> const
char * {
return str_; }
4304 buffer_[buffer_size - 1] =
'\0';
4313 auto str() const -> std::
string {
return std::string(str_,
size()); }
4316 template <
typename T,
typename Char>
4317 template <
typename FormatContext>
4318 FMT_CONSTEXPR FMT_INLINE
auto
4320 enable_if_t<detail::type_constant<T, Char>::value !=
4321 detail::type::custom_type>>::format(
const T &val,
4323 const -> decltype(ctx.out()) {
4324 if (specs_.width_ref.kind != detail::arg_id_kind::none ||
4325 specs_.precision_ref.kind != detail::arg_id_kind::none) {
4326 auto specs = specs_;
4327 detail::handle_dynamic_spec<detail::width_checker>(specs.width,
4328 specs.width_ref, ctx);
4329 detail::handle_dynamic_spec<detail::precision_checker>(
4330 specs.precision, specs.precision_ref, ctx);
4331 return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
4333 return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
4336 template <
typename Char>
4337 struct formatter<void *, Char> : formatter<const void *, Char> {
4338 template <
typename FormatContext>
4339 auto format(
void *val, FormatContext &ctx)
const -> decltype(ctx.out()) {
4340 return formatter<const void *, Char>::format(val, ctx);
4344 template <
typename Char,
size_t N>
4345 struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
4346 template <
typename FormatContext>
4347 FMT_CONSTEXPR
auto format(
const Char *val, FormatContext &ctx)
const
4348 -> decltype(ctx.out()) {
4349 return formatter<basic_string_view<Char>, Char>::format(val, ctx);
4362 template <
typename T>
auto ptr(T p) ->
const void * {
4363 static_assert(std::is_pointer<T>::value,
"");
4364 return detail::bit_cast<const void *>(p);
4366 template <
typename T,
typename Deleter>
4367 auto ptr(
const std::unique_ptr<T, Deleter> &p) ->
const void * {
4370 template <
typename T>
auto ptr(
const std::shared_ptr<T> &p) ->
const void * {
4384 template <
typename Enum>
4385 constexpr
auto underlying(Enum e) noexcept -> underlying_t<Enum> {
4386 return static_cast<underlying_t<Enum>
>(e);
4390 template <
typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
4391 constexpr
auto format_as(Enum e) noexcept -> underlying_t<Enum> {
4392 return static_cast<underlying_t<Enum>
>(e);
4399 friend struct formatter<bytes>;
4405 template <>
struct formatter<bytes> {
4407 detail::dynamic_format_specs<> specs_;
4410 template <
typename ParseContext>
4411 FMT_CONSTEXPR
auto parse(ParseContext &ctx) ->
const char * {
4412 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4413 detail::type::string_type);
4416 template <
typename FormatContext>
4417 auto format(bytes b, FormatContext &ctx) -> decltype(ctx.out()) {
4418 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4419 specs_.width_ref, ctx);
4420 detail::handle_dynamic_spec<detail::precision_checker>(
4421 specs_.precision, specs_.precision_ref, ctx);
4422 return detail::write_bytes(ctx.out(), b.data_, specs_);
4427 template <
typename T>
struct group_digits_view {
4442 template <
typename T>
auto group_digits(T value) -> group_digits_view<T> {
4446 template <
typename T>
struct formatter<group_digits_view<T>> : formatter<T> {
4448 detail::dynamic_format_specs<> specs_;
4451 template <
typename ParseContext>
4452 FMT_CONSTEXPR
auto parse(ParseContext &ctx) ->
const char * {
4453 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4454 detail::type::int_type);
4457 template <
typename FormatContext>
4458 auto format(group_digits_view<T> t, FormatContext &ctx)
4459 -> decltype(ctx.out()) {
4460 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4461 specs_.width_ref, ctx);
4462 detail::handle_dynamic_spec<detail::precision_checker>(
4463 specs_.precision, specs_.precision_ref, ctx);
4464 return detail::write_int(
4465 ctx.out(),
static_cast<detail::uint64_or_128_t<T>
>(t.value), 0, specs_,
4466 detail::digit_grouping<char>(
"\3",
","));
4471 template <
typename It,
typename Sentinel,
typename Char =
char>
4472 struct join_view : detail::view {
4478 : begin(b), end(e), sep(s) {}
4481 template <
typename It,
typename Sentinel,
typename Char>
4482 struct formatter<join_view<It, Sentinel, Char>, Char> {
4485 #ifdef __cpp_lib_ranges
4486 std::iter_value_t<It>;
4488 typename std::iterator_traits<It>::value_type;
4490 using context = buffer_context<Char>;
4491 using mapper = detail::arg_mapper<context>;
4493 template <
typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)>
4494 static auto map(
const T &value) ->
const T & {
4497 template <
typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)>
4498 static auto map(
const T &value) -> decltype(mapper().map(value)) {
4499 return mapper().map(value);
4502 using formatter_type =
4503 conditional_t<is_formattable<value_type, Char>::value,
4504 formatter<remove_cvref_t<decltype(map(
4505 std::declval<const value_type &>()))>,
4507 detail::fallback_formatter<value_type, Char>>;
4509 formatter_type value_formatter_;
4512 template <
typename ParseContext>
4513 FMT_CONSTEXPR
auto parse(ParseContext &ctx) ->
const Char * {
4514 return value_formatter_.parse(ctx);
4517 template <
typename FormatContext>
4518 auto format(
const join_view<It, Sentinel, Char> &value,
4519 FormatContext &ctx)
const -> decltype(ctx.out()) {
4520 auto it = value.begin;
4521 auto out = ctx.out();
4522 if (it != value.end) {
4523 out = value_formatter_.format(map(*it), ctx);
4525 while (it != value.end) {
4526 out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
4527 ctx.advance_to(out);
4528 out = value_formatter_.format(map(*it), ctx);
4540 template <
typename It,
typename Sentinel>
4541 auto join(It begin, Sentinel end,
string_view sep) -> join_view<It, Sentinel> {
4542 return {begin, end, sep};
4561 template <
typename Range>
4563 -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> {
4564 return join(std::begin(range), std::end(range), sep);
4578 template <
typename T, FMT_ENABLE_IF(!std::is_
integral<T>::value)>
4579 inline auto to_string(
const T &value) -> std::string {
4581 detail::write<char>(appender(
buffer), value);
4585 template <
typename T, FMT_ENABLE_IF(std::is_
integral<T>::value)>
4586 FMT_NODISCARD
inline auto to_string(T value) -> std::string {
4589 constexpr
int max_size = detail::digits10<T>() + 2;
4590 char buffer[max_size > 5 ?
static_cast<unsigned>(max_size) : 5];
4592 return std::string(begin, detail::write<char>(begin, value));
4595 template <
typename Char,
size_t SIZE>
4597 -> std::basic_string<Char> {
4598 auto size = buf.size();
4599 detail::assume(size < std::basic_string<Char>().max_size());
4600 return std::basic_string<Char>(buf.data(), size);
4603 FMT_BEGIN_DETAIL_NAMESPACE
4605 template <
typename Char>
4610 using detail::arg_formatter;
4611 using detail::buffer_appender;
4612 using detail::custom_formatter;
4613 using detail::default_arg_formatter;
4614 using detail::get_arg;
4615 using detail::locale_ref;
4616 using detail::parse_format_specs;
4617 using detail::to_unsigned;
4619 using detail::write;
4620 auto out = buffer_appender<Char>(buf);
4621 if (fmt.
size() == 2 && equal2(fmt.
data(),
"{}")) {
4622 auto arg = args.
get(0);
4624 error_handler().on_error(
"argument not found");
4625 visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg);
4629 struct format_handler : error_handler {
4631 buffer_context<Char> context;
4636 : parse_context(str), context(p_out, p_args, p_loc) {}
4638 void on_text(
const Char *begin,
const Char *end) {
4640 context.advance_to(write<Char>(context.out(), text));
4643 FMT_CONSTEXPR
auto on_arg_id() ->
int {
4646 FMT_CONSTEXPR
auto on_arg_id(
int id) ->
int {
4650 int arg_id = context.arg_id(
id);
4652 on_error(
"argument not found");
4656 FMT_INLINE
void on_replacement_field(
int id,
const Char *) {
4657 auto arg = get_arg(context,
id);
4658 context.advance_to(visit_format_arg(
4659 default_arg_formatter<Char>{context.out(), context.args(),
4664 auto on_format_specs(
int id,
const Char *begin,
const Char *end)
4666 auto arg = get_arg(context,
id);
4667 if (arg.type() == type::custom_type) {
4669 visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);
4670 return parse_context.
begin();
4672 auto specs = detail::dynamic_format_specs<Char>();
4673 begin = parse_format_specs(begin, end, specs, parse_context, arg.type());
4674 detail::handle_dynamic_spec<detail::width_checker>(
4675 specs.width, specs.width_ref, context);
4676 detail::handle_dynamic_spec<detail::precision_checker>(
4677 specs.precision, specs.precision_ref, context);
4678 if (begin == end || *begin !=
'}')
4679 on_error(
"missing '}' in format string");
4680 auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
4681 context.advance_to(visit_format_arg(f, arg));
4685 detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
4688 #ifndef FMT_HEADER_ONLY
4692 extern template FMT_API
auto thousands_sep_impl<char>(locale_ref)
4693 -> thousands_sep_result<char>;
4694 extern template FMT_API
auto thousands_sep_impl<wchar_t>(locale_ref)
4695 -> thousands_sep_result<wchar_t>;
4696 extern template FMT_API
auto decimal_point_impl(locale_ref) -> char;
4697 extern template FMT_API
auto decimal_point_impl(locale_ref) -> wchar_t;
4700 FMT_END_DETAIL_NAMESPACE
4702 #if FMT_USE_USER_DEFINED_LITERALS
4703 inline namespace literals {
4714 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
4715 template <detail_exported::fixed_
string Str> constexpr
auto operator""_a() {
4716 using char_t = remove_cvref_t<decltype(Str.data[0])>;
4717 return detail::udl_arg<char_t,
sizeof(Str.data) /
sizeof(char_t), Str>();
4720 constexpr
auto operator"" _a(
const char *s,
size_t) -> detail::udl_arg<char> {
4727 template <
typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4730 return detail::vformat(loc, fmt, args);
4733 template <
typename Locale,
typename... T,
4734 FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4737 return fmt::vformat(loc,
string_view(fmt), fmt::make_format_args(args...));
4740 template <
typename OutputIt,
typename Locale,
4741 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value
4742 &&detail::is_locale<Locale>::value)>
4743 auto vformat_to(OutputIt out,
const Locale &loc,
string_view fmt,
4745 using detail::get_buffer;
4746 auto &&buf = get_buffer<char>(out);
4747 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4748 return detail::get_iterator(buf, out);
4751 template <
typename OutputIt,
typename Locale,
typename... T,
4752 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value
4753 &&detail::is_locale<Locale>::value)>
4754 FMT_INLINE
auto format_to(OutputIt out,
const Locale &loc,
4756 return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
4759 template <
typename Locale,
typename... T,
4760 FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4761 FMT_NODISCARD FMT_INLINE
auto formatted_size(
const Locale &loc,
4763 T &&...args) ->
size_t {
4764 auto buf = detail::counting_buffer<>();
4765 detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...),
4766 detail::locale_ref(loc));
4770 FMT_MODULE_EXPORT_END
4773 #ifdef FMT_HEADER_ONLY
4774 #define FMT_FUNC inline
4775 #include "format-inl.h"
FMT_CONSTEXPR auto next_arg_id() -> int
Definition: core.h:725
FMT_CONSTEXPR void check_arg_id(int id)
Definition: core.h:740
FMT_CONSTEXPR void advance_to(iterator it)
Definition: core.h:717
constexpr auto begin() const noexcept -> iterator
Definition: core.h:707
FMT_CONSTEXPR20 void resize(size_t count)
Definition: format.h:988
auto operator=(basic_memory_buffer &&other) noexcept -> basic_memory_buffer &
Definition: format.h:973
void reserve(size_t new_capacity)
Definition: format.h:991
FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer &&other) noexcept
Definition: format.h:964
constexpr auto size() const noexcept -> size_t
Definition: core.h:480
constexpr auto data() const noexcept -> const Char *
Definition: core.h:477
constexpr auto capacity() const noexcept -> size_t
Definition: core.h:942
FMT_CONSTEXPR auto data() noexcept -> T *
Definition: core.h:945
void append(const U *begin, const U *end)
constexpr auto size() const noexcept -> size_t
Definition: core.h:939
double f(RaB r, PrincipalQN n, DiracQN k, Zeff z, AlphaFS a)
Upper radial component.
Definition: DiracHydrogen.cpp:71
double g(RaB r, PrincipalQN n, DiracQN k, Zeff z, AlphaFS a)
Lower (small) radial component.
Definition: DiracHydrogen.cpp:83
constexpr double c
speed of light in a.u. (=1/alpha)
Definition: PhysConst_constants.hpp:17
std::vector< T > & operator+=(std::vector< T > &a, const std::vector< T > &b)
Provide addition of two vectors:
Definition: Vector.hpp:454
T product(T first, Args... rest)
Variadic product - helper function.
Definition: Array.hpp:223
auto compare(const std::vector< T > &first, const std::vector< T > &second)
Directly compare two arithmetic vectors of the same type and length. Returns pair {delta,...
Definition: Vector.hpp:33