Warning, file /include/boost/math/special_functions/cbrt.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_SF_CBRT_HPP
0008 #define BOOST_MATH_SF_CBRT_HPP
0009
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #endif
0013
0014 #include <boost/math/tools/config.hpp>
0015
0016 #ifndef BOOST_MATH_HAS_NVRTC
0017
0018 #include <boost/math/tools/rational.hpp>
0019 #include <boost/math/tools/type_traits.hpp>
0020 #include <boost/math/tools/cstdint.hpp>
0021 #include <boost/math/policies/error_handling.hpp>
0022 #include <boost/math/special_functions/math_fwd.hpp>
0023 #include <boost/math/special_functions/fpclassify.hpp>
0024
0025 namespace boost{ namespace math{
0026
0027 namespace detail
0028 {
0029
0030 struct big_int_type
0031 {
0032 operator std::uintmax_t() const;
0033 };
0034
0035 template <typename T>
0036 struct largest_cbrt_int_type
0037 {
0038 using type = typename std::conditional<
0039 std::is_convertible<big_int_type, T>::value,
0040 std::uintmax_t,
0041 unsigned int
0042 >::type;
0043 };
0044
0045 template <typename T, typename Policy>
0046 BOOST_MATH_GPU_ENABLED T cbrt_imp(T z, const Policy& pol)
0047 {
0048 BOOST_MATH_STD_USING
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 BOOST_MATH_STATIC const T P[] = {
0060 static_cast<T>(0.37568269008611818),
0061 static_cast<T>(1.3304968705558024),
0062 static_cast<T>(-1.4897101632445036),
0063 static_cast<T>(1.2875573098219835),
0064 static_cast<T>(-0.6398703759826468),
0065 static_cast<T>(0.13584489959258635),
0066 };
0067 BOOST_MATH_STATIC const T correction[] = {
0068 static_cast<T>(0.62996052494743658238360530363911),
0069 static_cast<T>(0.79370052598409973737585281963615),
0070 static_cast<T>(1),
0071 static_cast<T>(1.2599210498948731647672106072782),
0072 static_cast<T>(1.5874010519681994747517056392723),
0073 };
0074 if((boost::math::isinf)(z) || (z == 0))
0075 return z;
0076 if(!(boost::math::isfinite)(z))
0077 {
0078 return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol);
0079 }
0080
0081 int i_exp, sign(1);
0082 if(z < 0)
0083 {
0084 z = -z;
0085 sign = -sign;
0086 }
0087
0088 T guess = frexp(z, &i_exp);
0089 int original_i_exp = i_exp;
0090 guess = tools::evaluate_polynomial(P, guess);
0091 int i_exp3 = i_exp / 3;
0092
0093 using shift_type = typename largest_cbrt_int_type<T>::type;
0094
0095 static_assert( ::std::numeric_limits<shift_type>::radix == 2, "The radix of the type to shift to must be 2.");
0096
0097 if(abs(i_exp3) < std::numeric_limits<shift_type>::digits)
0098 {
0099 if(i_exp3 > 0)
0100 guess *= shift_type(1u) << i_exp3;
0101 else
0102 guess /= shift_type(1u) << -i_exp3;
0103 }
0104 else
0105 {
0106 guess = ldexp(guess, i_exp3);
0107 }
0108 i_exp %= 3;
0109 guess *= correction[i_exp + 2];
0110
0111
0112
0113
0114
0115
0116
0117 using prec = typename policies::precision<T, Policy>::type;
0118 constexpr auto prec3 = prec::value / 3;
0119 constexpr auto new_prec = prec3 + 3;
0120 using new_policy = typename policies::normalise<Policy, policies::digits2<new_prec>>::type;
0121
0122
0123
0124
0125 T eps = (new_prec > 3) ? policies::get_epsilon<T, new_policy>() : ldexp(T(1), -2 - tools::digits<T>() / 3);
0126 T diff;
0127
0128 if(original_i_exp < std::numeric_limits<T>::max_exponent - 3)
0129 {
0130
0131
0132
0133 do
0134 {
0135 T g3 = guess * guess * guess;
0136 diff = (g3 + z + z) / (g3 + g3 + z);
0137 guess *= diff;
0138 }
0139 while(fabs(1 - diff) > eps);
0140 }
0141 else
0142 {
0143
0144
0145
0146
0147 do
0148 {
0149 T g2 = guess * guess;
0150 diff = (g2 - z / guess) / (2 * guess + z / g2);
0151 guess -= diff;
0152 }
0153 while((guess * eps) < fabs(diff));
0154 }
0155
0156 return sign * guess;
0157 }
0158
0159 }
0160
0161 template <typename T, typename Policy>
0162 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type cbrt(T z, const Policy& pol)
0163 {
0164 using result_type = typename tools::promote_args<T>::type;
0165 using value_type = typename policies::evaluation<result_type, Policy>::type;
0166 return static_cast<result_type>(detail::cbrt_imp(value_type(z), pol));
0167 }
0168
0169 template <typename T>
0170 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type cbrt(T z)
0171 {
0172 return cbrt(z, policies::policy<>());
0173 }
0174
0175 }
0176 }
0177
0178 #else
0179
0180 namespace boost {
0181 namespace math {
0182
0183 template <typename T>
0184 BOOST_MATH_GPU_ENABLED double cbrt(T x)
0185 {
0186 return ::cbrt(x);
0187 }
0188
0189 BOOST_MATH_GPU_ENABLED inline float cbrt(float x)
0190 {
0191 return ::cbrtf(x);
0192 }
0193
0194 template <typename T, typename Policy>
0195 BOOST_MATH_GPU_ENABLED double cbrt(T x, const Policy&)
0196 {
0197 return ::cbrt(x);
0198 }
0199
0200 template <typename Policy>
0201 BOOST_MATH_GPU_ENABLED float cbrt(float x, const Policy&)
0202 {
0203 return ::cbrtf(x);
0204 }
0205
0206 }
0207 }
0208
0209 #endif
0210
0211 #endif
0212
0213
0214
0215