diff options
Diffstat (limited to 'gsl-1.9/integration/qc25f.c')
-rw-r--r-- | gsl-1.9/integration/qc25f.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/gsl-1.9/integration/qc25f.c b/gsl-1.9/integration/qc25f.c new file mode 100644 index 0000000..73c085c --- /dev/null +++ b/gsl-1.9/integration/qc25f.c @@ -0,0 +1,158 @@ +/* integration/qc25f.c + * + * Copyright (C) 1996, 1997, 1998, 1999, 2000 Brian Gough + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +struct fn_fourier_params +{ + gsl_function *function; + double omega; +}; + +static double fn_sin (double t, void *params); +static double fn_cos (double t, void *params); + +static void +qc25f (gsl_function * f, double a, double b, + gsl_integration_qawo_table * wf, size_t level, + double *result, double *abserr, double *resabs, double *resasc); + +static void +qc25f (gsl_function * f, double a, double b, + gsl_integration_qawo_table * wf, size_t level, + double *result, double *abserr, double *resabs, double *resasc) +{ + const double center = 0.5 * (a + b); + const double half_length = 0.5 * (b - a); + const double omega = wf->omega ; + + const double par = omega * half_length; + + if (fabs (par) < 2) + { + gsl_function weighted_function; + struct fn_fourier_params fn_params; + + fn_params.function = f; + fn_params.omega = omega; + + if (wf->sine == GSL_INTEG_SINE) + { + weighted_function.function = &fn_sin; + } + else + { + weighted_function.function = &fn_cos; + } + + weighted_function.params = &fn_params; + + gsl_integration_qk15 (&weighted_function, a, b, result, abserr, + resabs, resasc); + + return; + } + else + { + double *moment; + double cheb12[13], cheb24[25]; + double result_abs, res12_cos, res12_sin, res24_cos, res24_sin; + double est_cos, est_sin; + double c, s; + size_t i; + + gsl_integration_qcheb (f, a, b, cheb12, cheb24); + + if (level >= wf->n) + { + /* table overflow should not happen, check before calling */ + GSL_ERROR_VOID("table overflow in internal function", GSL_ESANITY); + } + + /* obtain moments from the table */ + + moment = wf->chebmo + 25 * level; + + res12_cos = cheb12[12] * moment[12]; + res12_sin = 0 ; + + for (i = 0; i < 6; i++) + { + size_t k = 10 - 2 * i; + res12_cos += cheb12[k] * moment[k]; + res12_sin += cheb12[k + 1] * moment[k + 1]; + } + + res24_cos = cheb24[24] * moment[24]; + res24_sin = 0 ; + + result_abs = fabs(cheb24[24]) ; + + for (i = 0; i < 12; i++) + { + size_t k = 22 - 2 * i; + res24_cos += cheb24[k] * moment[k]; + res24_sin += cheb24[k + 1] * moment[k + 1]; + result_abs += fabs(cheb24[k]) + fabs(cheb24[k+1]); + } + + est_cos = fabs(res24_cos - res12_cos); + est_sin = fabs(res24_sin - res12_sin); + + c = half_length * cos(center * omega); + s = half_length * sin(center * omega); + + if (wf->sine == GSL_INTEG_SINE) + { + *result = c * res24_sin + s * res24_cos; + *abserr = fabs(c * est_sin) + fabs(s * est_cos); + } + else + { + *result = c * res24_cos - s * res24_sin; + *abserr = fabs(c * est_cos) + fabs(s * est_sin); + } + + *resabs = result_abs * half_length; + *resasc = GSL_DBL_MAX; + + return; + } +} + +static double +fn_sin (double x, void *params) +{ + struct fn_fourier_params *p = (struct fn_fourier_params *) params; + gsl_function *f = p->function; + double w = p->omega; + double wx = w * x; + double sinwx = sin(wx) ; + return GSL_FN_EVAL (f, x) * sinwx; +} + +static double +fn_cos (double x, void *params) +{ + struct fn_fourier_params *p = (struct fn_fourier_params *) params; + gsl_function *f = p->function; + double w = p->omega; + double wx = w * x; + double coswx = cos(wx) ; + return GSL_FN_EVAL (f, x) * coswx ; +} + |