Warning, file /include/boost/math/special_functions/ellint_rg.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 #ifndef BOOST_MATH_ELLINT_RG_HPP
0007 #define BOOST_MATH_ELLINT_RG_HPP
0008
0009 #ifdef _MSC_VER
0010 #pragma once
0011 #endif
0012
0013 #include <boost/math/tools/config.hpp>
0014 #include <boost/math/special_functions/math_fwd.hpp>
0015 #include <boost/math/constants/constants.hpp>
0016 #include <boost/math/policies/error_handling.hpp>
0017 #include <boost/math/special_functions/ellint_rd.hpp>
0018 #include <boost/math/special_functions/ellint_rf.hpp>
0019 #include <boost/math/special_functions/pow.hpp>
0020
0021 namespace boost { namespace math { namespace detail{
0022
0023 template <typename T, typename Policy>
0024 BOOST_MATH_GPU_ENABLED T ellint_rg_imp(T x, T y, T z, const Policy& pol)
0025 {
0026 BOOST_MATH_STD_USING
0027 constexpr auto function = "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)";
0028
0029 if(x < 0 || y < 0 || z < 0)
0030 {
0031 return policies::raise_domain_error<T>(function, "domain error, all arguments must be non-negative, only sensible result is %1%.", boost::math::numeric_limits<T>::quiet_NaN(), pol);
0032 }
0033
0034
0035
0036
0037
0038 if(x < y)
0039 BOOST_MATH_GPU_SAFE_SWAP(x, y);
0040 if(x < z)
0041 BOOST_MATH_GPU_SAFE_SWAP(x, z);
0042 if(y > z)
0043 BOOST_MATH_GPU_SAFE_SWAP(y, z);
0044
0045 BOOST_MATH_ASSERT(x >= z);
0046 BOOST_MATH_ASSERT(z >= y);
0047
0048
0049
0050 if(x == z)
0051 {
0052 if(y == z)
0053 {
0054
0055
0056 return sqrt(x);
0057 }
0058 else if(y == 0)
0059 {
0060
0061 return constants::pi<T>() * sqrt(x) / 4;
0062 }
0063 else
0064 {
0065
0066 BOOST_MATH_GPU_SAFE_SWAP(x, y);
0067 return (x == 0) ? T(sqrt(z) / 2) : T((z * ellint_rc_imp(x, z, pol) + sqrt(x)) / 2);
0068 }
0069 }
0070 else if(y == z)
0071 {
0072 BOOST_MATH_ASSERT(x > 0);
0073 return (y == 0) ? T(sqrt(x) / 2) : T((y * ellint_rc_imp(x, y, pol) + sqrt(x)) / 2);
0074 }
0075 else if(y == 0)
0076 {
0077 BOOST_MATH_GPU_SAFE_SWAP(y, z);
0078
0079
0080
0081
0082 T xn = sqrt(x);
0083 T yn = sqrt(y);
0084 T x0 = xn;
0085 T y0 = yn;
0086 T sum = 0;
0087 T sum_pow = 0.25f;
0088
0089 while(fabs(xn - yn) >= T(2.7) * tools::root_epsilon<T>() * fabs(xn))
0090 {
0091 T t = sqrt(xn * yn);
0092 xn = (xn + yn) / 2;
0093 yn = t;
0094 sum_pow *= 2;
0095 sum += sum_pow * boost::math::pow<2>(xn - yn);
0096 }
0097 T RF = constants::pi<T>() / (xn + yn);
0098 return ((boost::math::pow<2>((x0 + y0) / 2) - sum) * RF) / 2;
0099 }
0100 return (z * ellint_rf_imp(x, y, z, pol)
0101 - (x - z) * (y - z) * ellint_rd_imp(x, y, z, pol) / 3
0102 + sqrt(x * y / z)) / 2;
0103 }
0104
0105 }
0106
0107 template <class T1, class T2, class T3, class Policy>
0108 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T1, T2, T3>::type
0109 ellint_rg(T1 x, T2 y, T3 z, const Policy& pol)
0110 {
0111 typedef typename tools::promote_args<T1, T2, T3>::type result_type;
0112 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0113 return policies::checked_narrowing_cast<result_type, Policy>(
0114 detail::ellint_rg_imp(
0115 static_cast<value_type>(x),
0116 static_cast<value_type>(y),
0117 static_cast<value_type>(z), pol), "boost::math::ellint_rf<%1%>(%1%,%1%,%1%)");
0118 }
0119
0120 template <class T1, class T2, class T3>
0121 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T1, T2, T3>::type
0122 ellint_rg(T1 x, T2 y, T3 z)
0123 {
0124 return ellint_rg(x, y, z, policies::policy<>());
0125 }
0126
0127 }}
0128
0129 #endif
0130