series_expansion.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // Boost.Geometry
  2. // Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
  3. // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
  4. // Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program.
  5. // This file was modified by Oracle on 2019.
  6. // Modifications copyright (c) 2019 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. // This file is converted from GeographicLib, https://geographiclib.sourceforge.io
  12. // GeographicLib is originally written by Charles Karney.
  13. // Author: Charles Karney (2008-2017)
  14. // Last updated version of GeographicLib: 1.49
  15. // Original copyright notice:
  16. // Copyright (c) Charles Karney (2008-2017) <[email protected]> and licensed
  17. // under the MIT/X11 License. For more information, see
  18. // https://geographiclib.sourceforge.io
  19. #ifndef BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
  20. #define BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
  21. #include <boost/array.hpp>
  22. #include <boost/geometry/core/assert.hpp>
  23. #include <boost/geometry/util/math.hpp>
  24. namespace boost { namespace geometry { namespace series_expansion {
  25. /*
  26. Generate and evaluate the series expansion of the following integral
  27. I1 = integrate( sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
  28. which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
  29. and expand (1 - eps) * I1 retaining terms up to order eps^maxpow
  30. in A1 and C1[l].
  31. The resulting series is of the form
  32. A1 * ( sigma + sum(C1[l] * sin(2*l*sigma), l, 1, maxpow) ).
  33. The scale factor A1-1 = mean value of (d/dsigma)I1 - 1
  34. The expansion above is performed in Maxima, a Computer Algebra System.
  35. The C++ code (that yields the function evaluate_A1 below) is
  36. generated by the following Maxima script:
  37. geometry/doc/other/maxima/geod.mac
  38. To replace each number x by CT(x) the following
  39. script can be used:
  40. sed -e 's/[0-9]\+/CT(&)/g; s/\[CT/\[/g; s/)\]/\]/g;
  41. s/case\sCT(/case /g; s/):/:/g; s/epsCT(2)/eps2/g;'
  42. */
  43. template <size_t SeriesOrder, typename CT>
  44. inline CT evaluate_A1(CT const& eps)
  45. {
  46. CT const eps2 = math::sqr(eps);
  47. CT t;
  48. switch (SeriesOrder/2)
  49. {
  50. case 0:
  51. t = CT(0);
  52. break;
  53. case 1:
  54. t = eps2/CT(4);
  55. break;
  56. case 2:
  57. t = eps2*(eps2+CT(16))/CT(64);
  58. break;
  59. case 3:
  60. t = eps2*(eps2*(eps2+CT(4))+CT(64))/CT(256);
  61. break;
  62. default:
  63. t = eps2*(eps2*(eps2*(CT(25)*eps2+CT(64))+CT(256))+CT(4096))/CT(16384);
  64. break;
  65. }
  66. return (t + eps) / (CT(1) - eps);
  67. }
  68. /*
  69. Generate and evaluate the series expansion of the following integral
  70. I2 = integrate( 1/sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
  71. which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
  72. and expand (1 - eps) * I2 retaining terms up to order eps^maxpow
  73. in A2 and C2[l].
  74. The resulting series is of the form
  75. A2 * ( sigma + sum(C2[l] * sin(2*l*sigma), l, 1, maxpow) )
  76. The scale factor A2-1 = mean value of (d/dsigma)2 - 1
  77. The expansion above is performed in Maxima, a Computer Algebra System.
  78. The C++ code (that yields the function evaluate_A2 below) is
  79. generated by the following Maxima script:
  80. geometry/doc/other/maxima/geod.mac
  81. */
  82. template <size_t SeriesOrder, typename CT>
  83. inline CT evaluate_A2(CT const& eps)
  84. {
  85. CT const eps2 = math::sqr(eps);
  86. CT t;
  87. switch (SeriesOrder/2)
  88. {
  89. case 0:
  90. t = CT(0);
  91. break;
  92. case 1:
  93. t = -CT(3)*eps2/CT(4);
  94. break;
  95. case 2:
  96. t = (-CT(7)*eps2-CT(48))*eps2/CT(64);
  97. break;
  98. case 3:
  99. t = eps2*((-CT(11)*eps2-CT(28))*eps2-CT(192))/CT(256);
  100. break;
  101. default:
  102. t = eps2*(eps2*((-CT(375)*eps2-CT(704))*eps2-CT(1792))-CT(12288))/CT(16384);
  103. break;
  104. }
  105. return (t - eps) / (CT(1) + eps);
  106. }
  107. /*
  108. Express
  109. I3 = integrate( (2-f)/(1+(1-f)*sqrt(1+k2*sin(sigma1)^2)), sigma1, 0, sigma )
  110. as a series
  111. A3 * ( sigma + sum(C3[l] * sin(2*l*sigma), l, 1, maxpow-1) )
  112. valid for f and k2 small. It is convenient to write k2 = 4 * eps / (1 -
  113. eps)^2 and f = 2*n/(1+n) and expand in eps and n. This procedure leads
  114. to a series where the coefficients of eps^j are terminating series in n.
  115. The scale factor A3 = mean value of (d/dsigma)I3
  116. The expansion above is performed in Maxima, a Computer Algebra System.
  117. The C++ code (that yields the function evaluate_coeffs_A3 below) is
  118. generated by the following Maxima script:
  119. geometry/doc/other/maxima/geod.mac
  120. */
  121. template <typename Coeffs, typename CT>
  122. inline void evaluate_coeffs_A3(Coeffs &c, CT const& n)
  123. {
  124. switch (int(Coeffs::static_size))
  125. {
  126. case 0:
  127. break;
  128. case 1:
  129. c[0] = CT(1);
  130. break;
  131. case 2:
  132. c[0] = CT(1);
  133. c[1] = -CT(1)/CT(2);
  134. break;
  135. case 3:
  136. c[0] = CT(1);
  137. c[1] = (n-CT(1))/CT(2);
  138. c[2] = -CT(1)/CT(4);
  139. break;
  140. case 4:
  141. c[0] = CT(1);
  142. c[1] = (n-CT(1))/CT(2);
  143. c[2] = (-n-CT(2))/CT(8);
  144. c[3] = -CT(1)/CT(16);
  145. break;
  146. case 5:
  147. c[0] = CT(1);
  148. c[1] = (n-CT(1))/CT(2);
  149. c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
  150. c[3] = (-CT(3)*n-CT(1))/CT(16);
  151. c[4] = -CT(3)/CT(64);
  152. break;
  153. case 6:
  154. c[0] = CT(1);
  155. c[1] = (n-CT(1))/CT(2);
  156. c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
  157. c[3] = ((-n-CT(3))*n-CT(1))/CT(16);
  158. c[4] = (-CT(2)*n-CT(3))/CT(64);
  159. c[5] = -CT(3)/CT(128);
  160. break;
  161. case 7:
  162. c[0] = CT(1);
  163. c[1] = (n-CT(1))/CT(2);
  164. c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
  165. c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
  166. c[4] = ((-CT(10)*n-CT(2))*n-CT(3))/CT(64);
  167. c[5] = (-CT(5)*n-CT(3))/CT(128);
  168. c[6] = -CT(5)/CT(256);
  169. break;
  170. default:
  171. c[0] = CT(1);
  172. c[1] = (n-CT(1))/CT(2);
  173. c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
  174. c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
  175. c[4] = (n*((-CT(5)*n-CT(20))*n-CT(4))-CT(6))/CT(128);
  176. c[5] = ((-CT(5)*n-CT(10))*n-CT(6))/CT(256);
  177. c[6] = (-CT(15)*n-CT(20))/CT(1024);
  178. c[7] = -CT(25)/CT(2048);
  179. break;
  180. }
  181. }
  182. /*
  183. The coefficients C1[l] in the Fourier expansion of B1.
  184. The expansion below is performed in Maxima, a Computer Algebra System.
  185. The C++ code (that yields the function evaluate_coeffs_C1 below) is
  186. generated by the following Maxima script:
  187. geometry/doc/other/maxima/geod.mac
  188. */
  189. template <typename Coeffs, typename CT>
  190. inline void evaluate_coeffs_C1(Coeffs &c, CT const& eps)
  191. {
  192. CT const eps2 = math::sqr(eps);
  193. CT d = eps;
  194. switch (int(Coeffs::static_size) - 1)
  195. {
  196. case 0:
  197. break;
  198. case 1:
  199. c[1] = -d/CT(2);
  200. break;
  201. case 2:
  202. c[1] = -d/CT(2);
  203. d *= eps;
  204. c[2] = -d/CT(16);
  205. break;
  206. case 3:
  207. c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
  208. d *= eps;
  209. c[2] = -d/CT(16);
  210. d *= eps;
  211. c[3] = -d/CT(48);
  212. break;
  213. case 4:
  214. c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
  215. d *= eps;
  216. c[2] = d*(eps2-CT(2))/CT(32);
  217. d *= eps;
  218. c[3] = -d/CT(48);
  219. d *= eps;
  220. c[4] = -CT(5)*d/CT(512);
  221. break;
  222. case 5:
  223. c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
  224. d *= eps;
  225. c[2] = d*(eps2-CT(2))/CT(32);
  226. d *= eps;
  227. c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
  228. d *= eps;
  229. c[4] = -CT(5)*d/CT(512);
  230. d *= eps;
  231. c[5] = -CT(7)*d/CT(1280);
  232. break;
  233. case 6:
  234. c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
  235. d *= eps;
  236. c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
  237. d *= eps;
  238. c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
  239. d *= eps;
  240. c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
  241. d *= eps;
  242. c[5] = -CT(7)*d/CT(1280);
  243. d *= eps;
  244. c[6] = -CT(7)*d/CT(2048);
  245. break;
  246. case 7:
  247. c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
  248. d *= eps;
  249. c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
  250. d *= eps;
  251. c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
  252. d *= eps;
  253. c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
  254. d *= eps;
  255. c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
  256. d *= eps;
  257. c[6] = -CT(7)*d/CT(2048);
  258. d *= eps;
  259. c[7] = -CT(33)*d/CT(14336);
  260. break;
  261. default:
  262. c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
  263. d *= eps;
  264. c[2] = d*(eps2*(eps2*(CT(7)*eps2-CT(18))+CT(128))-CT(256))/CT(4096);
  265. d *= eps;
  266. c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
  267. d *= eps;
  268. c[4] = d*((CT(96)-CT(11)*eps2)*eps2-CT(160))/CT(16384);
  269. d *= eps;
  270. c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
  271. d *= eps;
  272. c[6] = d*(CT(9)*eps2-CT(14))/CT(4096);
  273. d *= eps;
  274. c[7] = -CT(33)*d/CT(14336);
  275. d *= eps;
  276. c[8] = -CT(429)*d/CT(262144);
  277. break;
  278. }
  279. }
  280. /*
  281. The coefficients C1p[l] in the Fourier expansion of B1p.
  282. The expansion below is performed in Maxima, a Computer Algebra System.
  283. The C++ code (that yields the function evaluate_coeffs_C1p below) is
  284. generated by the following Maxima script:
  285. geometry/doc/other/maxima/geod.mac
  286. */
  287. template <typename Coeffs, typename CT>
  288. inline void evaluate_coeffs_C1p(Coeffs& c, CT const& eps)
  289. {
  290. CT const eps2 = math::sqr(eps);
  291. CT d = eps;
  292. switch (int(Coeffs::static_size) - 1)
  293. {
  294. case 0:
  295. break;
  296. case 1:
  297. c[1] = d/CT(2);
  298. break;
  299. case 2:
  300. c[1] = d/CT(2);
  301. d *= eps;
  302. c[2] = CT(5)*d/CT(16);
  303. break;
  304. case 3:
  305. c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
  306. d *= eps;
  307. c[2] = CT(5)*d/CT(16);
  308. d *= eps;
  309. c[3] = CT(29)*d/CT(96);
  310. break;
  311. case 4:
  312. c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
  313. d *= eps;
  314. c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
  315. d *= eps;
  316. c[3] = CT(29)*d/CT(96);
  317. d *= eps;
  318. c[4] = CT(539)*d/CT(1536);
  319. break;
  320. case 5:
  321. c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
  322. d *= eps;
  323. c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
  324. d *= eps;
  325. c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
  326. d *= eps;
  327. c[4] = CT(539)*d/CT(1536);
  328. d *= eps;
  329. c[5] = CT(3467)*d/CT(7680);
  330. break;
  331. case 6:
  332. c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
  333. d *= eps;
  334. c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
  335. d *= eps;
  336. c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
  337. d *= eps;
  338. c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
  339. d *= eps;
  340. c[5] = CT(3467)*d/CT(7680);
  341. d *= eps;
  342. c[6] = CT(38081)*d/CT(61440);
  343. break;
  344. case 7:
  345. c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
  346. d *= eps;
  347. c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
  348. d *= eps;
  349. c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
  350. d *= eps;
  351. c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
  352. d *= eps;
  353. c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
  354. d *= eps;
  355. c[6] = CT(38081)*d/CT(61440);
  356. d *= eps;
  357. c[7] = CT(459485)*d/CT(516096);
  358. break;
  359. default:
  360. c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
  361. d *= eps;
  362. c[2] = d*(eps2*((CT(120150)-CT(86171)*eps2)*eps2-CT(142080))+CT(115200))/CT(368640);
  363. d *= eps;
  364. c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
  365. d *= eps;
  366. c[4] = d*(eps2*(CT(1082857)*eps2-CT(688608))+CT(258720))/CT(737280);
  367. d *= eps;
  368. c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
  369. d *= eps;
  370. c[6] = d*(CT(533134)-CT(2200311)*eps2)/CT(860160);
  371. d *= eps;
  372. c[7] = CT(459485)*d/CT(516096);
  373. d *= eps;
  374. c[8] = CT(109167851)*d/CT(82575360);
  375. break;
  376. }
  377. }
  378. /*
  379. The coefficients C2[l] in the Fourier expansion of B2.
  380. The expansion below is performed in Maxima, a Computer Algebra System.
  381. The C++ code (that yields the function evaluate_coeffs_C2 below) is
  382. generated by the following Maxima script:
  383. geometry/doc/other/maxima/geod.mac
  384. */
  385. template <typename Coeffs, typename CT>
  386. inline void evaluate_coeffs_C2(Coeffs& c, CT const& eps)
  387. {
  388. CT const eps2 = math::sqr(eps);
  389. CT d = eps;
  390. switch (int(Coeffs::static_size) - 1)
  391. {
  392. case 0:
  393. break;
  394. case 1:
  395. c[1] = d/CT(2);
  396. break;
  397. case 2:
  398. c[1] = d/CT(2);
  399. d *= eps;
  400. c[2] = CT(3)*d/CT(16);
  401. break;
  402. case 3:
  403. c[1] = d*(eps2+CT(8))/CT(16);
  404. d *= eps;
  405. c[2] = CT(3)*d/CT(16);
  406. d *= eps;
  407. c[3] = CT(5)*d/CT(48);
  408. break;
  409. case 4:
  410. c[1] = d*(eps2+CT(8))/CT(16);
  411. d *= eps;
  412. c[2] = d*(eps2+CT(6))/CT(32);
  413. d *= eps;
  414. c[3] = CT(5)*d/CT(48);
  415. d *= eps;
  416. c[4] = CT(35)*d/CT(512);
  417. break;
  418. case 5:
  419. c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
  420. d *= eps;
  421. c[2] = d*(eps2+CT(6))/CT(32);
  422. d *= eps;
  423. c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
  424. d *= eps;
  425. c[4] = CT(35)*d/CT(512);
  426. d *= eps;
  427. c[5] = CT(63)*d/CT(1280);
  428. break;
  429. case 6:
  430. c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
  431. d *= eps;
  432. c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
  433. d *= eps;
  434. c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
  435. d *= eps;
  436. c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
  437. d *= eps;
  438. c[5] = CT(63)*d/CT(1280);
  439. d *= eps;
  440. c[6] = CT(77)*d/CT(2048);
  441. break;
  442. case 7:
  443. c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
  444. d *= eps;
  445. c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
  446. d *= eps;
  447. c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
  448. d *= eps;
  449. c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
  450. d *= eps;
  451. c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
  452. d *= eps;
  453. c[6] = CT(77)*d/CT(2048);
  454. d *= eps;
  455. c[7] = CT(429)*d/CT(14336);
  456. break;
  457. default:
  458. c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
  459. d *= eps;
  460. c[2] = d*(eps2*(eps2*(CT(47)*eps2+CT(70))+CT(128))+CT(768))/CT(4096);
  461. d *= eps;
  462. c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
  463. d *= eps;
  464. c[4] = d*(eps2*(CT(133)*eps2+CT(224))+CT(1120))/CT(16384);
  465. d *= eps;
  466. c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
  467. d *= eps;
  468. c[6] = d*(CT(33)*eps2+CT(154))/CT(4096);
  469. d *= eps;
  470. c[7] = CT(429)*d/CT(14336);
  471. d *= eps;
  472. c[8] = CT(6435)*d/CT(262144);
  473. break;
  474. }
  475. }
  476. /*
  477. The coefficients C3[l] in the Fourier expansion of B3.
  478. The expansion below is performed in Maxima, a Computer Algebra System.
  479. The C++ code (that yields the function evaluate_coeffs_C3 below) is
  480. generated by the following Maxima script:
  481. geometry/doc/other/maxima/geod.mac
  482. */
  483. template <size_t SeriesOrder, typename Coeffs, typename CT>
  484. inline void evaluate_coeffs_C3x(Coeffs &c, CT const& n) {
  485. BOOST_GEOMETRY_ASSERT((Coeffs::static_size == (SeriesOrder * (SeriesOrder - 1)) / 2));
  486. CT const n2 = math::sqr(n);
  487. switch (SeriesOrder)
  488. {
  489. case 0:
  490. break;
  491. case 1:
  492. break;
  493. case 2:
  494. c[0] = (CT(1)-n)/CT(4);
  495. break;
  496. case 3:
  497. c[0] = (CT(1)-n)/CT(4);
  498. c[1] = (CT(1)-n2)/CT(8);
  499. c[2] = ((n-CT(3))*n+CT(2))/CT(32);
  500. break;
  501. case 4:
  502. c[0] = (CT(1)-n)/CT(4);
  503. c[1] = (CT(1)-n2)/CT(8);
  504. c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
  505. c[3] = ((n-CT(3))*n+CT(2))/CT(32);
  506. c[4] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
  507. c[5] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
  508. break;
  509. case 5:
  510. c[0] = (CT(1)-n)/CT(4);
  511. c[1] = (CT(1)-n2)/CT(8);
  512. c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
  513. c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
  514. c[4] = ((n-CT(3))*n+CT(2))/CT(32);
  515. c[5] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
  516. c[6] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
  517. c[7] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
  518. c[8] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
  519. c[9] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
  520. break;
  521. case 6:
  522. c[0] = (CT(1)-n)/CT(4);
  523. c[1] = (CT(1)-n2)/CT(8);
  524. c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
  525. c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
  526. c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
  527. c[5] = ((n-CT(3))*n+CT(2))/CT(32);
  528. c[6] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
  529. c[7] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
  530. c[8] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
  531. c[9] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
  532. c[10] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
  533. c[11] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
  534. c[12] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
  535. c[13] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
  536. c[14] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
  537. break;
  538. case 7:
  539. c[0] = (CT(1)-n)/CT(4);
  540. c[1] = (CT(1)-n2)/CT(8);
  541. c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
  542. c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
  543. c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
  544. c[5] = (CT(10)*n+CT(21))/CT(1024);
  545. c[6] = ((n-CT(3))*n+CT(2))/CT(32);
  546. c[7] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
  547. c[8] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
  548. c[9] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
  549. c[10] = (CT(69)*n+CT(108))/CT(8192);
  550. c[11] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
  551. c[12] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
  552. c[13] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
  553. c[14] = (CT(12)-n)/CT(1024);
  554. c[15] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
  555. c[16] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
  556. c[17] = (CT(72)-CT(43)*n)/CT(8192);
  557. c[18] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
  558. c[19] = (CT(9)-CT(15)*n)/CT(1024);
  559. c[20] = (CT(44)-CT(99)*n)/CT(8192);
  560. break;
  561. default:
  562. c[0] = (CT(1)-n)/CT(4);
  563. c[1] = (CT(1)-n2)/CT(8);
  564. c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
  565. c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
  566. c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
  567. c[5] = (CT(10)*n+CT(21))/CT(1024);
  568. c[6] = CT(243)/CT(16384);
  569. c[7] = ((n-CT(3))*n+CT(2))/CT(32);
  570. c[8] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
  571. c[9] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
  572. c[10] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
  573. c[11] = (CT(69)*n+CT(108))/CT(8192);
  574. c[12] = CT(187)/CT(16384);
  575. c[13] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
  576. c[14] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
  577. c[15] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
  578. c[16] = (CT(12)-n)/CT(1024);
  579. c[17] = CT(139)/CT(16384);
  580. c[18] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
  581. c[19] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
  582. c[20] = (CT(72)-CT(43)*n)/CT(8192);
  583. c[21] = CT(127)/CT(16384);
  584. c[22] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
  585. c[23] = (CT(9)-CT(15)*n)/CT(1024);
  586. c[24] = CT(99)/CT(16384);
  587. c[25] = (CT(44)-CT(99)*n)/CT(8192);
  588. c[26] = CT(99)/CT(16384);
  589. c[27] = CT(429)/CT(114688);
  590. break;
  591. }
  592. }
  593. /*
  594. \brief Given the set of coefficients coeffs2[] evaluate on
  595. C3 and return the set of coefficients coeffs1[].
  596. Elements coeffs1[1] through coeffs1[SeriesOrder - 1] are set.
  597. */
  598. template <typename Coeffs1, typename Coeffs2, typename CT>
  599. inline void evaluate_coeffs_C3(Coeffs1 &coeffs1, Coeffs2 &coeffs2, CT const& eps)
  600. {
  601. CT mult = 1;
  602. size_t offset = 0;
  603. // i is the index of C3[i].
  604. for (size_t i = 1; i < Coeffs1::static_size; ++i)
  605. {
  606. // Order of polynomial in eps.
  607. size_t m = Coeffs1::static_size - i;
  608. mult *= eps;
  609. coeffs1[i] = mult * math::horner_evaluate(eps, coeffs2.begin() + offset,
  610. coeffs2.begin() + offset + m);
  611. offset += m;
  612. }
  613. // Post condition: offset == coeffs_C3_size
  614. }
  615. /*
  616. \brief Evaluate the following:
  617. y = sum(c[i] * sin(2*i * x), i, 1, n)
  618. using Clenshaw summation.
  619. */
  620. template <typename CT, typename Coeffs>
  621. inline CT sin_cos_series(CT const& sinx, CT const& cosx, Coeffs const& coeffs)
  622. {
  623. size_t n = Coeffs::static_size - 1;
  624. size_t index = 0;
  625. // Point to one beyond last element.
  626. index += (n + 1);
  627. CT ar = 2 * (cosx - sinx) * (cosx + sinx);
  628. // If n is odd, get the last element.
  629. CT k0 = n & 1 ? coeffs[--index] : 0;
  630. CT k1 = 0;
  631. // Make n even.
  632. n /= 2;
  633. while (n--) {
  634. // Unroll loop x 2, so accumulators return to their original role.
  635. k1 = ar * k0 - k1 + coeffs[--index];
  636. k0 = ar * k1 - k0 + coeffs[--index];
  637. }
  638. return 2 * sinx * cosx * k0;
  639. }
  640. /*
  641. The coefficient containers for the series expansions.
  642. These structs allow the caller to only know the series order.
  643. */
  644. template <size_t SeriesOrder, typename CT>
  645. struct coeffs_C1 : boost::array<CT, SeriesOrder + 1>
  646. {
  647. coeffs_C1(CT const& epsilon)
  648. {
  649. evaluate_coeffs_C1(*this, epsilon);
  650. }
  651. };
  652. template <size_t SeriesOrder, typename CT>
  653. struct coeffs_C1p : boost::array<CT, SeriesOrder + 1>
  654. {
  655. coeffs_C1p(CT const& epsilon)
  656. {
  657. evaluate_coeffs_C1p(*this, epsilon);
  658. }
  659. };
  660. template <size_t SeriesOrder, typename CT>
  661. struct coeffs_C2 : boost::array<CT, SeriesOrder + 1>
  662. {
  663. coeffs_C2(CT const& epsilon)
  664. {
  665. evaluate_coeffs_C2(*this, epsilon);
  666. }
  667. };
  668. template <size_t SeriesOrder, typename CT>
  669. struct coeffs_C3x : boost::array<CT, (SeriesOrder * (SeriesOrder - 1)) / 2>
  670. {
  671. coeffs_C3x(CT const& n)
  672. {
  673. evaluate_coeffs_C3x<SeriesOrder>(*this, n);
  674. }
  675. };
  676. template <size_t SeriesOrder, typename CT>
  677. struct coeffs_C3 : boost::array<CT, SeriesOrder>
  678. {
  679. coeffs_C3(CT const& n, CT const& epsilon)
  680. {
  681. coeffs_C3x<SeriesOrder, CT> coeffs_C3x(n);
  682. evaluate_coeffs_C3(*this, coeffs_C3x, epsilon);
  683. }
  684. };
  685. template <size_t SeriesOrder, typename CT>
  686. struct coeffs_A3 : boost::array<CT, SeriesOrder>
  687. {
  688. coeffs_A3(CT const& n)
  689. {
  690. evaluate_coeffs_A3(*this, n);
  691. }
  692. };
  693. }}} // namespace boost::geometry::series_expansion
  694. #endif // BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP