diff --git a/include/fmt/base.h b/include/fmt/base.h index 001296fb..7cd243f9 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1694,7 +1694,7 @@ template class buffer { protected: // Don't initialize ptr_ since it is not accessed to save a few cycles. FMT_MSC_WARNING(suppress : 26495) - FMT_CONSTEXPR20 buffer(grow_fun grow, size_t sz) noexcept + FMT_CONSTEXPR buffer(grow_fun grow, size_t sz) noexcept : size_(sz), capacity_(sz), grow_(grow) {} constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0, diff --git a/include/fmt/format.h b/include/fmt/format.h index e3aa9fd6..88421c70 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -876,7 +876,7 @@ class basic_memory_buffer : public detail::buffer { using value_type = T; using const_reference = const T&; - FMT_CONSTEXPR20 explicit basic_memory_buffer( + FMT_CONSTEXPR explicit basic_memory_buffer( const Allocator& alloc = Allocator()) : detail::buffer(grow), alloc_(alloc) { this->set(store_, SIZE); @@ -924,7 +924,7 @@ class basic_memory_buffer : public detail::buffer { /// Resizes the buffer to contain `count` elements. If T is a POD type new /// elements may not be initialized. - FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } + FMT_CONSTEXPR void resize(size_t count) { this->try_resize(count); } /// Increases the buffer capacity to `new_capacity`. void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } @@ -2663,39 +2663,44 @@ inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) { class bigint { private: - // A bigint is stored as an array of bigits (big digits), with bigit at index - // 0 being the least significant one. - using bigit = uint32_t; + // A bigint is a number in the form bigit_[N - 1] ... bigit_[0] * 32^exp_. + using bigit = uint32_t; // A big digit. using double_bigit = uint64_t; + enum { bigit_bits = num_bits() }; enum { bigits_capacity = 32 }; basic_memory_buffer bigits_; int exp_; - FMT_CONSTEXPR20 auto operator[](int index) const -> bigit { - return bigits_[to_unsigned(index)]; - } - FMT_CONSTEXPR20 auto operator[](int index) -> bigit& { - return bigits_[to_unsigned(index)]; - } - - static constexpr const int bigit_bits = num_bits(); - friend struct formatter; - FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { + FMT_CONSTEXPR auto operator[](int index) const -> bigit { + return bigits_[to_unsigned(index)]; + } + FMT_CONSTEXPR auto operator[](int index) -> bigit& { + return bigits_[to_unsigned(index)]; + } + + static constexpr auto minimum(int a, int b) -> int { return a < b ? a : b; } + static constexpr auto maximum(int a, int b) -> int { return a > b ? a : b; } + + FMT_CONSTEXPR auto get_bigit(int i) const -> bigit { + return i >= exp_ && i < num_bigits() ? bigits_[i - exp_] : 0; + }; + + FMT_CONSTEXPR void subtract_bigits(int index, bigit other, bigit& borrow) { auto result = static_cast((*this)[index]) - other - borrow; (*this)[index] = static_cast(result); borrow = static_cast(result >> (bigit_bits * 2 - 1)); } - FMT_CONSTEXPR20 void remove_leading_zeros() { + FMT_CONSTEXPR void remove_leading_zeros() { int num_bigits = static_cast(bigits_.size()) - 1; while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; bigits_.resize(to_unsigned(num_bigits + 1)); } // Computes *this -= other assuming aligned bigints and *this >= other. - FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) { + FMT_CONSTEXPR void subtract_aligned(const bigint& other) { FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); FMT_ASSERT(compare(*this, other) >= 0, ""); bigit borrow = 0; @@ -2706,7 +2711,7 @@ class bigint { remove_leading_zeros(); } - FMT_CONSTEXPR20 void multiply(uint32_t value) { + FMT_CONSTEXPR void multiply(uint32_t value) { const double_bigit wide_value = value; bigit carry = 0; for (size_t i = 0, n = bigits_.size(); i < n; ++i) { @@ -2719,7 +2724,7 @@ class bigint { template ::value || std::is_same::value)> - FMT_CONSTEXPR20 void multiply(UInt value) { + FMT_CONSTEXPR void multiply(UInt value) { using half_uint = conditional_t::value, uint64_t, uint32_t>; const int shift = num_bits() - bigit_bits; @@ -2740,7 +2745,7 @@ class bigint { template ::value || std::is_same::value)> - FMT_CONSTEXPR20 void assign(UInt n) { + FMT_CONSTEXPR void assign(UInt n) { size_t num_bigits = 0; do { bigits_[num_bigits++] = static_cast(n); @@ -2751,13 +2756,13 @@ class bigint { } public: - FMT_CONSTEXPR20 bigint() : exp_(0) {} + FMT_CONSTEXPR bigint() : exp_(0) {} explicit bigint(uint64_t n) { assign(n); } bigint(const bigint&) = delete; void operator=(const bigint&) = delete; - FMT_CONSTEXPR20 void assign(const bigint& other) { + FMT_CONSTEXPR void assign(const bigint& other) { auto size = other.bigits_.size(); bigits_.resize(size); auto data = other.bigits_.data(); @@ -2765,16 +2770,16 @@ class bigint { exp_ = other.exp_; } - template FMT_CONSTEXPR20 void operator=(Int n) { + template FMT_CONSTEXPR void operator=(Int n) { FMT_ASSERT(n > 0, ""); assign(uint64_or_128_t(n)); } - FMT_CONSTEXPR20 auto num_bigits() const -> int { + FMT_CONSTEXPR auto num_bigits() const -> int { return static_cast(bigits_.size()) + exp_; } - FMT_NOINLINE FMT_CONSTEXPR20 auto operator<<=(int shift) -> bigint& { + FMT_CONSTEXPR auto operator<<=(int shift) -> bigint& { FMT_ASSERT(shift >= 0, ""); exp_ += shift / bigit_bits; shift %= bigit_bits; @@ -2789,14 +2794,13 @@ class bigint { return *this; } - template - FMT_CONSTEXPR20 auto operator*=(Int value) -> bigint& { + template FMT_CONSTEXPR auto operator*=(Int value) -> bigint& { FMT_ASSERT(value > 0, ""); multiply(uint32_or_64_or_128_t(value)); return *this; } - friend FMT_CONSTEXPR20 auto compare(const bigint& lhs, const bigint& rhs) + friend FMT_CONSTEXPR auto compare(const bigint& lhs, const bigint& rhs) -> int { int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); if (num_lhs_bigits != num_rhs_bigits) @@ -2814,24 +2818,18 @@ class bigint { } // Returns compare(lhs1 + lhs2, rhs). - friend FMT_CONSTEXPR20 auto add_compare(const bigint& lhs1, - const bigint& lhs2, const bigint& rhs) - -> int { - auto minimum = [](int a, int b) { return a < b ? a : b; }; - auto maximum = [](int a, int b) { return a > b ? a : b; }; + friend FMT_CONSTEXPR auto add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) -> int { int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits()); int num_rhs_bigits = rhs.num_bigits(); if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; if (max_lhs_bigits > num_rhs_bigits) return 1; - auto get_bigit = [](const bigint& n, int i) -> bigit { - return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; - }; double_bigit borrow = 0; int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_); for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { double_bigit sum = - static_cast(get_bigit(lhs1, i)) + get_bigit(lhs2, i); - bigit rhs_bigit = get_bigit(rhs, i); + static_cast(lhs1.get_bigit(i)) + lhs2.get_bigit(i); + bigit rhs_bigit = rhs.get_bigit(i); if (sum > rhs_bigit + borrow) return 1; borrow = rhs_bigit + borrow - sum; if (borrow > 1) return -1; @@ -2890,7 +2888,7 @@ class bigint { // If this bigint has a bigger exponent than other, adds trailing zero to make // exponents equal. This simplifies some operations such as subtraction. - FMT_CONSTEXPR20 void align(const bigint& other) { + FMT_CONSTEXPR void align(const bigint& other) { int exp_difference = exp_ - other.exp_; if (exp_difference <= 0) return; int num_bigits = static_cast(bigits_.size()); @@ -2903,7 +2901,7 @@ class bigint { // Divides this bignum by divisor, assigning the remainder to this and // returning the quotient. - FMT_CONSTEXPR20 auto divmod_assign(const bigint& divisor) -> int { + FMT_CONSTEXPR auto divmod_assign(const bigint& divisor) -> int { FMT_ASSERT(this != &divisor, ""); if (compare(*this, divisor) < 0) return 0; FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); diff --git a/test/test-assert.h b/test/test-assert.h index ab7b2bf7..bec3dfc3 100644 --- a/test/test-assert.h +++ b/test/test-assert.h @@ -12,7 +12,7 @@ void throw_assertion_failure(const char* message); #define FMT_ASSERT(condition, message) \ - if (!(condition)) throw_assertion_failure(message); + ((condition) ? (void)0 : throw_assertion_failure(message)) #include "gtest/gtest.h"