]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/multiprecision/detail/functions/trig.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / multiprecision / detail / functions / trig.hpp
index 6550549808b56f1767df2adb77db0829644817c7..c95b4b0c29eee8934073adacd610e0d9229991b0 100644 (file)
@@ -1,6 +1,6 @@
 
 // Copyright Christopher Kormanyos 2002 - 2011.
-// Copyright 2011 John Maddock. Distributed under the Boost
+// Copyright 2011 John Maddock.
 // Distributed under the Boost Software License, Version 1.0.
 //    (See accompanying file LICENSE_1_0.txt or copy at
 //          http://www.boost.org/LICENSE_1_0.txt)
 // This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp
 //
 
+#include <boost/multiprecision/detail/standalone_config.hpp>
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
 #ifdef BOOST_MSVC
 #pragma warning(push)
 #pragma warning(disable : 6326) // comparison of two constants
+#pragma warning(disable : 4127) // conditional expression is constant
 #endif
 
 template <class T>
 void hyp0F1(T& result, const T& b, const T& x)
 {
-   typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type  si_type;
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+   using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
 
    // Compute the series representation of Hypergeometric0F1 taken from
    // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F1/06/01/01/
@@ -67,7 +72,7 @@ void hyp0F1(T& result, const T& b, const T& x)
    }
 
    if (n >= series_limit)
-      BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge"));
+      BOOST_MP_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge"));
 }
 
 template <class T, unsigned N, bool b = boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<T> >::value>
