File indexing completed on 2026-08-17 08:50:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_MP_CPP_DF_QF_DETAIL_2023_01_02_HPP
0011 #define BOOST_MP_CPP_DF_QF_DETAIL_2023_01_02_HPP
0012
0013 #include <boost/multiprecision/detail/standalone_config.hpp>
0014
0015 #if defined(BOOST_HAS_FLOAT128)
0016 #if __has_include(<quadmath.h>)
0017
0018 #include <quadmath.h>
0019
0020 #if !defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
0021 #define BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128
0022 #endif
0023
0024 #endif
0025 #endif
0026
0027 #include <boost/multiprecision/number.hpp>
0028 #include <boost/multiprecision/detail/float128_functions.hpp>
0029 #include <boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath.hpp>
0030
0031 namespace boost { namespace multiprecision { namespace backends { namespace cpp_df_qf_detail {
0032
0033 template <typename UnsignedIntegralType,
0034 typename FloatType>
0035 constexpr auto float_mask() noexcept -> UnsignedIntegralType
0036 {
0037 using local_unsigned_integral_type = UnsignedIntegralType;
0038 using local_float_type = FloatType;
0039
0040 static_assert(static_cast<int>(sizeof(local_unsigned_integral_type) * 8u) > static_cast<int>(cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits),
0041 "Error: this function is intended for unsigned integral type wider than the float type.");
0042
0043 return
0044 {
0045 local_unsigned_integral_type { local_unsigned_integral_type { 1 } << static_cast<unsigned>(cpp_df_qf_detail::ccmath::numeric_limits<local_float_type>::digits) }
0046 - local_unsigned_integral_type { 1 }
0047 };
0048 }
0049
0050 template <class FloatingPointTypeA, class FloatingPointTypeB>
0051 struct pair
0052 {
0053 static_assert(std::is_same<FloatingPointTypeA, FloatingPointTypeB>::value, "Error: floating point types A and B must be identical");
0054
0055 using float_type = FloatingPointTypeA;
0056
0057 float_type first;
0058 float_type second;
0059
0060
0061 constexpr pair() noexcept : first { }, second { } { }
0062
0063 constexpr pair(float_type a, float_type b) noexcept : first { a }, second { b } { }
0064 constexpr pair(const pair& other) noexcept : first { other.first }, second { other.second } { }
0065 constexpr pair(pair&& other) noexcept : first { other.first }, second { other.second } { }
0066
0067 constexpr auto operator=(const pair& other) noexcept -> pair&
0068 {
0069 if (this != &other)
0070 {
0071 first = other.first;
0072 second = other.second;
0073 }
0074
0075 return *this;
0076 }
0077
0078 constexpr auto operator=(pair&& other) noexcept -> pair&
0079 {
0080 first = other.first;
0081 second = other.second;
0082
0083 return *this;
0084 }
0085 };
0086
0087 template <class FloatingPointType>
0088 struct is_floating_point
0089 {
0090 static constexpr auto value = ::std::is_same<FloatingPointType, float>::value
0091 || ::std::is_same<FloatingPointType, double>::value
0092 || ::std::is_same<FloatingPointType, long double>::value
0093 #if defined(BOOST_MP_CPP_DOUBLE_FP_HAS_FLOAT128)
0094 || ::std::is_same<FloatingPointType, ::boost::float128_type>::value
0095 #endif
0096 ;
0097 };
0098
0099 template <typename FloatType>
0100 struct split_maker
0101 {
0102 private:
0103 using float_type = FloatType;
0104
0105 public:
0106 static constexpr int
0107 n_shl
0108 {
0109 static_cast<int>((ccmath::numeric_limits<float_type>::digits + 1) / 2)
0110 };
0111
0112 static_assert(n_shl < std::numeric_limits<std::uint64_t>::digits,
0113 "Error: Left-shift amount for split does not fit in std::uint64_t");
0114
0115 static constexpr float_type
0116 value
0117 {
0118 static_cast<float_type>
0119 (
0120 std::uint64_t
0121 {
0122 UINT64_C(1)
0123 + std::uint64_t { UINT64_C(1) << static_cast<unsigned>(n_shl) }
0124 }
0125 )
0126 };
0127 };
0128
0129 template <typename FloatingPointType>
0130 struct exact_arithmetic
0131 {
0132
0133
0134
0135 static_assert(is_floating_point<FloatingPointType>::value, "Error: exact_arithmetic<> invoked with unknown floating-point type");
0136
0137 using float_type = FloatingPointType;
0138 using float_pair = pair<float_type, float_type>;
0139
0140 static constexpr auto two_sum(const float_type a, const float_type b) -> float_pair
0141 {
0142 const float_type hi { a + b };
0143 const float_type a1 { hi - b };
0144
0145 return { hi, float_type { (a - a1) + (b - float_type { hi - a1 }) } };
0146 }
0147
0148 static constexpr auto two_diff(const float_type a, const float_type b) -> float_pair
0149 {
0150 const float_type hi { a - b };
0151 const float_type a1 { hi + b };
0152
0153 return { hi, float_type { (a - a1) - (b + float_type { hi - a1 }) } };
0154 }
0155
0156 static constexpr auto two_hilo_sum(const float_type a, const float_type b) -> float_pair
0157 {
0158 const float_type hi { a + b };
0159
0160 return { hi, float_type { b - (hi - a) } };
0161 }
0162
0163 static constexpr auto normalize(float_type a, float_type b) -> float_pair
0164 {
0165 const float_type u { a + b };
0166
0167 return
0168 {
0169 u,
0170 float_type { a - u } + b
0171 };
0172 }
0173 };
0174
0175 } } } }
0176
0177 #endif