annotate DEPENDENCIES/generic/include/boost/math/special_functions/ellint_d.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // Copyright (c) 2006 Xiaogang Zhang
Chris@102 2 // Copyright (c) 2006 John Maddock
Chris@102 3 // Use, modification and distribution are subject to the
Chris@102 4 // Boost Software License, Version 1.0. (See accompanying file
Chris@102 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@102 6 //
Chris@102 7 // History:
Chris@102 8 // XZ wrote the original of this file as part of the Google
Chris@102 9 // Summer of Code 2006. JM modified it to fit into the
Chris@102 10 // Boost.Math conceptual framework better, and to ensure
Chris@102 11 // that the code continues to work no matter how many digits
Chris@102 12 // type T has.
Chris@102 13
Chris@102 14 #ifndef BOOST_MATH_ELLINT_D_HPP
Chris@102 15 #define BOOST_MATH_ELLINT_D_HPP
Chris@102 16
Chris@102 17 #ifdef _MSC_VER
Chris@102 18 #pragma once
Chris@102 19 #endif
Chris@102 20
Chris@102 21 #include <boost/math/special_functions/math_fwd.hpp>
Chris@102 22 #include <boost/math/special_functions/ellint_rf.hpp>
Chris@102 23 #include <boost/math/special_functions/ellint_rd.hpp>
Chris@102 24 #include <boost/math/special_functions/ellint_rg.hpp>
Chris@102 25 #include <boost/math/constants/constants.hpp>
Chris@102 26 #include <boost/math/policies/error_handling.hpp>
Chris@102 27 #include <boost/math/tools/workaround.hpp>
Chris@102 28 #include <boost/math/special_functions/round.hpp>
Chris@102 29
Chris@102 30 // Elliptic integrals (complete and incomplete) of the second kind
Chris@102 31 // Carlson, Numerische Mathematik, vol 33, 1 (1979)
Chris@102 32
Chris@102 33 namespace boost { namespace math {
Chris@102 34
Chris@102 35 template <class T1, class T2, class Policy>
Chris@102 36 typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol);
Chris@102 37
Chris@102 38 namespace detail{
Chris@102 39
Chris@102 40 template <typename T, typename Policy>
Chris@102 41 T ellint_d_imp(T k, const Policy& pol);
Chris@102 42
Chris@102 43 // Elliptic integral (Legendre form) of the second kind
Chris@102 44 template <typename T, typename Policy>
Chris@102 45 T ellint_d_imp(T phi, T k, const Policy& pol)
Chris@102 46 {
Chris@102 47 BOOST_MATH_STD_USING
Chris@102 48 using namespace boost::math::tools;
Chris@102 49 using namespace boost::math::constants;
Chris@102 50
Chris@102 51 bool invert = false;
Chris@102 52 if(phi < 0)
Chris@102 53 {
Chris@102 54 phi = fabs(phi);
Chris@102 55 invert = true;
Chris@102 56 }
Chris@102 57
Chris@102 58 T result;
Chris@102 59
Chris@102 60 if(phi >= tools::max_value<T>())
Chris@102 61 {
Chris@102 62 // Need to handle infinity as a special case:
Chris@102 63 result = policies::raise_overflow_error<T>("boost::math::ellint_e<%1%>(%1%,%1%)", 0, pol);
Chris@102 64 }
Chris@102 65 else if(phi > 1 / tools::epsilon<T>())
Chris@102 66 {
Chris@102 67 // Phi is so large that phi%pi is necessarily zero (or garbage),
Chris@102 68 // just return the second part of the duplication formula:
Chris@102 69 result = 2 * phi * ellint_d_imp(k, pol) / constants::pi<T>();
Chris@102 70 }
Chris@102 71 else
Chris@102 72 {
Chris@102 73 // Carlson's algorithm works only for |phi| <= pi/2,
Chris@102 74 // use the integrand's periodicity to normalize phi
Chris@102 75 //
Chris@102 76 T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
Chris@102 77 T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
Chris@102 78 int s = 1;
Chris@102 79 if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
Chris@102 80 {
Chris@102 81 m += 1;
Chris@102 82 s = -1;
Chris@102 83 rphi = constants::half_pi<T>() - rphi;
Chris@102 84 }
Chris@102 85 T sinp = sin(rphi);
Chris@102 86 T cosp = cos(rphi);
Chris@102 87 T c = 1 / (sinp * sinp);
Chris@102 88 T cm1 = cosp * cosp / (sinp * sinp); // c - 1
Chris@102 89 T k2 = k * k;
Chris@102 90 if(k2 > 1)
Chris@102 91 {
Chris@102 92 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);
Chris@102 93 }
Chris@102 94 else if(rphi == 0)
Chris@102 95 {
Chris@102 96 result = 0;
Chris@102 97 }
Chris@102 98 else
Chris@102 99 {
Chris@102 100 // http://dlmf.nist.gov/19.25#E10
Chris@102 101 result = s * ellint_rd_imp(cm1, T(c - k2), c, pol) / 3;
Chris@102 102 }
Chris@102 103 if(m != 0)
Chris@102 104 result += m * ellint_d_imp(k, pol);
Chris@102 105 }
Chris@102 106 return invert ? T(-result) : result;
Chris@102 107 }
Chris@102 108
Chris@102 109 // Complete elliptic integral (Legendre form) of the second kind
Chris@102 110 template <typename T, typename Policy>
Chris@102 111 T ellint_d_imp(T k, const Policy& pol)
Chris@102 112 {
Chris@102 113 BOOST_MATH_STD_USING
Chris@102 114 using namespace boost::math::tools;
Chris@102 115
Chris@102 116 if (abs(k) > 1)
Chris@102 117 {
Chris@102 118 return policies::raise_domain_error<T>("boost::math::ellint_e<%1%>(%1%)",
Chris@102 119 "Got k = %1%, function requires |k| <= 1", k, pol);
Chris@102 120 }
Chris@102 121 if (abs(k) == 1)
Chris@102 122 {
Chris@102 123 return static_cast<T>(1);
Chris@102 124 }
Chris@102 125 if(fabs(k) <= tools::root_epsilon<T>())
Chris@102 126 return constants::pi<T>() / 4;
Chris@102 127
Chris@102 128 T x = 0;
Chris@102 129 T t = k * k;
Chris@102 130 T y = 1 - t;
Chris@102 131 T z = 1;
Chris@102 132 T value = ellint_rd_imp(x, y, z, pol) / 3;
Chris@102 133
Chris@102 134 return value;
Chris@102 135 }
Chris@102 136
Chris@102 137 template <typename T, typename Policy>
Chris@102 138 inline typename tools::promote_args<T>::type ellint_d(T k, const Policy& pol, const mpl::true_&)
Chris@102 139 {
Chris@102 140 typedef typename tools::promote_args<T>::type result_type;
Chris@102 141 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@102 142 return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_d_imp(static_cast<value_type>(k), pol), "boost::math::ellint_d<%1%>(%1%)");
Chris@102 143 }
Chris@102 144
Chris@102 145 // Elliptic integral (Legendre form) of the second kind
Chris@102 146 template <class T1, class T2>
Chris@102 147 inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const mpl::false_&)
Chris@102 148 {
Chris@102 149 return boost::math::ellint_d(k, phi, policies::policy<>());
Chris@102 150 }
Chris@102 151
Chris@102 152 } // detail
Chris@102 153
Chris@102 154 // Complete elliptic integral (Legendre form) of the second kind
Chris@102 155 template <typename T>
Chris@102 156 inline typename tools::promote_args<T>::type ellint_d(T k)
Chris@102 157 {
Chris@102 158 return ellint_d(k, policies::policy<>());
Chris@102 159 }
Chris@102 160
Chris@102 161 // Elliptic integral (Legendre form) of the second kind
Chris@102 162 template <class T1, class T2>
Chris@102 163 inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi)
Chris@102 164 {
Chris@102 165 typedef typename policies::is_policy<T2>::type tag_type;
Chris@102 166 return detail::ellint_d(k, phi, tag_type());
Chris@102 167 }
Chris@102 168
Chris@102 169 template <class T1, class T2, class Policy>
Chris@102 170 inline typename tools::promote_args<T1, T2>::type ellint_d(T1 k, T2 phi, const Policy& pol)
Chris@102 171 {
Chris@102 172 typedef typename tools::promote_args<T1, T2>::type result_type;
Chris@102 173 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@102 174 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%)");
Chris@102 175 }
Chris@102 176
Chris@102 177 }} // namespaces
Chris@102 178
Chris@102 179 #endif // BOOST_MATH_ELLINT_D_HPP
Chris@102 180