1 /* specfunc/mathieu_angfunc.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 */
26 #include <gsl/gsl_math.h>
27 #include <gsl/gsl_sf_mathieu.h>
30 int gsl_sf_mathieu_ce(int order, double qq, double zz, gsl_sf_result *result)
32 int even_odd, ii, status;
33 double coeff[GSL_SF_MATHIEU_COEFF], norm, fn, factor;
42 /* Handle the trivial case where q = 0. */
49 fn = cos(order*zz)/norm;
52 result->err = 2.0*GSL_DBL_EPSILON;
55 result->err *= factor;
60 /* Use symmetry characteristics of the functions to handle cases with
65 /* Compute the characteristic value. */
66 status = gsl_sf_mathieu_a(order, qq, &aa);
67 if (status != GSL_SUCCESS)
72 /* Compute the series coefficients. */
73 status = gsl_sf_mathieu_a_coeff(order, qq, aa.val, coeff);
74 if (status != GSL_SUCCESS)
82 norm = coeff[0]*coeff[0];
83 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
85 fn += coeff[ii]*cos(2.0*ii*zz);
86 norm += coeff[ii]*coeff[ii];
92 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
94 fn += coeff[ii]*cos((2.0*ii + 1.0)*zz);
95 norm += coeff[ii]*coeff[ii];
103 result->err = 2.0*GSL_DBL_EPSILON;
106 result->err *= factor;
112 int gsl_sf_mathieu_se(int order, double qq, double zz, gsl_sf_result *result)
114 int even_odd, ii, status;
115 double coeff[GSL_SF_MATHIEU_COEFF], norm, fn, factor;
124 /* Handle the trivial cases where order = 0 and/or q = 0. */
138 result->err = 2.0*GSL_DBL_EPSILON;
141 result->err *= factor;
146 /* Use symmetry characteristics of the functions to handle cases with
151 /* Compute the characteristic value. */
152 status = gsl_sf_mathieu_b(order, qq, &aa);
153 if (status != GSL_SUCCESS)
158 /* Compute the series coefficients. */
159 status = gsl_sf_mathieu_b_coeff(order, qq, aa.val, coeff);
160 if (status != GSL_SUCCESS)
168 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
170 norm += coeff[ii]*coeff[ii];
171 fn += coeff[ii]*sin(2.0*(ii + 1)*zz);
177 for (ii=0; ii<GSL_SF_MATHIEU_COEFF; ii++)
179 norm += coeff[ii]*coeff[ii];
180 fn += coeff[ii]*sin((2.0*ii + 1)*zz);
187 result->err = 2.0*GSL_DBL_EPSILON;
190 result->err *= factor;
196 int gsl_sf_mathieu_ce_array(int nmin, int nmax, double qq, double zz,
197 gsl_sf_mathieu_workspace *work,
198 double result_array[])
200 int even_odd, order, ii, jj, status;
201 double coeff[GSL_SF_MATHIEU_COEFF], *aa = work->aa, norm;
204 /* Initialize the result array to zeroes. */
205 for (ii=0; ii<nmax-nmin+1; ii++)
206 result_array[ii] = 0.0;
208 /* Ensure that the workspace is large enough to accomodate. */
209 if (work->size < (unsigned int)nmax)
211 GSL_ERROR("Work space not large enough", GSL_EINVAL);
214 if (nmin < 0 || nmax < nmin)
216 GSL_ERROR("domain error", GSL_EDOM);
219 /* Compute all of the eigenvalues up to nmax. */
220 gsl_sf_mathieu_a_array(0, nmax, qq, work, aa);
222 for (ii=0, order=nmin; order<=nmax; ii++, order++)
229 /* Handle the trivial case where q = 0. */
236 result_array[ii] = cos(order*zz)/norm;
241 /* Compute the series coefficients. */
242 status = gsl_sf_mathieu_a_coeff(order, qq, aa[order], coeff);
243 if (status != GSL_SUCCESS)
248 norm = coeff[0]*coeff[0];
249 for (jj=0; jj<GSL_SF_MATHIEU_COEFF; jj++)
251 result_array[ii] += coeff[jj]*cos(2.0*jj*zz);
252 norm += coeff[jj]*coeff[jj];
257 for (jj=0; jj<GSL_SF_MATHIEU_COEFF; jj++)
259 result_array[ii] += coeff[jj]*cos((2.0*jj + 1.0)*zz);
260 norm += coeff[jj]*coeff[jj];
265 result_array[ii] /= norm;
272 int gsl_sf_mathieu_se_array(int nmin, int nmax, double qq, double zz,
273 gsl_sf_mathieu_workspace *work,
274 double result_array[])
276 int even_odd, order, ii, jj, status;
277 double coeff[GSL_SF_MATHIEU_COEFF], *bb = work->bb, norm;
280 /* Initialize the result array to zeroes. */
281 for (ii=0; ii<nmax-nmin+1; ii++)
282 result_array[ii] = 0.0;
284 /* Ensure that the workspace is large enough to accomodate. */
285 if (work->size < (unsigned int)nmax)
287 GSL_ERROR("Work space not large enough", GSL_EINVAL);
290 if (nmin < 0 || nmax < nmin)
292 GSL_ERROR("domain error", GSL_EDOM);
295 /* Compute all of the eigenvalues up to nmax. */
296 gsl_sf_mathieu_b_array(0, nmax, qq, work, bb);
298 for (ii=0, order=nmin; order<=nmax; ii++, order++)
305 /* Handle the trivial case where q = 0. */
309 result_array[ii] = sin(order*zz);
314 /* Compute the series coefficients. */
315 status = gsl_sf_mathieu_b_coeff(order, qq, bb[order], coeff);
316 if (status != GSL_SUCCESS)
323 for (jj=0; jj<GSL_SF_MATHIEU_COEFF; jj++)
325 result_array[ii] += coeff[jj]*sin(2.0*(jj + 1)*zz);
326 norm += coeff[jj]*coeff[jj];
331 for (jj=0; jj<GSL_SF_MATHIEU_COEFF; jj++)
333 result_array[ii] += coeff[jj]*sin((2.0*jj + 1.0)*zz);
334 norm += coeff[jj]*coeff[jj];
339 result_array[ii] /= norm;