| 73 | |
| 74 | template <unsigned Digits10, class ExponentType, class Allocator> |
| 75 | class cpp_dec_float |
| 76 | { |
| 77 | private: |
| 78 | // Perform some static sanity checks. |
| 79 | static_assert(boost::multiprecision::detail::is_signed<ExponentType>::value, |
| 80 | "ExponentType must be a signed built in integer type."); |
| 81 | |
| 82 | static_assert(sizeof(ExponentType) > 1, |
| 83 | "ExponentType is too small."); |
| 84 | |
| 85 | static_assert(Digits10 < UINT32_C(0x80000000), |
| 86 | "Digits10 exceeds the maximum."); |
| 87 | |
| 88 | // Private class-local constants. |
| 89 | static constexpr std::int32_t cpp_dec_float_digits10_limit_lo = INT32_C(9); |
| 90 | static constexpr std::int32_t cpp_dec_float_digits10_limit_hi = static_cast<std::int32_t>((std::numeric_limits<std::int32_t>::max)() - 100); |
| 91 | |
| 92 | static constexpr std::int32_t cpp_dec_float_elem_digits10 = INT32_C(8); |
| 93 | static constexpr std::int32_t cpp_dec_float_elem_mask = INT32_C(100000000); |
| 94 | |
| 95 | static constexpr std::int32_t cpp_dec_float_elems_for_kara = static_cast<std::int32_t>(128 + 1); |
| 96 | |
| 97 | public: |
| 98 | using signed_types = std::tuple<long long> ; |
| 99 | using unsigned_types = std::tuple<unsigned long long>; |
| 100 | using float_types = std::tuple<double, long double>; |
| 101 | using exponent_type = ExponentType; |
| 102 | |
| 103 | // Public class-local constants. |
| 104 | static constexpr std::int32_t cpp_dec_float_radix = INT32_C(10); |
| 105 | static constexpr std::int32_t cpp_dec_float_digits10 = ((static_cast<std::int32_t>(Digits10) < cpp_dec_float_digits10_limit_lo) ? cpp_dec_float_digits10_limit_lo : ((static_cast<std::int32_t>(Digits10) > cpp_dec_float_digits10_limit_hi) ? cpp_dec_float_digits10_limit_hi : static_cast<std::int32_t>(Digits10))); |
| 106 | static constexpr exponent_type cpp_dec_float_max_exp10 = (static_cast<exponent_type>(1) << (std::numeric_limits<exponent_type>::digits - 5)); |
| 107 | static constexpr exponent_type cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10; |
| 108 | static constexpr exponent_type cpp_dec_float_max_exp = cpp_dec_float_max_exp10; |
| 109 | static constexpr exponent_type cpp_dec_float_min_exp = cpp_dec_float_min_exp10; |
| 110 | |
| 111 | static_assert(cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10 == -cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10, "Failed exponent range check"); |
| 112 | |
| 113 | static_assert(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10, "Failed digit sanity check"); |
| 114 | |
| 115 | private: |
| 116 | // There are three guard limbs. |
| 117 | // 1) The first limb has 'play' from 1...8 decimal digits. |
| 118 | // 2) The last limb also has 'play' from 1...8 decimal digits. |
| 119 | // 3) One limb can get lost when justifying after multiply. |
| 120 | static constexpr std::int32_t cpp_dec_float_elem_number = static_cast<std::int32_t>(((Digits10 / cpp_dec_float_elem_digits10) + (((Digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)) + 3); |
| 121 | |
| 122 | public: |
| 123 | static constexpr std::int32_t cpp_dec_float_max_digits10 = static_cast<std::int32_t>(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10); |
| 124 | |
| 125 | private: |
| 126 | using array_type = |
| 127 | typename std::conditional<std::is_void<Allocator>::value, |
| 128 | detail::static_array <std::uint32_t, static_cast<std::uint32_t>(cpp_dec_float_elem_number)>, |
| 129 | detail::dynamic_array<std::uint32_t, static_cast<std::uint32_t>(cpp_dec_float_elem_number), Allocator> >::type; |
| 130 | |
| 131 | typedef enum enum_fpclass_type |
| 132 | { |
nothing calls this directly
no test coverage detected