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