gsl_specfunc__mathieu_coeff.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* specfunc/mathieu_coeff.c
  2. *
  3. * Copyright (C) 2002 Lowell Johnson
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. /* Author: L. Johnson */
  20. #include "gsl__config.h"
  21. #include <stdlib.h>
  22. #include <math.h>
  23. #include "gsl_sf_mathieu.h"
  24. /*****************************************************************************
  25. * backward_recurse
  26. *
  27. * Purpose:
  28. ****************************************************************************/
  29. static void backward_recurse_c(double aa, double qq, double xx, double *ff,
  30. double *gx, int even_odd, int ni)
  31. {
  32. int ii, nn;
  33. double g1;
  34. g1 = *gx;
  35. ff[ni] = xx;
  36. if (even_odd == 0)
  37. {
  38. for (ii=0; ii<ni; ii++)
  39. {
  40. nn = GSL_SF_MATHIEU_COEFF - ii - 1;
  41. ff[ni-ii-1] = -1.0/((4*nn*nn - aa)/qq + ff[ni-ii]);
  42. }
  43. if (ni == GSL_SF_MATHIEU_COEFF - 1)
  44. ff[0] *= 2.0;
  45. }
  46. else
  47. {
  48. for (ii=0; ii<ni; ii++)
  49. {
  50. nn = GSL_SF_MATHIEU_COEFF - ii - 1;
  51. ff[ni-ii-1] = -1.0/(((2*nn + 1)*(2*nn + 1) - aa)/qq + ff[ni-ii]);
  52. }
  53. }
  54. *gx = ff[0] - g1;
  55. }
  56. static void backward_recurse_s(double aa, double qq, double xx, double *ff,
  57. double *gx, int even_odd, int ni)
  58. {
  59. int ii, nn;
  60. double g1;
  61. g1 = *gx;
  62. ff[ni] = xx;
  63. if (even_odd == 0)
  64. {
  65. for (ii=0; ii<ni; ii++)
  66. {
  67. nn = GSL_SF_MATHIEU_COEFF - ii - 1;
  68. ff[ni-ii-1] = -1.0/((4*(nn + 1)*(nn + 1) - aa)/qq + ff[ni-ii]);
  69. }
  70. }
  71. else
  72. {
  73. for (ii=0; ii<ni; ii++)
  74. {
  75. nn = GSL_SF_MATHIEU_COEFF - ii - 1;
  76. ff[ni-ii-1] = -1.0/(((2*nn + 1)*(2*nn + 1) - aa)/qq + ff[ni-ii]);
  77. }
  78. }
  79. *gx = ff[0] - g1;
  80. }
  81. int gsl_sf_mathieu_a_coeff(int order, double qq, double aa, double coeff[])
  82. {
  83. int ni, nn, ii, even_odd;
  84. double eps, g1, g2, x1, x2, e1, e2, de, xh, sum, ratio,
  85. ff[GSL_SF_MATHIEU_COEFF];
  86. eps = 1e-14;
  87. coeff[0] = 1.0;
  88. even_odd = 0;
  89. if (order % 2 != 0)
  90. even_odd = 1;
  91. /* If the coefficient array is not large enough to hold all necessary
  92. coefficients, error out. */
  93. if (order > GSL_SF_MATHIEU_COEFF)
  94. return GSL_FAILURE;
  95. /* Handle the trivial case where q = 0. */
  96. if (qq == 0.0)
  97. {
  98. for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
  99. coeff[ii] = 0.0;
  100. coeff[order/2] = 1.0;
  101. return GSL_SUCCESS;
  102. }
  103. if (order < 5)
  104. {
  105. nn = 0;
  106. sum = 0.0;
  107. if (even_odd == 0)
  108. ratio = aa/qq;
  109. else
  110. ratio = (aa - 1 - qq)/qq;
  111. }
  112. else
  113. {
  114. if (even_odd == 0)
  115. {
  116. coeff[1] = aa/qq;
  117. coeff[2] = (aa - 4)/qq*coeff[1] - 2;
  118. sum = coeff[0] + coeff[1] + coeff[2];
  119. for (ii=3; ii<order/2+1; ii++)
  120. {
  121. coeff[ii] = (aa - 4*(ii - 1)*(ii - 1))/qq*coeff[ii-1] -
  122. coeff[ii-2];
  123. sum += coeff[ii];
  124. }
  125. }
  126. else
  127. {
  128. coeff[1] = (aa - 1)/qq - 1;
  129. sum = coeff[0] + coeff[1];
  130. for (ii=2; ii<order/2+1; ii++)
  131. {
  132. coeff[ii] = (aa - (2*ii - 1)*(2*ii - 1))/qq*coeff[ii-1] -
  133. coeff[ii-2];
  134. sum += coeff[ii];
  135. }
  136. }
  137. nn = ii - 1;
  138. ratio = coeff[nn]/coeff[nn-1];
  139. }
  140. ni = GSL_SF_MATHIEU_COEFF - nn - 1;
  141. /* Compute first two points to start root-finding. */
  142. if (even_odd == 0)
  143. x1 = -qq/(4.0*GSL_SF_MATHIEU_COEFF*GSL_SF_MATHIEU_COEFF);
  144. else
  145. x1 = -qq/((2.0*GSL_SF_MATHIEU_COEFF + 1.0)*(2.0*GSL_SF_MATHIEU_COEFF + 1.0));
  146. g1 = ratio;
  147. backward_recurse_c(aa, qq, x1, ff, &g1, even_odd, ni);
  148. x2 = g1;
  149. g2 = ratio;
  150. backward_recurse_c(aa, qq, x2, ff, &g2, even_odd, ni);
  151. /* Find the root. */
  152. while (1)
  153. {
  154. /* Compute the relative error. */
  155. e1 = g1 - x1;
  156. e2 = g2 - x2;
  157. de = e1 - e2;
  158. /* If we are close enough to the root, break... */
  159. if (fabs(de) < eps)
  160. break;
  161. /* Otherwise, determine the next guess and try again. */
  162. xh = (e1*x2 - e2*x1)/de;
  163. x1 = x2;
  164. g1 = g2;
  165. x2 = xh;
  166. g2 = ratio;
  167. backward_recurse_c(aa, qq, x2, ff, &g2, even_odd, ni);
  168. }
  169. /* Compute the rest of the coefficients. */
  170. sum += coeff[nn];
  171. for (ii=nn+1; ii<GSL_SF_MATHIEU_COEFF; ii++)
  172. {
  173. coeff[ii] = ff[ii-nn-1]*coeff[ii-1];
  174. sum += coeff[ii];
  175. /* If the coefficients are getting really small, set the remainder
  176. to zero. */
  177. if (fabs(coeff[ii]) < 1e-20)
  178. {
  179. for (; ii<GSL_SF_MATHIEU_COEFF;)
  180. coeff[ii++] = 0.0;
  181. }
  182. }
  183. /* Normalize the coefficients. */
  184. for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
  185. coeff[ii] /= sum;
  186. return GSL_SUCCESS;
  187. }
  188. int gsl_sf_mathieu_b_coeff(int order, double qq, double aa, double coeff[])
  189. {
  190. int ni, nn, ii, even_odd;
  191. double eps, g1, g2, x1, x2, e1, e2, de, xh, sum, ratio,
  192. ff[GSL_SF_MATHIEU_COEFF];
  193. eps = 1e-10;
  194. coeff[0] = 1.0;
  195. even_odd = 0;
  196. if (order % 2 != 0)
  197. even_odd = 1;
  198. /* If the coefficient array is not large enough to hold all necessary
  199. coefficients, error out. */
  200. if (order > GSL_SF_MATHIEU_COEFF)
  201. return GSL_FAILURE;
  202. /* Handle the trivial case where q = 0. */
  203. if (qq == 0.0)
  204. {
  205. for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
  206. coeff[ii] = 0.0;
  207. coeff[(order-1)/2] = 1.0;
  208. return GSL_SUCCESS;
  209. }
  210. if (order < 5)
  211. {
  212. nn = 0;
  213. sum = 0.0;
  214. if (even_odd == 0)
  215. ratio = (aa - 4)/qq;
  216. else
  217. ratio = (aa - 1 - qq)/qq;
  218. }
  219. else
  220. {
  221. if (even_odd == 0)
  222. {
  223. coeff[1] = (aa - 4)/qq;
  224. sum = 2*coeff[0] + 4*coeff[1];
  225. for (ii=2; ii<order/2; ii++)
  226. {
  227. coeff[ii] = (aa - 4*ii*ii)/qq*coeff[ii-1] - coeff[ii-2];
  228. sum += 2*(ii + 1)*coeff[ii];
  229. }
  230. }
  231. else
  232. {
  233. coeff[1] = (aa - 1)/qq + 1;
  234. sum = coeff[0] + 3*coeff[1];
  235. for (ii=2; ii<order/2+1; ii++)
  236. {
  237. coeff[ii] = (aa - (2*ii - 1)*(2*ii - 1))/qq*coeff[ii-1] -
  238. coeff[ii-2];
  239. sum += (2*(ii + 1) - 1)*coeff[ii];
  240. }
  241. }
  242. nn = ii - 1;
  243. ratio = coeff[nn]/coeff[nn-1];
  244. }
  245. ni = GSL_SF_MATHIEU_COEFF - nn - 1;
  246. /* Compute first two points to start root-finding. */
  247. if (even_odd == 0)
  248. x1 = -qq/(4.0*(GSL_SF_MATHIEU_COEFF + 1.0)*(GSL_SF_MATHIEU_COEFF + 1.0));
  249. else
  250. x1 = -qq/((2.0*GSL_SF_MATHIEU_COEFF + 1.0)*(2.0*GSL_SF_MATHIEU_COEFF + 1.0));
  251. g1 = ratio;
  252. backward_recurse_s(aa, qq, x1, ff, &g1, even_odd, ni);
  253. x2 = g1;
  254. g2 = ratio;
  255. backward_recurse_s(aa, qq, x2, ff, &g2, even_odd, ni);
  256. /* Find the root. */
  257. while (1)
  258. {
  259. /* Compute the relative error. */
  260. e1 = g1 - x1;
  261. e2 = g2 - x2;
  262. de = e1 - e2;
  263. /* If we are close enough to the root, break... */
  264. if (fabs(de) < eps)
  265. break;
  266. /* Otherwise, determine the next guess and try again. */
  267. xh = (e1*x2 - e2*x1)/de;
  268. x1 = x2;
  269. g1 = g2;
  270. x2 = xh;
  271. g2 = ratio;
  272. backward_recurse_s(aa, qq, x2, ff, &g2, even_odd, ni);
  273. }
  274. /* Compute the rest of the coefficients. */
  275. sum += 2*(nn + 1)*coeff[nn];
  276. for (ii=nn+1; ii<GSL_SF_MATHIEU_COEFF; ii++)
  277. {
  278. coeff[ii] = ff[ii-nn-1]*coeff[ii-1];
  279. sum += 2*(ii + 1)*coeff[ii];
  280. /* If the coefficients are getting really small, set the remainder
  281. to zero. */
  282. if (fabs(coeff[ii]) < 1e-20)
  283. {
  284. for (; ii<GSL_SF_MATHIEU_COEFF;)
  285. coeff[ii++] = 0.0;
  286. }
  287. }
  288. /* Normalize the coefficients. */
  289. for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
  290. coeff[ii] /= sum;
  291. return GSL_SUCCESS;
  292. }