annotate DEPENDENCIES/generic/include/boost/math/special_functions/jacobi_elliptic.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 c530137014c0
children
rev   line source
Chris@16 1 // Copyright John Maddock 2012.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0.
Chris@16 4 // (See accompanying file LICENSE_1_0.txt
Chris@16 5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 #ifndef BOOST_MATH_JACOBI_ELLIPTIC_HPP
Chris@16 8 #define BOOST_MATH_JACOBI_ELLIPTIC_HPP
Chris@16 9
Chris@16 10 #include <boost/math/tools/precision.hpp>
Chris@16 11 #include <boost/math/tools/promotion.hpp>
Chris@16 12 #include <boost/math/policies/error_handling.hpp>
Chris@101 13 #include <boost/math/special_functions/math_fwd.hpp>
Chris@16 14
Chris@16 15 namespace boost{ namespace math{
Chris@16 16
Chris@16 17 namespace detail{
Chris@16 18
Chris@16 19 template <class T, class Policy>
Chris@16 20 T jacobi_recurse(const T& x, const T& k, T anm1, T bnm1, unsigned N, T* pTn, const Policy& pol)
Chris@16 21 {
Chris@16 22 BOOST_MATH_STD_USING
Chris@16 23 ++N;
Chris@16 24 T Tn;
Chris@16 25 T cn = (anm1 - bnm1) / 2;
Chris@16 26 T an = (anm1 + bnm1) / 2;
Chris@16 27 if(cn < policies::get_epsilon<T, Policy>())
Chris@16 28 {
Chris@16 29 Tn = ldexp(T(1), (int)N) * x * an;
Chris@16 30 }
Chris@16 31 else
Chris@16 32 Tn = jacobi_recurse<T>(x, k, an, sqrt(anm1 * bnm1), N, 0, pol);
Chris@16 33 if(pTn)
Chris@16 34 *pTn = Tn;
Chris@16 35 return (Tn + asin((cn / an) * sin(Tn))) / 2;
Chris@16 36 }
Chris@16 37
Chris@16 38 template <class T, class Policy>
Chris@16 39 T jacobi_imp(const T& x, const T& k, T* cn, T* dn, const Policy& pol, const char* function)
Chris@16 40 {
Chris@16 41 BOOST_MATH_STD_USING
Chris@16 42 if(k < 0)
Chris@16 43 {
Chris@16 44 *cn = policies::raise_domain_error<T>(function, "Modulus k must be positive but got %1%.", k, pol);
Chris@16 45 *dn = *cn;
Chris@16 46 return *cn;
Chris@16 47 }
Chris@16 48 if(k > 1)
Chris@16 49 {
Chris@16 50 T xp = x * k;
Chris@16 51 T kp = 1 / k;
Chris@16 52 T snp, cnp, dnp;
Chris@16 53 snp = jacobi_imp(xp, kp, &cnp, &dnp, pol, function);
Chris@16 54 *cn = dnp;
Chris@16 55 *dn = cnp;
Chris@16 56 return snp * kp;
Chris@16 57 }
Chris@16 58 //
Chris@16 59 // Special cases first:
Chris@16 60 //
Chris@16 61 if(x == 0)
Chris@16 62 {
Chris@16 63 *cn = *dn = 1;
Chris@16 64 return 0;
Chris@16 65 }
Chris@16 66 if(k == 0)
Chris@16 67 {
Chris@16 68 *cn = cos(x);
Chris@16 69 *dn = 1;
Chris@16 70 return sin(x);
Chris@16 71 }
Chris@16 72 if(k == 1)
Chris@16 73 {
Chris@16 74 *cn = *dn = 1 / cosh(x);
Chris@16 75 return tanh(x);
Chris@16 76 }
Chris@16 77 //
Chris@16 78 // Asymptotic forms from A&S 16.13:
Chris@16 79 //
Chris@16 80 if(k < tools::forth_root_epsilon<T>())
Chris@16 81 {
Chris@16 82 T su = sin(x);
Chris@16 83 T cu = cos(x);
Chris@16 84 T m = k * k;
Chris@16 85 *dn = 1 - m * su * su / 2;
Chris@16 86 *cn = cu + m * (x - su * cu) * su / 4;
Chris@16 87 return su - m * (x - su * cu) * cu / 4;
Chris@16 88 }
Chris@16 89 /* Can't get this to work to adequate precision - disabled for now...
Chris@16 90 //
Chris@16 91 // Asymptotic forms from A&S 16.15:
Chris@16 92 //
Chris@16 93 if(k > 1 - tools::root_epsilon<T>())
Chris@16 94 {
Chris@16 95 T tu = tanh(x);
Chris@16 96 T su = sinh(x);
Chris@16 97 T cu = cosh(x);
Chris@16 98 T sec = 1 / cu;
Chris@16 99 T kp = 1 - k;
Chris@16 100 T m1 = 2 * kp - kp * kp;
Chris@16 101 *dn = sec + m1 * (su * cu + x) * tu * sec / 4;
Chris@16 102 *cn = sec - m1 * (su * cu - x) * tu * sec / 4;
Chris@16 103 T sn = tu;
Chris@16 104 T sn2 = m1 * (x * sec * sec - tu) / 4;
Chris@16 105 T sn3 = (72 * x * cu + 4 * (8 * x * x - 5) * su - 19 * sinh(3 * x) + sinh(5 * x)) * sec * sec * sec * m1 * m1 / 512;
Chris@16 106 return sn + sn2 - sn3;
Chris@16 107 }*/
Chris@16 108 T T1;
Chris@16 109 T kc = 1 - k;
Chris@16 110 T k_prime = k < 0.5 ? T(sqrt(1 - k * k)) : T(sqrt(2 * kc - kc * kc));
Chris@16 111 T T0 = jacobi_recurse(x, k, T(1), k_prime, 0, &T1, pol);
Chris@16 112 *cn = cos(T0);
Chris@16 113 *dn = cos(T0) / cos(T1 - T0);
Chris@16 114 return sin(T0);
Chris@16 115 }
Chris@16 116
Chris@16 117 } // namespace detail
Chris@16 118
Chris@16 119 template <class T, class U, class V, class Policy>
Chris@16 120 inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn, const Policy&)
Chris@16 121 {
Chris@16 122 BOOST_FPU_EXCEPTION_GUARD
Chris@16 123 typedef typename tools::promote_args<T>::type result_type;
Chris@16 124 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 125 typedef typename policies::normalise<
Chris@16 126 Policy,
Chris@16 127 policies::promote_float<false>,
Chris@16 128 policies::promote_double<false>,
Chris@16 129 policies::discrete_quantile<>,
Chris@16 130 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 131
Chris@16 132 static const char* function = "boost::math::jacobi_elliptic<%1%>(%1%)";
Chris@16 133
Chris@16 134 value_type sn, cn, dn;
Chris@16 135 sn = detail::jacobi_imp<value_type>(static_cast<value_type>(theta), static_cast<value_type>(k), &cn, &dn, forwarding_policy(), function);
Chris@16 136 if(pcn)
Chris@16 137 *pcn = policies::checked_narrowing_cast<result_type, Policy>(cn, function);
Chris@16 138 if(pdn)
Chris@16 139 *pdn = policies::checked_narrowing_cast<result_type, Policy>(dn, function);
Chris@16 140 return policies::checked_narrowing_cast<result_type, Policy>(sn, function);;
Chris@16 141 }
Chris@16 142
Chris@16 143 template <class T, class U, class V>
Chris@16 144 inline typename tools::promote_args<T, U, V>::type jacobi_elliptic(T k, U theta, V* pcn, V* pdn)
Chris@16 145 {
Chris@16 146 return jacobi_elliptic(k, theta, pcn, pdn, policies::policy<>());
Chris@16 147 }
Chris@16 148
Chris@16 149 template <class U, class T, class Policy>
Chris@16 150 inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta, const Policy& pol)
Chris@16 151 {
Chris@16 152 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 153 return jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
Chris@16 154 }
Chris@16 155
Chris@16 156 template <class U, class T>
Chris@16 157 inline typename tools::promote_args<T, U>::type jacobi_sn(U k, T theta)
Chris@16 158 {
Chris@16 159 return jacobi_sn(k, theta, policies::policy<>());
Chris@16 160 }
Chris@16 161
Chris@16 162 template <class T, class U, class Policy>
Chris@16 163 inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta, const Policy& pol)
Chris@16 164 {
Chris@16 165 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 166 result_type cn;
Chris@16 167 jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
Chris@16 168 return cn;
Chris@16 169 }
Chris@16 170
Chris@16 171 template <class T, class U>
Chris@16 172 inline typename tools::promote_args<T, U>::type jacobi_cn(T k, U theta)
Chris@16 173 {
Chris@16 174 return jacobi_cn(k, theta, policies::policy<>());
Chris@16 175 }
Chris@16 176
Chris@16 177 template <class T, class U, class Policy>
Chris@16 178 inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta, const Policy& pol)
Chris@16 179 {
Chris@16 180 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 181 result_type dn;
Chris@16 182 jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
Chris@16 183 return dn;
Chris@16 184 }
Chris@16 185
Chris@16 186 template <class T, class U>
Chris@16 187 inline typename tools::promote_args<T, U>::type jacobi_dn(T k, U theta)
Chris@16 188 {
Chris@16 189 return jacobi_dn(k, theta, policies::policy<>());
Chris@16 190 }
Chris@16 191
Chris@16 192 template <class T, class U, class Policy>
Chris@16 193 inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta, const Policy& pol)
Chris@16 194 {
Chris@16 195 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 196 result_type cn, dn;
Chris@16 197 jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
Chris@16 198 return cn / dn;
Chris@16 199 }
Chris@16 200
Chris@16 201 template <class T, class U>
Chris@16 202 inline typename tools::promote_args<T, U>::type jacobi_cd(T k, U theta)
Chris@16 203 {
Chris@16 204 return jacobi_cd(k, theta, policies::policy<>());
Chris@16 205 }
Chris@16 206
Chris@16 207 template <class T, class U, class Policy>
Chris@16 208 inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta, const Policy& pol)
Chris@16 209 {
Chris@16 210 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 211 result_type cn, dn;
Chris@16 212 jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, &dn, pol);
Chris@16 213 return dn / cn;
Chris@16 214 }
Chris@16 215
Chris@16 216 template <class T, class U>
Chris@16 217 inline typename tools::promote_args<T, U>::type jacobi_dc(T k, U theta)
Chris@16 218 {
Chris@16 219 return jacobi_dc(k, theta, policies::policy<>());
Chris@16 220 }
Chris@16 221
Chris@16 222 template <class T, class U, class Policy>
Chris@16 223 inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta, const Policy& pol)
Chris@16 224 {
Chris@16 225 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 226 return 1 / jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), static_cast<result_type*>(0), pol);
Chris@16 227 }
Chris@16 228
Chris@16 229 template <class T, class U>
Chris@16 230 inline typename tools::promote_args<T, U>::type jacobi_ns(T k, U theta)
Chris@16 231 {
Chris@16 232 return jacobi_ns(k, theta, policies::policy<>());
Chris@16 233 }
Chris@16 234
Chris@16 235 template <class T, class U, class Policy>
Chris@16 236 inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta, const Policy& pol)
Chris@16 237 {
Chris@16 238 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 239 result_type sn, dn;
Chris@16 240 sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
Chris@16 241 return sn / dn;
Chris@16 242 }
Chris@16 243
Chris@16 244 template <class T, class U>
Chris@16 245 inline typename tools::promote_args<T, U>::type jacobi_sd(T k, U theta)
Chris@16 246 {
Chris@16 247 return jacobi_sd(k, theta, policies::policy<>());
Chris@16 248 }
Chris@16 249
Chris@16 250 template <class T, class U, class Policy>
Chris@16 251 inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta, const Policy& pol)
Chris@16 252 {
Chris@16 253 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 254 result_type sn, dn;
Chris@16 255 sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), static_cast<result_type*>(0), &dn, pol);
Chris@16 256 return dn / sn;
Chris@16 257 }
Chris@16 258
Chris@16 259 template <class T, class U>
Chris@16 260 inline typename tools::promote_args<T, U>::type jacobi_ds(T k, U theta)
Chris@16 261 {
Chris@16 262 return jacobi_ds(k, theta, policies::policy<>());
Chris@16 263 }
Chris@16 264
Chris@16 265 template <class T, class U, class Policy>
Chris@16 266 inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta, const Policy& pol)
Chris@16 267 {
Chris@16 268 return 1 / jacobi_cn(k, theta, pol);
Chris@16 269 }
Chris@16 270
Chris@16 271 template <class T, class U>
Chris@16 272 inline typename tools::promote_args<T, U>::type jacobi_nc(T k, U theta)
Chris@16 273 {
Chris@16 274 return jacobi_nc(k, theta, policies::policy<>());
Chris@16 275 }
Chris@16 276
Chris@16 277 template <class T, class U, class Policy>
Chris@16 278 inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta, const Policy& pol)
Chris@16 279 {
Chris@16 280 return 1 / jacobi_dn(k, theta, pol);
Chris@16 281 }
Chris@16 282
Chris@16 283 template <class T, class U>
Chris@16 284 inline typename tools::promote_args<T, U>::type jacobi_nd(T k, U theta)
Chris@16 285 {
Chris@16 286 return jacobi_nd(k, theta, policies::policy<>());
Chris@16 287 }
Chris@16 288
Chris@16 289 template <class T, class U, class Policy>
Chris@16 290 inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta, const Policy& pol)
Chris@16 291 {
Chris@16 292 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 293 result_type sn, cn;
Chris@16 294 sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
Chris@16 295 return sn / cn;
Chris@16 296 }
Chris@16 297
Chris@16 298 template <class T, class U>
Chris@16 299 inline typename tools::promote_args<T, U>::type jacobi_sc(T k, U theta)
Chris@16 300 {
Chris@16 301 return jacobi_sc(k, theta, policies::policy<>());
Chris@16 302 }
Chris@16 303
Chris@16 304 template <class T, class U, class Policy>
Chris@16 305 inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta, const Policy& pol)
Chris@16 306 {
Chris@16 307 typedef typename tools::promote_args<T, U>::type result_type;
Chris@16 308 result_type sn, cn;
Chris@16 309 sn = jacobi_elliptic(static_cast<result_type>(k), static_cast<result_type>(theta), &cn, static_cast<result_type*>(0), pol);
Chris@16 310 return cn / sn;
Chris@16 311 }
Chris@16 312
Chris@16 313 template <class T, class U>
Chris@16 314 inline typename tools::promote_args<T, U>::type jacobi_cs(T k, U theta)
Chris@16 315 {
Chris@16 316 return jacobi_cs(k, theta, policies::policy<>());
Chris@16 317 }
Chris@16 318
Chris@16 319 }} // namespaces
Chris@16 320
Chris@16 321 #endif // BOOST_MATH_JACOBI_ELLIPTIC_HPP