File indexing completed on 2025-10-20 08:29:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_MATH_ELLINT_D_HPP
0016 #define BOOST_MATH_ELLINT_D_HPP
0017
0018 #ifdef _MSC_VER
0019 #pragma once
0020 #endif
0021
0022 #include <boost/math/tools/config.hpp>
0023 #include <boost/math/tools/type_traits.hpp>
0024 #include <boost/math/special_functions/math_fwd.hpp>
0025 #include <boost/math/special_functions/ellint_rf.hpp>
0026 #include <boost/math/special_functions/ellint_rd.hpp>
0027 #include <boost/math/special_functions/ellint_rg.hpp>
0028 #include <boost/math/constants/constants.hpp>
0029 #include <boost/math/policies/error_handling.hpp>
0030 #include <boost/math/tools/workaround.hpp>
0031 #include <boost/math/special_functions/round.hpp>
0032
0033
0034
0035
0036 namespace boost { namespace math {
0037
0038 template <class T1, class T2, class Policy>
0039 BOOST_MATH_GPU_ENABLED typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol);
0040
0041 namespace detail{
0042
0043 template <typename T, typename Policy>
0044 BOOST_MATH_GPU_ENABLED T ellint_d_imp(T k, const Policy& pol);
0045
0046
0047 template <typename T, typename Policy>
0048 BOOST_MATH_GPU_ENABLED T ellint_d_imp(T phi, T k, const Policy& pol)
0049 {
0050 BOOST_MATH_STD_USING
0051 using namespace boost::math::tools;
0052 using namespace boost::math::constants;
0053
0054 bool invert = false;
0055 if(phi < 0)
0056 {
0057 phi = fabs(phi);
0058 invert = true;
0059 }
0060
0061 T result;
0062
0063 if(phi >= tools::max_value<T>())
0064 {
0065
0066 result = policies::raise_overflow_error<T>("boost::math::ellint_d<%1%>(%1%,%1%)", nullptr, pol);
0067 }
0068 else if(phi > 1 / tools::epsilon<T>())
0069 {
0070
0071
0072 result = 2 * phi * ellint_d_imp(k, pol) / constants::pi<T>();
0073 }
0074 else
0075 {
0076
0077
0078
0079 T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
0080 T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
0081 int s = 1;
0082 if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5))
0083 {
0084 m += 1;
0085 s = -1;
0086 rphi = constants::half_pi<T>() - rphi;
0087 }
0088 BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
0089 BOOST_MATH_INSTRUMENT_VARIABLE(m);
0090 T sinp = sin(rphi);
0091 T cosp = cos(rphi);
0092 BOOST_MATH_INSTRUMENT_VARIABLE(sinp);
0093 BOOST_MATH_INSTRUMENT_VARIABLE(cosp);
0094 T c = 1 / (sinp * sinp);
0095 T cm1 = cosp * cosp / (sinp * sinp);
0096 T k2 = k * k;
0097 if(k2 * sinp * sinp > 1)
0098 {
0099 return policies::raise_domain_error<T>("boost::math::ellint_d<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol);
0100 }
0101 else if(rphi == 0)
0102 {
0103 result = 0;
0104 }
0105 else
0106 {
0107
0108 result = s * ellint_rd_imp(cm1, T(c - k2), c, pol) / 3;
0109 BOOST_MATH_INSTRUMENT_VARIABLE(result);
0110 }
0111 if(m != 0)
0112 result += m * ellint_d_imp(k, pol);
0113 }
0114 return invert ? T(-result) : result;
0115 }
0116
0117
0118 template <typename T, typename Policy>
0119 BOOST_MATH_GPU_ENABLED T ellint_d_imp(T k, const Policy& pol)
0120 {
0121 BOOST_MATH_STD_USING
0122 using namespace boost::math::tools;
0123
0124 if (abs(k) >= 1)
0125 {
0126 return policies::raise_domain_error<T>("boost::math::ellint_d<%1%>(%1%)", "Got k = %1%, function requires |k| <= 1", k, pol);
0127 }
0128 if(fabs(k) <= tools::root_epsilon<T>())
0129 return constants::pi<T>() / 4;
0130
0131 T x = 0;
0132 T t = k * k;
0133 T y = 1 - t;
0134 T z = 1;
0135 T value = ellint_rd_imp(x, y, z, pol) / 3;
0136
0137 return value;
0138 }
0139
0140 template <typename T, typename Policy>
0141 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type ellint_d(T k, const Policy& pol, const boost::math::true_type&)
0142 {
0143 typedef typename tools::promote_args<T>::type result_type;
0144 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0145 return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_d_imp(static_cast<value_type>(k), pol), "boost::math::ellint_d<%1%>(%1%)");
0146 }
0147
0148
0149 template <class T1, class T2>
0150 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const boost::math::false_type&)
0151 {
0152 return boost::math::ellint_d(k, phi, policies::policy<>());
0153 }
0154
0155 }
0156
0157
0158 template <typename T>
0159 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type ellint_d(T k)
0160 {
0161 return ellint_d(k, policies::policy<>());
0162 }
0163
0164
0165 template <class T1, class T2>
0166 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi)
0167 {
0168 typedef typename policies::is_policy<T2>::type tag_type;
0169 return detail::ellint_d(k, phi, tag_type());
0170 }
0171
0172 template <class T1, class T2, class Policy>
0173 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol)
0174 {
0175 typedef typename tools::promote_args<T1, T2>::type result_type;
0176 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0177 return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_d_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::ellint_2<%1%>(%1%,%1%)");
0178 }
0179
0180 }}
0181
0182 #endif
0183