diff --git a/base/common/wide_integer_impl.h b/base/common/wide_integer_impl.h index 48a2a278df9..e18a27df48a 100644 --- a/base/common/wide_integer_impl.h +++ b/base/common/wide_integer_impl.h @@ -233,7 +233,7 @@ struct integer::_impl * the recursive call happens when t / 2^64 > 2^64, so there won't be more than 5 of them. */ template - constexpr static void set_multiplier(wide_integer & self, T t) noexcept { + constexpr static void set_multiplier(integer & self, T t) noexcept { constexpr uint64_t max_int = std::numeric_limits::max(); const T alpha = t / max_int; @@ -241,15 +241,26 @@ struct integer::_impl for (uint64_t i = 0; i < static_cast(alpha); ++i) self *= max_int; else // max(double) / 2^64 will surely contain less than 52 precision bits, so speed up computations. - set_multiplier(self, static_cast(alpha)); + set_multiplier(self, alpha); self += static_cast(t - alpha * max_int); } - constexpr static void wide_integer_from_bultin(wide_integer& self, double rhs) noexcept { + constexpr static void wide_integer_from_bultin(integer& self, double rhs) noexcept { constexpr int64_t max_int = std::numeric_limits::max(); constexpr int64_t min_int = std::numeric_limits::min(); + /// There are values in int64 that have more than 53 significant bits (in terms of double + /// representation). Such values, being promoted to double, are rounded up or down. If they are rounded up, + /// the result may not fit in 64 bits. + /// The example of such a number is 9.22337e+18. + /// As to_Integral does a static_cast to int64_t, it may result in UB. + /// The necessary check here is that long double has enough significant (mantissa) bits to store the + /// int64_t max value precisely. + static_assert(LDBL_MANT_DIG >= 64, + "On your system long double has less than 64 precision bits," + "which may result in UB when initializing double from int64_t"); + if ((rhs > 0 && rhs < max_int) || (rhs < 0 && rhs > min_int)) { self = static_cast(rhs); return;