Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:50:55

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //  Copyright 2021 - 2025 Fahad Syed.
0003 //  Copyright 2021 - 2025 Christopher Kormanyos.
0004 //  Copyright 2021 - 2025 Janek Kozicki.
0005 //  Distributed under the Boost Software License, Version 1.0.
0006 //  (See accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
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 // __has_include(<quadmath.h>)
0025 #endif // defined(BOOST_HAS_FLOAT128)
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   // Default-constructed cpp_double_fp_backend values are zero.
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    // The exact_arithmetic<> struct implements a few extended
0133    // precision algorithms that are used in cpp_double_fp_backend.
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 } } } } // namespace boost::multiprecision::backends::cpp_df_qf_detail
0176 
0177 #endif // BOOST_MP_CPP_DF_QF_DETAIL_2023_01_02_HPP