summaryrefslogtreecommitdiff
path: root/gsl-1.9/integration/qc25f.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsl-1.9/integration/qc25f.c')
-rw-r--r--gsl-1.9/integration/qc25f.c158
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 ;
+}
+