ellint_1.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. // Copyright (c) 2006 Xiaogang Zhang
  2. // Copyright (c) 2006 John Maddock
  3. // Copyright (c) 2024 Matt Borland
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // History:
  9. // XZ wrote the original of this file as part of the Google
  10. // Summer of Code 2006. JM modified it to fit into the
  11. // Boost.Math conceptual framework better, and to ensure
  12. // that the code continues to work no matter how many digits
  13. // type T has.
  14. #ifndef BOOST_MATH_ELLINT_1_HPP
  15. #define BOOST_MATH_ELLINT_1_HPP
  16. #ifdef _MSC_VER
  17. #pragma once
  18. #endif
  19. #include <boost/math/tools/config.hpp>
  20. #include <boost/math/tools/type_traits.hpp>
  21. #include <boost/math/special_functions/math_fwd.hpp>
  22. #include <boost/math/special_functions/ellint_rf.hpp>
  23. #include <boost/math/constants/constants.hpp>
  24. #include <boost/math/policies/error_handling.hpp>
  25. #include <boost/math/tools/workaround.hpp>
  26. #include <boost/math/special_functions/round.hpp>
  27. // Elliptic integrals (complete and incomplete) of the first kind
  28. // Carlson, Numerische Mathematik, vol 33, 1 (1979)
  29. namespace boost { namespace math {
  30. template <class T1, class T2, class Policy>
  31. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const Policy& pol);
  32. namespace detail{
  33. template <typename T, typename Policy>
  34. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 0> const&);
  35. template <typename T, typename Policy>
  36. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 1> const&);
  37. template <typename T, typename Policy>
  38. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 2> const&);
  39. template <typename T, typename Policy>
  40. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, T one_minus_k2);
  41. // Elliptic integral (Legendre form) of the first kind
  42. template <typename T, typename Policy>
  43. BOOST_MATH_GPU_ENABLED T ellint_f_imp(T phi, T k, const Policy& pol, T one_minus_k2)
  44. {
  45. BOOST_MATH_STD_USING
  46. using namespace boost::math::tools;
  47. using namespace boost::math::constants;
  48. constexpr auto function = "boost::math::ellint_f<%1%>(%1%,%1%)";
  49. BOOST_MATH_INSTRUMENT_VARIABLE(phi);
  50. BOOST_MATH_INSTRUMENT_VARIABLE(k);
  51. BOOST_MATH_INSTRUMENT_VARIABLE(function);
  52. bool invert = false;
  53. if(phi < 0)
  54. {
  55. BOOST_MATH_INSTRUMENT_VARIABLE(phi);
  56. phi = fabs(phi);
  57. invert = true;
  58. }
  59. T result;
  60. if(phi >= tools::max_value<T>())
  61. {
  62. // Need to handle infinity as a special case:
  63. result = policies::raise_overflow_error<T>(function, nullptr, pol);
  64. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  65. }
  66. else if(phi > 1 / tools::epsilon<T>())
  67. {
  68. // Phi is so large that phi%pi is necessarily zero (or garbage),
  69. // just return the second part of the duplication formula:
  70. result = 2 * phi * ellint_k_imp(k, pol, one_minus_k2) / constants::pi<T>();
  71. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  72. }
  73. else
  74. {
  75. // Carlson's algorithm works only for |phi| <= pi/2,
  76. // use the integrand's periodicity to normalize phi
  77. //
  78. // Xiaogang's original code used a cast to long long here
  79. // but that fails if T has more digits than a long long,
  80. // so rewritten to use fmod instead:
  81. //
  82. BOOST_MATH_INSTRUMENT_CODE("pi/2 = " << constants::pi<T>() / 2);
  83. T rphi = boost::math::tools::fmod_workaround(phi, T(constants::half_pi<T>()));
  84. BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
  85. T m = boost::math::round((phi - rphi) / constants::half_pi<T>());
  86. BOOST_MATH_INSTRUMENT_VARIABLE(m);
  87. int s = 1;
  88. if(boost::math::tools::fmod_workaround(m, T(2)) > T(0.5))
  89. {
  90. m += 1;
  91. s = -1;
  92. rphi = constants::half_pi<T>() - rphi;
  93. BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
  94. }
  95. T sinp = sin(rphi);
  96. sinp *= sinp;
  97. if (sinp * k * k >= 1)
  98. {
  99. return policies::raise_domain_error<T>(function,
  100. "Got k^2 * sin^2(phi) = %1%, but the function requires this < 1", sinp * k * k, pol);
  101. }
  102. T cosp = cos(rphi);
  103. cosp *= cosp;
  104. BOOST_MATH_INSTRUMENT_VARIABLE(sinp);
  105. BOOST_MATH_INSTRUMENT_VARIABLE(cosp);
  106. if(sinp > tools::min_value<T>())
  107. {
  108. BOOST_MATH_ASSERT(rphi != 0); // precondition, can't be true if sin(rphi) != 0.
  109. //
  110. // Use http://dlmf.nist.gov/19.25#E5, note that
  111. // c-1 simplifies to cot^2(rphi) which avoids cancellation.
  112. // Likewise c - k^2 is the same as (c - 1) + (1 - k^2).
  113. //
  114. T c = 1 / sinp;
  115. T c_minus_one = cosp / sinp;
  116. T arg2;
  117. if (k != 0)
  118. {
  119. T cross = fabs(c / (k * k));
  120. if ((cross > 0.9f) && (cross < 1.1f))
  121. arg2 = c_minus_one + one_minus_k2;
  122. else
  123. arg2 = c - k * k;
  124. }
  125. else
  126. arg2 = c;
  127. result = static_cast<T>(s * ellint_rf_imp(c_minus_one, arg2, c, pol));
  128. }
  129. else
  130. result = s * sin(rphi);
  131. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  132. if(m != 0)
  133. {
  134. result += m * ellint_k_imp(k, pol, one_minus_k2);
  135. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  136. }
  137. }
  138. return invert ? T(-result) : result;
  139. }
  140. template <typename T, typename Policy>
  141. BOOST_MATH_GPU_ENABLED inline T ellint_f_imp(T phi, T k, const Policy& pol)
  142. {
  143. return ellint_f_imp(phi, k, pol, T(1 - k * k));
  144. }
  145. // Complete elliptic integral (Legendre form) of the first kind
  146. template <typename T, typename Policy>
  147. BOOST_MATH_GPU_ENABLED T ellint_k_imp(T k, const Policy& pol, T one_minus_k2)
  148. {
  149. BOOST_MATH_STD_USING
  150. using namespace boost::math::tools;
  151. constexpr auto function = "boost::math::ellint_k<%1%>(%1%)";
  152. if (abs(k) > 1)
  153. {
  154. return policies::raise_domain_error<T>(function, "Got k = %1%, function requires |k| <= 1", k, pol);
  155. }
  156. if (abs(k) == 1)
  157. {
  158. return policies::raise_overflow_error<T>(function, nullptr, pol);
  159. }
  160. T x = 0;
  161. T z = 1;
  162. T value = ellint_rf_imp(x, one_minus_k2, z, pol);
  163. return value;
  164. }
  165. template <typename T, typename Policy>
  166. BOOST_MATH_GPU_ENABLED inline T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 2> const&)
  167. {
  168. return ellint_k_imp(k, pol, T(1 - k * k));
  169. }
  170. //
  171. // Special versions for double and 80-bit long double precision,
  172. // double precision versions use the coefficients from:
  173. // "Fast computation of complete elliptic integrals and Jacobian elliptic functions",
  174. // Celestial Mechanics and Dynamical Astronomy, April 2012.
  175. //
  176. // Higher precision coefficients for 80-bit long doubles can be calculated
  177. // using for example:
  178. // Table[N[SeriesCoefficient[ EllipticK [ m ], { m, 875/1000, i} ], 20], {i, 0, 24}]
  179. // and checking the value of the first neglected term with:
  180. // N[SeriesCoefficient[ EllipticK [ m ], { m, 875/1000, 24} ], 20] * (2.5/100)^24
  181. //
  182. // For m > 0.9 we don't use the method of the paper above, but simply call our
  183. // existing routines. The routine used in the above paper was tried (and is
  184. // archived in the code below), but was found to have slightly higher error rates.
  185. //
  186. template <typename T, typename Policy>
  187. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 0> const&)
  188. {
  189. BOOST_MATH_STD_USING
  190. using namespace boost::math::tools;
  191. T m = k * k;
  192. switch (static_cast<int>(m * 20))
  193. {
  194. case 0:
  195. case 1:
  196. //if (m < 0.1)
  197. {
  198. constexpr T coef[] =
  199. {
  200. static_cast<T>(1.591003453790792180),
  201. static_cast<T>(0.416000743991786912),
  202. static_cast<T>(0.245791514264103415),
  203. static_cast<T>(0.179481482914906162),
  204. static_cast<T>(0.144556057087555150),
  205. static_cast<T>(0.123200993312427711),
  206. static_cast<T>(0.108938811574293531),
  207. static_cast<T>(0.098853409871592910),
  208. static_cast<T>(0.091439629201749751),
  209. static_cast<T>(0.085842591595413900),
  210. static_cast<T>(0.081541118718303215),
  211. static_cast<T>(0.078199656811256481910)
  212. };
  213. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.05));
  214. }
  215. case 2:
  216. case 3:
  217. //else if (m < 0.2)
  218. {
  219. constexpr T coef[] =
  220. {
  221. static_cast<T>(1.635256732264579992),
  222. static_cast<T>(0.471190626148732291),
  223. static_cast<T>(0.309728410831499587),
  224. static_cast<T>(0.252208311773135699),
  225. static_cast<T>(0.226725623219684650),
  226. static_cast<T>(0.215774446729585976),
  227. static_cast<T>(0.213108771877348910),
  228. static_cast<T>(0.216029124605188282),
  229. static_cast<T>(0.223255831633057896),
  230. static_cast<T>(0.234180501294209925),
  231. static_cast<T>(0.248557682972264071),
  232. static_cast<T>(0.266363809892617521)
  233. };
  234. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.15));
  235. }
  236. case 4:
  237. case 5:
  238. //else if (m < 0.3)
  239. {
  240. constexpr T coef[] =
  241. {
  242. static_cast<T>(1.685750354812596043),
  243. static_cast<T>(0.541731848613280329),
  244. static_cast<T>(0.401524438390690257),
  245. static_cast<T>(0.369642473420889090),
  246. static_cast<T>(0.376060715354583645),
  247. static_cast<T>(0.405235887085125919),
  248. static_cast<T>(0.453294381753999079),
  249. static_cast<T>(0.520518947651184205),
  250. static_cast<T>(0.609426039204995055),
  251. static_cast<T>(0.724263522282908870),
  252. static_cast<T>(0.871013847709812357),
  253. static_cast<T>(1.057652872753547036)
  254. };
  255. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.25));
  256. }
  257. case 6:
  258. case 7:
  259. //else if (m < 0.4)
  260. {
  261. constexpr T coef[] =
  262. {
  263. static_cast<T>(1.744350597225613243),
  264. static_cast<T>(0.634864275371935304),
  265. static_cast<T>(0.539842564164445538),
  266. static_cast<T>(0.571892705193787391),
  267. static_cast<T>(0.670295136265406100),
  268. static_cast<T>(0.832586590010977199),
  269. static_cast<T>(1.073857448247933265),
  270. static_cast<T>(1.422091460675497751),
  271. static_cast<T>(1.920387183402304829),
  272. static_cast<T>(2.632552548331654201),
  273. static_cast<T>(3.652109747319039160),
  274. static_cast<T>(5.115867135558865806),
  275. static_cast<T>(7.224080007363877411)
  276. };
  277. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.35));
  278. }
  279. case 8:
  280. case 9:
  281. //else if (m < 0.5)
  282. {
  283. constexpr T coef[] =
  284. {
  285. static_cast<T>(1.813883936816982644),
  286. static_cast<T>(0.763163245700557246),
  287. static_cast<T>(0.761928605321595831),
  288. static_cast<T>(0.951074653668427927),
  289. static_cast<T>(1.315180671703161215),
  290. static_cast<T>(1.928560693477410941),
  291. static_cast<T>(2.937509342531378755),
  292. static_cast<T>(4.594894405442878062),
  293. static_cast<T>(7.330071221881720772),
  294. static_cast<T>(11.87151259742530180),
  295. static_cast<T>(19.45851374822937738),
  296. static_cast<T>(32.20638657246426863),
  297. static_cast<T>(53.73749198700554656),
  298. static_cast<T>(90.27388602940998849)
  299. };
  300. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.45));
  301. }
  302. case 10:
  303. case 11:
  304. //else if (m < 0.6)
  305. {
  306. constexpr T coef[] =
  307. {
  308. static_cast<T>(1.898924910271553526),
  309. static_cast<T>(0.950521794618244435),
  310. static_cast<T>(1.151077589959015808),
  311. static_cast<T>(1.750239106986300540),
  312. static_cast<T>(2.952676812636875180),
  313. static_cast<T>(5.285800396121450889),
  314. static_cast<T>(9.832485716659979747),
  315. static_cast<T>(18.78714868327559562),
  316. static_cast<T>(36.61468615273698145),
  317. static_cast<T>(72.45292395127771801),
  318. static_cast<T>(145.1079577347069102),
  319. static_cast<T>(293.4786396308497026),
  320. static_cast<T>(598.3851815055010179),
  321. static_cast<T>(1228.420013075863451),
  322. static_cast<T>(2536.529755382764488)
  323. };
  324. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.55));
  325. }
  326. case 12:
  327. case 13:
  328. //else if (m < 0.7)
  329. {
  330. constexpr T coef[] =
  331. {
  332. static_cast<T>(2.007598398424376302),
  333. static_cast<T>(1.248457231212347337),
  334. static_cast<T>(1.926234657076479729),
  335. static_cast<T>(3.751289640087587680),
  336. static_cast<T>(8.119944554932045802),
  337. static_cast<T>(18.66572130873555361),
  338. static_cast<T>(44.60392484291437063),
  339. static_cast<T>(109.5092054309498377),
  340. static_cast<T>(274.2779548232413480),
  341. static_cast<T>(697.5598008606326163),
  342. static_cast<T>(1795.716014500247129),
  343. static_cast<T>(4668.381716790389910),
  344. static_cast<T>(12235.76246813664335),
  345. static_cast<T>(32290.17809718320818),
  346. static_cast<T>(85713.07608195964685),
  347. static_cast<T>(228672.1890493117096),
  348. static_cast<T>(612757.2711915852774)
  349. };
  350. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.65));
  351. }
  352. case 14:
  353. case 15:
  354. //else if (m < static_cast<T>(0.8))
  355. {
  356. constexpr T coef[] =
  357. {
  358. static_cast<T>(2.156515647499643235),
  359. static_cast<T>(1.791805641849463243),
  360. static_cast<T>(3.826751287465713147),
  361. static_cast<T>(10.38672468363797208),
  362. static_cast<T>(31.40331405468070290),
  363. static_cast<T>(100.9237039498695416),
  364. static_cast<T>(337.3268282632272897),
  365. static_cast<T>(1158.707930567827917),
  366. static_cast<T>(4060.990742193632092),
  367. static_cast<T>(14454.00184034344795),
  368. static_cast<T>(52076.66107599404803),
  369. static_cast<T>(189493.6591462156887),
  370. static_cast<T>(695184.5762413896145),
  371. static_cast<T>(2567994.048255284686),
  372. static_cast<T>(9541921.966748386322),
  373. static_cast<T>(35634927.44218076174),
  374. static_cast<T>(133669298.4612040871),
  375. static_cast<T>(503352186.6866284541),
  376. static_cast<T>(1901975729.538660119),
  377. static_cast<T>(7208915015.330103756)
  378. };
  379. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.75));
  380. }
  381. case 16:
  382. //else if (m < static_cast<T>(0.85))
  383. {
  384. constexpr T coef[] =
  385. {
  386. static_cast<T>(2.318122621712510589),
  387. static_cast<T>(2.616920150291232841),
  388. static_cast<T>(7.897935075731355823),
  389. static_cast<T>(30.50239715446672327),
  390. static_cast<T>(131.4869365523528456),
  391. static_cast<T>(602.9847637356491617),
  392. static_cast<T>(2877.024617809972641),
  393. static_cast<T>(14110.51991915180325),
  394. static_cast<T>(70621.44088156540229),
  395. static_cast<T>(358977.2665825309926),
  396. static_cast<T>(1847238.263723971684),
  397. static_cast<T>(9600515.416049214109),
  398. static_cast<T>(50307677.08502366879),
  399. static_cast<T>(265444188.6527127967),
  400. static_cast<T>(1408862325.028702687),
  401. static_cast<T>(7515687935.373774627)
  402. };
  403. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.825));
  404. }
  405. case 17:
  406. //else if (m < static_cast<T>(0.90))
  407. {
  408. constexpr T coef[] =
  409. {
  410. static_cast<T>(2.473596173751343912),
  411. static_cast<T>(3.727624244118099310),
  412. static_cast<T>(15.60739303554930496),
  413. static_cast<T>(84.12850842805887747),
  414. static_cast<T>(506.9818197040613935),
  415. static_cast<T>(3252.277058145123644),
  416. static_cast<T>(21713.24241957434256),
  417. static_cast<T>(149037.0451890932766),
  418. static_cast<T>(1043999.331089990839),
  419. static_cast<T>(7427974.817042038995),
  420. static_cast<T>(53503839.67558661151),
  421. static_cast<T>(389249886.9948708474),
  422. static_cast<T>(2855288351.100810619),
  423. static_cast<T>(21090077038.76684053),
  424. static_cast<T>(156699833947.7902014),
  425. static_cast<T>(1170222242422.439893),
  426. static_cast<T>(8777948323668.937971),
  427. static_cast<T>(66101242752484.95041),
  428. static_cast<T>(499488053713388.7989),
  429. static_cast<T>(37859743397240299.20)
  430. };
  431. return boost::math::tools::evaluate_polynomial(coef, m - static_cast<T>(0.875));
  432. }
  433. default:
  434. //
  435. // This handles all cases where m > 0.9,
  436. // including all error handling:
  437. //
  438. return ellint_k_imp(k, pol, boost::math::integral_constant<int, 2>());
  439. #if 0
  440. else
  441. {
  442. T lambda_prime = (1 - sqrt(k)) / (2 * (1 + sqrt(k)));
  443. T k_prime = ellint_k(sqrt((1 - k) * (1 + k))); // K(m')
  444. T lambda_prime_4th = boost::math::pow<4>(lambda_prime);
  445. T q_prime = ((((((20910 * lambda_prime_4th) + 1707) * lambda_prime_4th + 150) * lambda_prime_4th + 15) * lambda_prime_4th + 2) * lambda_prime_4th + 1) * lambda_prime;
  446. /*T q_prime_2 = lambda_prime
  447. + 2 * boost::math::pow<5>(lambda_prime)
  448. + 15 * boost::math::pow<9>(lambda_prime)
  449. + 150 * boost::math::pow<13>(lambda_prime)
  450. + 1707 * boost::math::pow<17>(lambda_prime)
  451. + 20910 * boost::math::pow<21>(lambda_prime);*/
  452. return -log(q_prime) * k_prime / boost::math::constants::pi<T>();
  453. }
  454. #endif
  455. }
  456. }
  457. template <typename T, typename Policy>
  458. BOOST_MATH_GPU_ENABLED BOOST_MATH_FORCEINLINE T ellint_k_imp(T k, const Policy& pol, boost::math::integral_constant<int, 1> const&)
  459. {
  460. BOOST_MATH_STD_USING
  461. using namespace boost::math::tools;
  462. T m = k * k;
  463. switch (static_cast<int>(m * 20))
  464. {
  465. case 0:
  466. case 1:
  467. {
  468. constexpr T coef[] =
  469. {
  470. 1.5910034537907921801L,
  471. 0.41600074399178691174L,
  472. 0.24579151426410341536L,
  473. 0.17948148291490616181L,
  474. 0.14455605708755514976L,
  475. 0.12320099331242771115L,
  476. 0.10893881157429353105L,
  477. 0.098853409871592910399L,
  478. 0.091439629201749751268L,
  479. 0.085842591595413899672L,
  480. 0.081541118718303214749L,
  481. 0.078199656811256481910L,
  482. 0.075592617535422415648L,
  483. 0.073562939365441925050L
  484. };
  485. return boost::math::tools::evaluate_polynomial(coef, m - 0.05L);
  486. }
  487. case 2:
  488. case 3:
  489. {
  490. constexpr T coef[] =
  491. {
  492. 1.6352567322645799924L,
  493. 0.47119062614873229055L,
  494. 0.30972841083149958708L,
  495. 0.25220831177313569923L,
  496. 0.22672562321968464974L,
  497. 0.21577444672958597588L,
  498. 0.21310877187734890963L,
  499. 0.21602912460518828154L,
  500. 0.22325583163305789567L,
  501. 0.23418050129420992492L,
  502. 0.24855768297226407136L,
  503. 0.26636380989261752077L,
  504. 0.28772845215611466775L,
  505. 0.31290024539780334906L,
  506. 0.34223105446381299902L
  507. };
  508. return boost::math::tools::evaluate_polynomial(coef, m - 0.15L);
  509. }
  510. case 4:
  511. case 5:
  512. {
  513. constexpr T coef[] =
  514. {
  515. 1.6857503548125960429L,
  516. 0.54173184861328032882L,
  517. 0.40152443839069025682L,
  518. 0.36964247342088908995L,
  519. 0.37606071535458364462L,
  520. 0.40523588708512591863L,
  521. 0.45329438175399907924L,
  522. 0.52051894765118420473L,
  523. 0.60942603920499505544L,
  524. 0.72426352228290886975L,
  525. 0.87101384770981235737L,
  526. 1.0576528727535470365L,
  527. 1.2945970872087764321L,
  528. 1.5953368253888783747L,
  529. 1.9772844873556364793L,
  530. 2.4628890581910021287L
  531. };
  532. return boost::math::tools::evaluate_polynomial(coef, m - 0.25L);
  533. }
  534. case 6:
  535. case 7:
  536. {
  537. constexpr T coef[] =
  538. {
  539. 1.7443505972256132429L,
  540. 0.63486427537193530383L,
  541. 0.53984256416444553751L,
  542. 0.57189270519378739093L,
  543. 0.67029513626540610034L,
  544. 0.83258659001097719939L,
  545. 1.0738574482479332654L,
  546. 1.4220914606754977514L,
  547. 1.9203871834023048288L,
  548. 2.6325525483316542006L,
  549. 3.6521097473190391602L,
  550. 5.1158671355588658061L,
  551. 7.2240800073638774108L,
  552. 10.270306349944787227L,
  553. 14.685616935355757348L,
  554. 21.104114212004582734L,
  555. 30.460132808575799413L,
  556. };
  557. return boost::math::tools::evaluate_polynomial(coef, m - 0.35L);
  558. }
  559. case 8:
  560. case 9:
  561. {
  562. constexpr T coef[] =
  563. {
  564. 1.8138839368169826437L,
  565. 0.76316324570055724607L,
  566. 0.76192860532159583095L,
  567. 0.95107465366842792679L,
  568. 1.3151806717031612153L,
  569. 1.9285606934774109412L,
  570. 2.9375093425313787550L,
  571. 4.5948944054428780618L,
  572. 7.3300712218817207718L,
  573. 11.871512597425301798L,
  574. 19.458513748229377383L,
  575. 32.206386572464268628L,
  576. 53.737491987005546559L,
  577. 90.273886029409988491L,
  578. 152.53312130253275268L,
  579. 259.02388747148299086L,
  580. 441.78537518096201946L,
  581. 756.39903981567380952L
  582. };
  583. return boost::math::tools::evaluate_polynomial(coef, m - 0.45L);
  584. }
  585. case 10:
  586. case 11:
  587. {
  588. constexpr T coef[] =
  589. {
  590. 1.8989249102715535257L,
  591. 0.95052179461824443490L,
  592. 1.1510775899590158079L,
  593. 1.7502391069863005399L,
  594. 2.9526768126368751802L,
  595. 5.2858003961214508892L,
  596. 9.8324857166599797471L,
  597. 18.787148683275595622L,
  598. 36.614686152736981447L,
  599. 72.452923951277718013L,
  600. 145.10795773470691023L,
  601. 293.47863963084970259L,
  602. 598.38518150550101790L,
  603. 1228.4200130758634505L,
  604. 2536.5297553827644880L,
  605. 5263.9832725075189576L,
  606. 10972.138126273491753L,
  607. 22958.388550988306870L,
  608. 48203.103373625406989L
  609. };
  610. return boost::math::tools::evaluate_polynomial(coef, m - 0.55L);
  611. }
  612. case 12:
  613. case 13:
  614. {
  615. constexpr T coef[] =
  616. {
  617. 2.0075983984243763017L,
  618. 1.2484572312123473371L,
  619. 1.9262346570764797287L,
  620. 3.7512896400875876798L,
  621. 8.1199445549320458022L,
  622. 18.665721308735553611L,
  623. 44.603924842914370633L,
  624. 109.50920543094983774L,
  625. 274.27795482324134804L,
  626. 697.55980086063261629L,
  627. 1795.7160145002471293L,
  628. 4668.3817167903899100L,
  629. 12235.762468136643348L,
  630. 32290.178097183208178L,
  631. 85713.076081959646847L,
  632. 228672.18904931170958L,
  633. 612757.27119158527740L,
  634. 1.6483233976504668314e6L,
  635. 4.4492251046211960936e6L,
  636. 1.2046317340783185238e7L,
  637. 3.2705187507963254185e7L
  638. };
  639. return boost::math::tools::evaluate_polynomial(coef, m - 0.65L);
  640. }
  641. case 14:
  642. case 15:
  643. {
  644. constexpr T coef[] =
  645. {
  646. 2.1565156474996432354L,
  647. 1.7918056418494632425L,
  648. 3.8267512874657131470L,
  649. 10.386724683637972080L,
  650. 31.403314054680702901L,
  651. 100.92370394986954165L,
  652. 337.32682826322728966L,
  653. 1158.7079305678279173L,
  654. 4060.9907421936320917L,
  655. 14454.001840343447947L,
  656. 52076.661075994048028L,
  657. 189493.65914621568866L,
  658. 695184.57624138961450L,
  659. 2.5679940482552846861e6L,
  660. 9.5419219667483863221e6L,
  661. 3.5634927442180761743e7L,
  662. 1.3366929846120408712e8L,
  663. 5.0335218668662845411e8L,
  664. 1.9019757295386601192e9L,
  665. 7.2089150153301037563e9L,
  666. 2.7398741806339510931e10L,
  667. 1.0439286724885300495e11L,
  668. 3.9864875581513728207e11L,
  669. 1.5254661585564745591e12L,
  670. 5.8483259088850315936e12
  671. };
  672. return boost::math::tools::evaluate_polynomial(coef, m - 0.75L);
  673. }
  674. case 16:
  675. {
  676. constexpr T coef[] =
  677. {
  678. 2.3181226217125105894L,
  679. 2.6169201502912328409L,
  680. 7.8979350757313558232L,
  681. 30.502397154466723270L,
  682. 131.48693655235284561L,
  683. 602.98476373564916170L,
  684. 2877.0246178099726410L,
  685. 14110.519919151803247L,
  686. 70621.440881565402289L,
  687. 358977.26658253099258L,
  688. 1.8472382637239716844e6L,
  689. 9.6005154160492141090e6L,
  690. 5.0307677085023668786e7L,
  691. 2.6544418865271279673e8L,
  692. 1.4088623250287026866e9L,
  693. 7.5156879353737746270e9L,
  694. 4.0270783964955246149e10L,
  695. 2.1662089325801126339e11L,
  696. 1.1692489201929996116e12L,
  697. 6.3306543358985679881e12
  698. };
  699. return boost::math::tools::evaluate_polynomial(coef, m - 0.825L);
  700. }
  701. case 17:
  702. {
  703. constexpr T coef[] =
  704. {
  705. 2.4735961737513439120L,
  706. 3.7276242441180993105L,
  707. 15.607393035549304964L,
  708. 84.128508428058877470L,
  709. 506.98181970406139349L,
  710. 3252.2770581451236438L,
  711. 21713.242419574342564L,
  712. 149037.04518909327662L,
  713. 1.0439993310899908390e6L,
  714. 7.4279748170420389947e6L,
  715. 5.3503839675586611510e7L,
  716. 3.8924988699487084738e8L,
  717. 2.8552883511008106195e9L,
  718. 2.1090077038766840525e10L,
  719. 1.5669983394779020136e11L,
  720. 1.1702222424224398927e12L,
  721. 8.7779483236689379709e12L,
  722. 6.6101242752484950408e13L,
  723. 4.9948805371338879891e14L,
  724. 3.7859743397240299201e15L,
  725. 2.8775996123036112296e16L,
  726. 2.1926346839925760143e17L,
  727. 1.6744985438468349361e18L,
  728. 1.2814410112866546052e19L,
  729. 9.8249807041031260167e19
  730. };
  731. return boost::math::tools::evaluate_polynomial(coef, m - 0.875L);
  732. }
  733. default:
  734. //
  735. // All cases where m > 0.9
  736. // including all error handling:
  737. //
  738. return ellint_k_imp(k, pol, boost::math::integral_constant<int, 2>());
  739. }
  740. }
  741. template <typename T, typename Policy>
  742. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T>::type ellint_1(T k, const Policy& pol, const boost::math::true_type&)
  743. {
  744. typedef typename tools::promote_args<T>::type result_type;
  745. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  746. typedef boost::math::integral_constant<int,
  747. #if defined(__clang_major__) && (__clang_major__ == 7)
  748. 2
  749. #else
  750. boost::math::is_floating_point<T>::value && boost::math::numeric_limits<T>::digits && (boost::math::numeric_limits<T>::digits <= 54) ? 0 :
  751. boost::math::is_floating_point<T>::value && boost::math::numeric_limits<T>::digits && (boost::math::numeric_limits<T>::digits <= 64) ? 1 : 2
  752. #endif
  753. > precision_tag_type;
  754. return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_k_imp(static_cast<value_type>(k), pol, precision_tag_type()), "boost::math::ellint_1<%1%>(%1%)");
  755. }
  756. template <class T1, class T2>
  757. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const boost::math::false_type&)
  758. {
  759. return boost::math::ellint_1(k, phi, policies::policy<>());
  760. }
  761. } // namespace detail
  762. // Elliptic integral (Legendre form) of the first kind
  763. template <class T1, class T2, class Policy>
  764. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi, const Policy& pol) // LCOV_EXCL_LINE gcc misses this but sees the function body, strange!
  765. {
  766. typedef typename tools::promote_args<T1, T2>::type result_type;
  767. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  768. return policies::checked_narrowing_cast<result_type, Policy>(detail::ellint_f_imp(static_cast<value_type>(phi), static_cast<value_type>(k), pol), "boost::math::ellint_1<%1%>(%1%,%1%)");
  769. }
  770. template <class T1, class T2>
  771. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T1, T2>::type ellint_1(T1 k, T2 phi)
  772. {
  773. typedef typename policies::is_policy<T2>::type tag_type;
  774. return detail::ellint_1(k, phi, tag_type());
  775. }
  776. // Complete elliptic integral (Legendre form) of the first kind
  777. template <typename T>
  778. BOOST_MATH_GPU_ENABLED typename tools::promote_args<T>::type ellint_1(T k)
  779. {
  780. return ellint_1(k, policies::policy<>());
  781. }
  782. }} // namespaces
  783. #endif // BOOST_MATH_ELLINT_1_HPP