annotate DEPENDENCIES/generic/include/boost/math/special_functions/cbrt.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // (C) Copyright John Maddock 2006.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #ifndef BOOST_MATH_SF_CBRT_HPP
Chris@16 7 #define BOOST_MATH_SF_CBRT_HPP
Chris@16 8
Chris@16 9 #ifdef _MSC_VER
Chris@16 10 #pragma once
Chris@16 11 #endif
Chris@16 12
Chris@16 13 #include <boost/math/tools/rational.hpp>
Chris@16 14 #include <boost/math/policies/error_handling.hpp>
Chris@16 15 #include <boost/math/special_functions/math_fwd.hpp>
Chris@16 16 #include <boost/math/special_functions/fpclassify.hpp>
Chris@16 17 #include <boost/mpl/divides.hpp>
Chris@16 18 #include <boost/mpl/plus.hpp>
Chris@16 19 #include <boost/mpl/if.hpp>
Chris@16 20 #include <boost/type_traits/is_convertible.hpp>
Chris@16 21
Chris@16 22 namespace boost{ namespace math{
Chris@16 23
Chris@16 24 namespace detail
Chris@16 25 {
Chris@16 26
Chris@16 27 struct big_int_type
Chris@16 28 {
Chris@16 29 operator boost::uintmax_t()const;
Chris@16 30 };
Chris@16 31
Chris@16 32 template <class T>
Chris@16 33 struct largest_cbrt_int_type
Chris@16 34 {
Chris@16 35 typedef typename mpl::if_<
Chris@16 36 boost::is_convertible<big_int_type, T>,
Chris@16 37 boost::uintmax_t,
Chris@16 38 unsigned int
Chris@16 39 >::type type;
Chris@16 40 };
Chris@16 41
Chris@16 42 template <class T, class Policy>
Chris@16 43 T cbrt_imp(T z, const Policy& pol)
Chris@16 44 {
Chris@16 45 BOOST_MATH_STD_USING
Chris@16 46 //
Chris@16 47 // cbrt approximation for z in the range [0.5,1]
Chris@16 48 // It's hard to say what number of terms gives the optimum
Chris@16 49 // trade off between precision and performance, this seems
Chris@16 50 // to be about the best for double precision.
Chris@16 51 //
Chris@16 52 // Maximum Deviation Found: 1.231e-006
Chris@16 53 // Expected Error Term: -1.231e-006
Chris@16 54 // Maximum Relative Change in Control Points: 5.982e-004
Chris@16 55 //
Chris@16 56 static const T P[] = {
Chris@16 57 static_cast<T>(0.37568269008611818),
Chris@16 58 static_cast<T>(1.3304968705558024),
Chris@16 59 static_cast<T>(-1.4897101632445036),
Chris@16 60 static_cast<T>(1.2875573098219835),
Chris@16 61 static_cast<T>(-0.6398703759826468),
Chris@16 62 static_cast<T>(0.13584489959258635),
Chris@16 63 };
Chris@16 64 static const T correction[] = {
Chris@16 65 static_cast<T>(0.62996052494743658238360530363911), // 2^-2/3
Chris@16 66 static_cast<T>(0.79370052598409973737585281963615), // 2^-1/3
Chris@16 67 static_cast<T>(1),
Chris@16 68 static_cast<T>(1.2599210498948731647672106072782), // 2^1/3
Chris@16 69 static_cast<T>(1.5874010519681994747517056392723), // 2^2/3
Chris@16 70 };
Chris@16 71
Chris@16 72 if(!(boost::math::isfinite)(z))
Chris@16 73 {
Chris@16 74 return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol);
Chris@16 75 }
Chris@16 76
Chris@16 77 int i_exp, sign(1);
Chris@16 78 if(z < 0)
Chris@16 79 {
Chris@16 80 z = -z;
Chris@16 81 sign = -sign;
Chris@16 82 }
Chris@16 83 if(z == 0)
Chris@16 84 return 0;
Chris@16 85
Chris@16 86 T guess = frexp(z, &i_exp);
Chris@16 87 int original_i_exp = i_exp; // save for later
Chris@16 88 guess = tools::evaluate_polynomial(P, guess);
Chris@16 89 int i_exp3 = i_exp / 3;
Chris@16 90
Chris@16 91 typedef typename largest_cbrt_int_type<T>::type shift_type;
Chris@16 92
Chris@16 93 BOOST_STATIC_ASSERT( ::std::numeric_limits<shift_type>::radix == 2);
Chris@16 94
Chris@16 95 if(abs(i_exp3) < std::numeric_limits<shift_type>::digits)
Chris@16 96 {
Chris@16 97 if(i_exp3 > 0)
Chris@16 98 guess *= shift_type(1u) << i_exp3;
Chris@16 99 else
Chris@16 100 guess /= shift_type(1u) << -i_exp3;
Chris@16 101 }
Chris@16 102 else
Chris@16 103 {
Chris@16 104 guess = ldexp(guess, i_exp3);
Chris@16 105 }
Chris@16 106 i_exp %= 3;
Chris@16 107 guess *= correction[i_exp + 2];
Chris@16 108 //
Chris@16 109 // Now inline Halley iteration.
Chris@16 110 // We do this here rather than calling tools::halley_iterate since we can
Chris@16 111 // simplify the expressions algebraically, and don't need most of the error
Chris@16 112 // checking of the boilerplate version as we know in advance that the function
Chris@16 113 // is well behaved...
Chris@16 114 //
Chris@16 115 typedef typename policies::precision<T, Policy>::type prec;
Chris@16 116 typedef typename mpl::divides<prec, mpl::int_<3> >::type prec3;
Chris@16 117 typedef typename mpl::plus<prec3, mpl::int_<3> >::type new_prec;
Chris@16 118 typedef typename policies::normalise<Policy, policies::digits2<new_prec::value> >::type new_policy;
Chris@16 119 //
Chris@16 120 // Epsilon calculation uses compile time arithmetic when it's available for type T,
Chris@16 121 // otherwise uses ldexp to calculate at runtime:
Chris@16 122 //
Chris@16 123 T eps = (new_prec::value > 3) ? policies::get_epsilon<T, new_policy>() : ldexp(T(1), -2 - tools::digits<T>() / 3);
Chris@16 124 T diff;
Chris@16 125
Chris@16 126 if(original_i_exp < std::numeric_limits<T>::max_exponent - 3)
Chris@16 127 {
Chris@16 128 //
Chris@16 129 // Safe from overflow, use the fast method:
Chris@16 130 //
Chris@16 131 do
Chris@16 132 {
Chris@16 133 T g3 = guess * guess * guess;
Chris@16 134 diff = (g3 + z + z) / (g3 + g3 + z);
Chris@16 135 guess *= diff;
Chris@16 136 }
Chris@16 137 while(fabs(1 - diff) > eps);
Chris@16 138 }
Chris@16 139 else
Chris@16 140 {
Chris@16 141 //
Chris@16 142 // Either we're ready to overflow, or we can't tell because numeric_limits isn't
Chris@16 143 // available for type T:
Chris@16 144 //
Chris@16 145 do
Chris@16 146 {
Chris@16 147 T g2 = guess * guess;
Chris@16 148 diff = (g2 - z / guess) / (2 * guess + z / g2);
Chris@16 149 guess -= diff;
Chris@16 150 }
Chris@16 151 while((guess * eps) < fabs(diff));
Chris@16 152 }
Chris@16 153
Chris@16 154 return sign * guess;
Chris@16 155 }
Chris@16 156
Chris@16 157 } // namespace detail
Chris@16 158
Chris@16 159 template <class T, class Policy>
Chris@16 160 inline typename tools::promote_args<T>::type cbrt(T z, const Policy& pol)
Chris@16 161 {
Chris@16 162 typedef typename tools::promote_args<T>::type result_type;
Chris@16 163 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 164 return static_cast<result_type>(detail::cbrt_imp(value_type(z), pol));
Chris@16 165 }
Chris@16 166
Chris@16 167 template <class T>
Chris@16 168 inline typename tools::promote_args<T>::type cbrt(T z)
Chris@16 169 {
Chris@16 170 return cbrt(z, policies::policy<>());
Chris@16 171 }
Chris@16 172
Chris@16 173 } // namespace math
Chris@16 174 } // namespace boost
Chris@16 175
Chris@16 176 #endif // BOOST_MATH_SF_CBRT_HPP
Chris@16 177
Chris@16 178
Chris@16 179
Chris@16 180