From b4a4189d0c7612d143f438119fa149d8b381d37f Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 10 Mar 2022 11:41:56 -0800 Subject: [PATCH] Fix handling of implicit bit --- include/fmt/format-inl.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 988e3a0d..372295ee 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -215,11 +215,16 @@ template struct bits { static_cast(sizeof(T) * std::numeric_limits::digits); }; +template constexpr bool has_implicit_bit() { + return std::numeric_limits::digits != 64; +} + // Returns the number of significand bits in Float excluding the implicit bit. template constexpr int num_significand_bits() { // Subtract 1 to account for an implicit most significant bit in the - // normalized form. - return std::numeric_limits::digits - 1; + // normalized form.. + return std::numeric_limits::digits - + (has_implicit_bit() ? 1 : 0); } // A floating-point number f * pow(2, e). @@ -248,8 +253,9 @@ template struct basic_fp { // Assume float is in the format [sign][exponent][significand]. const int num_float_significand_bits = detail::num_significand_bits(); - const uint64_t implicit_bit = 1ULL << num_float_significand_bits; using carrier_uint = typename dragonbox::float_info::carrier_uint; + const carrier_uint implicit_bit = carrier_uint(1) + << num_float_significand_bits; const carrier_uint significand_mask = implicit_bit - 1; auto u = bit_cast(n); f = static_cast(u & significand_mask); @@ -260,11 +266,11 @@ template struct basic_fp { // than the smallest normalized number (biased_e > 1). bool is_predecessor_closer = f == 0 && biased_e > 1; if (biased_e != 0) - f += implicit_bit; + f += static_cast(implicit_bit); else biased_e = 1; // Subnormals use biased exponent 1 (min exponent). const int exponent_bias = std::numeric_limits::max_exponent - 1; - e = biased_e - exponent_bias - num_float_significand_bits; + e = biased_e - exponent_bias - std::numeric_limits::digits + 1; return is_predecessor_closer; }