1 /* specfunc/mathieu_coeff.c
3 * Copyright (C) 2002 Lowell Johnson
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.
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.
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.
20 /* Author: L. Johnson */
25 #include <gsl/gsl_sf_mathieu.h>
28 /*****************************************************************************
32 ****************************************************************************/
33 static void backward_recurse_c(double aa, double qq, double xx, double *ff,
34 double *gx, int even_odd, int ni)
45 for (ii=0; ii<ni; ii++)
47 nn = GSL_SF_MATHIEU_COEFF - ii - 1;
48 ff[ni-ii-1] = -1.0/((4*nn*nn - aa)/qq + ff[ni-ii]);
50 if (ni == GSL_SF_MATHIEU_COEFF - 1)
55 for (ii=0; ii<ni; ii++)
57 nn = GSL_SF_MATHIEU_COEFF - ii - 1;
58 ff[ni-ii-1] = -1.0/(((2*nn + 1)*(2*nn + 1) - aa)/qq + ff[ni-ii]);
66 static void backward_recurse_s(double aa, double qq, double xx, double *ff,
67 double *gx, int even_odd, int ni)
78 for (ii=0; ii<ni; ii++)
80 nn = GSL_SF_MATHIEU_COEFF - ii - 1;
81 ff[ni-ii-1] = -1.0/((4*(nn + 1)*(nn + 1) - aa)/qq + ff[ni-ii]);
86 for (ii=0; ii<ni; ii++)
88 nn = GSL_SF_MATHIEU_COEFF - ii - 1;
89 ff[ni-ii-1] = -1.0/(((2*nn + 1)*(2*nn + 1) - aa)/qq + ff[ni-ii]);
97 int gsl_sf_mathieu_a_coeff(int order, double qq, double aa, double coeff[])
99 int ni, nn, ii, even_odd;
100 double eps, g1, g2, x1, x2, e1, e2, de, xh, sum, ratio,
101 ff[GSL_SF_MATHIEU_COEFF];
111 /* If the coefficient array is not large enough to hold all necessary
112 coefficients, error out. */
113 if (order > GSL_SF_MATHIEU_COEFF)
116 /* Handle the trivial case where q = 0. */
119 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
122 coeff[order/2] = 1.0;
134 ratio = (aa - 1 - qq)/qq;
141 coeff[2] = (aa - 4)/qq*coeff[1] - 2;
142 sum = coeff[0] + coeff[1] + coeff[2];
143 for (ii=3; ii<order/2+1; ii++)
145 coeff[ii] = (aa - 4*(ii - 1)*(ii - 1))/qq*coeff[ii-1] -
152 coeff[1] = (aa - 1)/qq - 1;
153 sum = coeff[0] + coeff[1];
154 for (ii=2; ii<order/2+1; ii++)
156 coeff[ii] = (aa - (2*ii - 1)*(2*ii - 1))/qq*coeff[ii-1] -
164 ratio = coeff[nn]/coeff[nn-1];
167 ni = GSL_SF_MATHIEU_COEFF - nn - 1;
169 /* Compute first two points to start root-finding. */
171 x1 = -qq/(4.0*GSL_SF_MATHIEU_COEFF*GSL_SF_MATHIEU_COEFF);
173 x1 = -qq/((2.0*GSL_SF_MATHIEU_COEFF + 1.0)*(2.0*GSL_SF_MATHIEU_COEFF + 1.0));
175 backward_recurse_c(aa, qq, x1, ff, &g1, even_odd, ni);
178 backward_recurse_c(aa, qq, x2, ff, &g2, even_odd, ni);
183 /* Compute the relative error. */
188 /* If we are close enough to the root, break... */
192 /* Otherwise, determine the next guess and try again. */
193 xh = (e1*x2 - e2*x1)/de;
198 backward_recurse_c(aa, qq, x2, ff, &g2, even_odd, ni);
201 /* Compute the rest of the coefficients. */
203 for (ii=nn+1; ii<GSL_SF_MATHIEU_COEFF; ii++)
205 coeff[ii] = ff[ii-nn-1]*coeff[ii-1];
208 /* If the coefficients are getting really small, set the remainder
210 if (fabs(coeff[ii]) < 1e-20)
212 for (; ii<GSL_SF_MATHIEU_COEFF;)
217 /* Normalize the coefficients. */
218 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
225 int gsl_sf_mathieu_b_coeff(int order, double qq, double aa, double coeff[])
227 int ni, nn, ii, even_odd;
228 double eps, g1, g2, x1, x2, e1, e2, de, xh, sum, ratio,
229 ff[GSL_SF_MATHIEU_COEFF];
239 /* If the coefficient array is not large enough to hold all necessary
240 coefficients, error out. */
241 if (order > GSL_SF_MATHIEU_COEFF)
244 /* Handle the trivial case where q = 0. */
247 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
250 coeff[(order-1)/2] = 1.0;
262 ratio = (aa - 1 - qq)/qq;
268 coeff[1] = (aa - 4)/qq;
269 sum = 2*coeff[0] + 4*coeff[1];
270 for (ii=2; ii<order/2; ii++)
272 coeff[ii] = (aa - 4*ii*ii)/qq*coeff[ii-1] - coeff[ii-2];
273 sum += 2*(ii + 1)*coeff[ii];
278 coeff[1] = (aa - 1)/qq + 1;
279 sum = coeff[0] + 3*coeff[1];
280 for (ii=2; ii<order/2+1; ii++)
282 coeff[ii] = (aa - (2*ii - 1)*(2*ii - 1))/qq*coeff[ii-1] -
284 sum += (2*(ii + 1) - 1)*coeff[ii];
290 ratio = coeff[nn]/coeff[nn-1];
293 ni = GSL_SF_MATHIEU_COEFF - nn - 1;
295 /* Compute first two points to start root-finding. */
297 x1 = -qq/(4.0*(GSL_SF_MATHIEU_COEFF + 1.0)*(GSL_SF_MATHIEU_COEFF + 1.0));
299 x1 = -qq/((2.0*GSL_SF_MATHIEU_COEFF + 1.0)*(2.0*GSL_SF_MATHIEU_COEFF + 1.0));
301 backward_recurse_s(aa, qq, x1, ff, &g1, even_odd, ni);
304 backward_recurse_s(aa, qq, x2, ff, &g2, even_odd, ni);
309 /* Compute the relative error. */
314 /* If we are close enough to the root, break... */
318 /* Otherwise, determine the next guess and try again. */
319 xh = (e1*x2 - e2*x1)/de;
324 backward_recurse_s(aa, qq, x2, ff, &g2, even_odd, ni);
327 /* Compute the rest of the coefficients. */
328 sum += 2*(nn + 1)*coeff[nn];
329 for (ii=nn+1; ii<GSL_SF_MATHIEU_COEFF; ii++)
331 coeff[ii] = ff[ii-nn-1]*coeff[ii-1];
332 sum += 2*(ii + 1)*coeff[ii];
334 /* If the coefficients are getting really small, set the remainder
336 if (fabs(coeff[ii]) < 1e-20)
338 for (; ii<GSL_SF_MATHIEU_COEFF;)
343 /* Normalize the coefficients. */
344 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)