@@ -85,14 +90,14 @@ struct scoped_N_precision<T, N, true>
    unsigned old_precision, old_arg_precision;
    scoped_N_precision(T& arg)
    {
-      old_precision = T::default_precision();
+      old_precision     = T::thread_default_precision();
       old_arg_precision = arg.precision();
-      T::default_precision(old_arg_precision * N);
+      T::thread_default_precision(old_arg_precision * N);
       arg.precision(old_arg_precision * N);
    }
    ~scoped_N_precision()
    {
-      T::default_precision(old_precision);
+      T::thread_default_precision(old_precision);
    }
    void reduce(T& arg) 
    {
@@ -116,7 +121,7 @@ void reduce_n_half_pi(T& arg, const T& n, bool go_down)
    // 1) To define a fixed precision type with 3 times the precision for the calculation.
    // 2) To dynamically increase the precision of the variables.
    //
-   typedef typename boost::multiprecision::detail::transcendental_reduction_type<T>::type reduction_type;
+   using reduction_type = typename boost::multiprecision::detail::transcendental_reduction_type<T>::type;
    //
    // Make a copy of the arg at higher precision:
    //
@@ -132,6 +137,7 @@ void reduce_n_half_pi(T& arg, const T& n, bool go_down)
    reduction_type reduction = get_constant_pi<reduction_type>();
    eval_ldexp(reduction, reduction, -1); // divide by 2
    eval_multiply(reduction, n);
+
    BOOST_MATH_INSTRUMENT_CODE(big_arg.str(10, std::ios_base::scientific));
    BOOST_MATH_INSTRUMENT_CODE(reduction.str(10, std::ios_base::scientific));
 
@@ -152,7 +158,7 @@ void reduce_n_half_pi(T& arg, const T& n, bool go_down)
 template <class T>
 void eval_sin(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
+   static_assert(number_category<T>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
    BOOST_MATH_INSTRUMENT_CODE(x.str(0, std::ios_base::scientific));
    if (&result == &x)
    {
@@ -162,21 +168,21 @@ void eval_sin(T& result, const T& x)
       return;
    }
 
-   typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type  si_type;
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
-   typedef typename mpl::front<typename T::float_types>::type                          fp_type;
+   using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+   using fp_type = typename std::tuple_element<0, typename T::float_types>::type                         ;
 
    switch (eval_fpclassify(x))
    {
    case FP_INFINITE:
    case FP_NAN:
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    case FP_ZERO:
       result = x;
@@ -261,8 +267,8 @@ void eval_sin(T& result, const T& x)
 
       BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
       BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
-      BOOST_ASSERT(xx.compare(half_pi) <= 0);
-      BOOST_ASSERT(xx.compare(ui_type(0)) >= 0);
+      BOOST_MP_ASSERT(xx.compare(half_pi) <= 0);
+      BOOST_MP_ASSERT(xx.compare(ui_type(0)) >= 0);
    }
 
    t = half_pi;
@@ -312,8 +318,8 @@ void eval_sin(T& result, const T& x)
       // divide by three identity a certain number of times.
       // Here we use division by 3^9 --> (19683 = 3^9).
 
-      static const si_type n_scale           = 9;
-      static const si_type n_three_pow_scale = static_cast<si_type>(19683L);
+      constexpr const si_type n_scale           = 9;
+      constexpr const si_type n_three_pow_scale = static_cast<si_type>(19683L);
 
       eval_divide(xx, n_three_pow_scale);
 
@@ -327,7 +333,7 @@ void eval_sin(T& result, const T& x)
       eval_multiply(result, xx);
 
       // Convert back using multiple angle identity.
-      for (boost::int32_t k = static_cast<boost::int32_t>(0); k < n_scale; k++)
+      for (std::int32_t k = static_cast<std::int32_t>(0); k < n_scale; k++)
       {
          // Rescale the cosine value using the multiple angle identity.
          eval_multiply(t2, result, ui_type(3));
@@ -346,7 +352,7 @@ void eval_sin(T& result, const T& x)
 template <class T>
 void eval_cos(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
+   static_assert(number_category<T>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
    if (&result == &x)
    {
       T temp;
@@ -355,20 +361,20 @@ void eval_cos(T& result, const T& x)
       return;
    }
 
-   typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type  si_type;
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+   using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
 
    switch (eval_fpclassify(x))
    {
    case FP_INFINITE:
    case FP_NAN:
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    case FP_ZERO:
       result = ui_type(1);
@@ -398,6 +404,20 @@ void eval_cos(T& result, const T& x)
    {
       eval_divide(t, xx, half_pi);
       eval_trunc(n_pi, t);
+      //
+      // If n_pi is > 1/epsilon, then it is no longer an exact integer value
+      // but an approximation.  As a result we can no longer reliably reduce
+      // xx to 0 <= xx < pi/2, nor can we tell the sign of the result as we need
+      // n_pi % 4 for that, but that will always be zero in this situation.
+      // We could use a higher precision type for n_pi, along with division at
+      // higher precision, but that's rather expensive.  So for now we do not support
+      // this, and will see if anyone complains and has a legitimate use case.
+      //
+      if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
+      {
+         result = ui_type(1);
+         return;
+      }
       BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
       t = ui_type(4);
       eval_fmod(t, n_pi, t);
@@ -418,25 +438,11 @@ void eval_cos(T& result, const T& x)
       }
       else
       {
-         BOOST_ASSERT(t.compare(ui_type(3)) == 0);
+         BOOST_MP_ASSERT(t.compare(ui_type(3)) == 0);
       }
 
       if (b_go_down)
          eval_increment(n_pi);
-      //
-      // If n_pi is > 1/epsilon, then it is no longer an exact integer value
-      // but an approximation.  As a result we can no longer reliably reduce
-      // xx to 0 <= xx < pi/2, nor can we tell the sign of the result as we need
-      // n_pi % 4 for that, but that will always be zero in this situation.
-      // We could use a higher precision type for n_pi, along with division at
-      // higher precision, but that's rather expensive.  So for now we do not support
-      // this, and will see if anyone complains and has a legitimate use case.
-      //
-      if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
-      {
-         result = ui_type(1);
-         return;
-      }
 
       reduce_n_half_pi(xx, n_pi, b_go_down);
       //
@@ -455,8 +461,8 @@ void eval_cos(T& result, const T& x)
          eval_subtract(xx, half_pi, xx);
          eval_ldexp(half_pi, half_pi, -1);
       }
-      BOOST_ASSERT(xx.compare(half_pi) <= 0);
-      BOOST_ASSERT(xx.compare(ui_type(0)) >= 0);
+      BOOST_MP_ASSERT(xx.compare(half_pi) <= 0);
+      BOOST_MP_ASSERT(xx.compare(ui_type(0)) >= 0);
    }
    else
    {
@@ -482,7 +488,7 @@ void eval_cos(T& result, const T& x)
 template <class T>
 void eval_tan(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
+   static_assert(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
    if (&result == &x)
    {
       T temp;
@@ -503,7 +509,7 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x)
    // Abramowitz and Stegun 15.1.1.
    // There are no checks on input range or parameter boundaries.
 
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
 
    T x_pow_n_div_n_fact(x);
    T pochham_a(a);
@@ -555,15 +561,15 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x)
          break;
    }
    if (n > series_limit)
-      BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge."));
+      BOOST_MP_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge."));
 }
 
 template <class T>
 void eval_asin(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
-   typedef typename mpl::front<typename T::float_types>::type                          fp_type;
+   static_assert(number_category<T>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+   using fp_type = typename std::tuple_element<0, typename T::float_types>::type                         ;
 
    if (&result == &x)
    {
@@ -576,13 +582,13 @@ void eval_asin(T& result, const T& x)
    {
    case FP_NAN:
    case FP_INFINITE:
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    case FP_ZERO:
       result = x;
@@ -599,13 +605,13 @@ void eval_asin(T& result, const T& x)
    int c = xx.compare(ui_type(1));
    if (c > 0)
    {
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    }
    else if (c == 0)
@@ -651,9 +657,9 @@ void eval_asin(T& result, const T& x)
       return;
    }
 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
-   typedef typename boost::multiprecision::detail::canonical<long double, T>::type guess_type;
+   using guess_type = typename boost::multiprecision::detail::canonical<long double, T>::type;
 #else
-   typedef fp_type guess_type;
+   using guess_type = fp_type;
 #endif
    // Get initial estimate using standard math function asin.
    guess_type dd;
@@ -666,8 +672,8 @@ void eval_asin(T& result, const T& x)
    // have at least 2/3 of the digits correct on the assumption that the correction
    // we've just added will finish the job...
 
-   boost::intmax_t current_precision = eval_ilogb(result);
-   boost::intmax_t target_precision  = std::numeric_limits<number<T> >::is_specialized ? 
+   std::intmax_t current_precision = eval_ilogb(result);
+   std::intmax_t target_precision  = std::numeric_limits<number<T> >::is_specialized ? 
       current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
       : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 2) / 3;
 
@@ -691,20 +697,20 @@ void eval_asin(T& result, const T& x)
 template <class T>
 inline void eval_acos(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+   static_assert(number_category<T>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
 
    switch (eval_fpclassify(x))
    {
    case FP_NAN:
    case FP_INFINITE:
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    case FP_ZERO:
       result = get_constant_pi<T>();
@@ -718,13 +724,13 @@ inline void eval_acos(T& result, const T& x)
 
    if (c > 0)
    {
-      if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+      BOOST_IF_CONSTEXPR(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
       {
          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
          errno  = EDOM;
       }
       else
-         BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+         BOOST_MP_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
       return;
    }
    else if (c == 0)
@@ -736,7 +742,7 @@ inline void eval_acos(T& result, const T& x)
       return;
    }
 
-   typedef typename mpl::front<typename T::float_types>::type fp_type;
+   using fp_type = typename std::tuple_element<0, typename T::float_types>::type;
 
    if (xx.compare(fp_type(1e-3)) < 0)
    {
@@ -778,9 +784,9 @@ inline void eval_acos(T& result, const T& x)
    }
 
 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
-   typedef typename boost::multiprecision::detail::canonical<long double, T>::type guess_type;
+   using guess_type = typename boost::multiprecision::detail::canonical<long double, T>::type;
 #else
-   typedef fp_type guess_type;
+   using guess_type = fp_type;
 #endif
    // Get initial estimate using standard math function asin.
    guess_type dd;
@@ -793,8 +799,8 @@ inline void eval_acos(T& result, const T& x)
    // have at least 2/3 of the digits correct on the assumption that the correction
    // we've just added will finish the job...
 
-   boost::intmax_t current_precision = eval_ilogb(result);
-   boost::intmax_t target_precision = std::numeric_limits<number<T> >::is_specialized ?
+   std::intmax_t current_precision = eval_ilogb(result);
+   std::intmax_t target_precision = std::numeric_limits<number<T> >::is_specialized ?
       current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
       : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 2) / 3;
 
@@ -817,10 +823,10 @@ inline void eval_acos(T& result, const T& x)
 template <class T>
 void eval_atan(T& result, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
-   typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type  si_type;
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
-   typedef typename mpl::front<typename T::float_types>::type                          fp_type;
+   static_assert(number_category<T>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
+   using si_type = typename boost::multiprecision::detail::canonical<std::int32_t, T>::type ;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
+   using fp_type = typename std::tuple_element<0, typename T::float_types>::type                         ;
 
    switch (eval_fpclassify(x))
    {
@@ -891,8 +897,8 @@ void eval_atan(T& result, const T& x)
    // have at least 2/3 of the digits correct on the assumption that the correction
    // we've just added will finish the job...
 
-   boost::intmax_t current_precision = eval_ilogb(result);
-   boost::intmax_t target_precision  = std::numeric_limits<number<T> >::is_specialized ?
+   std::intmax_t current_precision = eval_ilogb(result);
+   std::intmax_t target_precision  = std::numeric_limits<number<T> >::is_specialized ?
       current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3
       : current_precision - 1 - (boost::multiprecision::detail::digits2<number<T> >::value() * 2) / 3;
 
@@ -916,7 +922,7 @@ void eval_atan(T& result, const T& x)
 template <class T>
 void eval_atan2(T& result, const T& y, const T& x)
 {
-   BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
+   static_assert(number_category<T>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
    if (&result == &y)
    {
       T temp(y);
@@ -930,7 +936,7 @@ void eval_atan2(T& result, const T& y, const T& x)
       return;
    }
 
-   typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
+   using ui_type = typename boost::multiprecision::detail::canonical<std::uint32_t, T>::type;
 
    switch (eval_fpclassify(y))
    {
@@ -1028,20 +1034,20 @@ void eval_atan2(T& result, const T& y, const T& x)
    }
 }
 template <class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const T& x, const A& a)
+inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_atan2(T& result, const T& x, const A& a)
 {
-   typedef typename boost::multiprecision::detail::canonical<A, T>::type          canonical_type;
-   typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
+   using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type         ;
+   using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
    cast_type                                                                      c;
    c = a;
    eval_atan2(result, x, c);
 }
 
 template <class T, class A>
-inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const A& x, const T& a)
+inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_atan2(T& result, const A& x, const T& a)
 {
-   typedef typename boost::multiprecision::detail::canonical<A, T>::type          canonical_type;
-   typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
+   using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type         ;
+   using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
    cast_type                                                                      c;
    c = x;
    eval_atan2(result, c, a);