ellint_1.hpp 27 KB

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