1 /////////////////////////////////////////////////////////////// 2 // Copyright 2012 John Maddock. Distributed under the Boost 3 // Software License, Version 1.0. (See accompanying file 4 // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt 5 6 #ifndef BOOST_MATH_MAX_DIGITS10_HPP 7 #define BOOST_MATH_MAX_DIGITS10_HPP 8 9 namespace boost { 10 namespace multiprecision { 11 namespace detail { 12 13 template <unsigned digits> 14 struct calc_max_digits10 15 { 16 #ifndef BOOST_NO_CXX11_CONSTEXPR max_digits_10boost::multiprecision::detail::calc_max_digits1017 static constexpr unsigned max_digits_10(unsigned d) 18 { 19 // 20 // We need ceil(log10(2) * d) + 1 decimal places to 21 // guarantee round tripping, see: https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/ 22 // and references therein. Since log10(2) is irrational, then d*log10(2) will 23 // never be exactly an integer so we can replace by trunc(log10(2) * d) + 2 24 // and avoid the call to ceil: 25 // 26 return static_cast<unsigned>(0.301029995663981195213738894724493026768189881462108541310 * d) + 2; 27 } 28 static const unsigned value = max_digits_10(digits); 29 #else 30 // 31 // This version works up to about 15K binary digits, then starts sporadically failing 32 // and giving values that are 1 too small. 33 // 34 BOOST_STATIC_CONSTANT(unsigned, value = 2 + ((static_cast<boost::uint64_t>(digits) * static_cast<boost::uint64_t>(1292913986)) >> 32)); 35 #endif 36 }; 37 38 template <unsigned digits> 39 struct calc_digits10 40 { 41 #ifndef BOOST_NO_CXX11_CONSTEXPR digits_10boost::multiprecision::detail::calc_digits1042 static constexpr unsigned digits_10(unsigned d) 43 { 44 // 45 // We need floor(log10(2) * (d-1)), see: 46 // https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/ 47 // and references therein. 48 // 49 return static_cast<unsigned>(0.301029995663981195213738894724493026768189881462108541310 * (d - 1)); 50 } 51 static const unsigned value = digits_10(digits); 52 #else 53 BOOST_STATIC_CONSTANT(unsigned, value = ((static_cast<boost::uint64_t>(digits - 1) * static_cast<boost::uint64_t>(1292913986)) >> 32)); 54 #endif 55 }; 56 57 }}} // namespace boost::multiprecision::detail 58 59 #endif 60