3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <gsl/gsl_math.h>
24 #include <gsl/gsl_errno.h>
25 #include <gsl/gsl_integration.h>
31 gsl_integration_qng (const gsl_function *f,
33 double epsabs, double epsrel,
34 double * result, double * abserr, size_t * neval)
36 double fv1[5], fv2[5], fv3[5], fv4[5];
37 double savfun[21]; /* array of function values which have been computed */
38 double res10, res21, res43, res87; /* 10, 21, 43 and 87 point results */
39 double result_kronrod, err ;
40 double resabs; /* approximation to the integral of abs(f) */
41 double resasc; /* approximation to the integral of abs(f-i/(b-a)) */
43 const double half_length = 0.5 * (b - a);
44 const double abs_half_length = fabs (half_length);
45 const double center = 0.5 * (b + a);
46 const double f_center = GSL_FN_EVAL(f, center);
50 if (epsabs <= 0 && (epsrel < 50 * GSL_DBL_EPSILON || epsrel < 0.5e-28))
55 GSL_ERROR ("tolerance cannot be acheived with given epsabs and epsrel",
59 /* Compute the integral using the 10- and 21-point formula. */
62 res21 = w21b[5] * f_center;
63 resabs = w21b[5] * fabs (f_center);
65 for (k = 0; k < 5; k++)
67 const double abscissa = half_length * x1[k];
68 const double fval1 = GSL_FN_EVAL(f, center + abscissa);
69 const double fval2 = GSL_FN_EVAL(f, center - abscissa);
70 const double fval = fval1 + fval2;
71 res10 += w10[k] * fval;
72 res21 += w21a[k] * fval;
73 resabs += w21a[k] * (fabs (fval1) + fabs (fval2));
79 for (k = 0; k < 5; k++)
81 const double abscissa = half_length * x2[k];
82 const double fval1 = GSL_FN_EVAL(f, center + abscissa);
83 const double fval2 = GSL_FN_EVAL(f, center - abscissa);
84 const double fval = fval1 + fval2;
85 res21 += w21b[k] * fval;
86 resabs += w21b[k] * (fabs (fval1) + fabs (fval2));
92 resabs *= abs_half_length ;
95 const double mean = 0.5 * res21;
97 resasc = w21b[5] * fabs (f_center - mean);
99 for (k = 0; k < 5; k++)
102 (w21a[k] * (fabs (fv1[k] - mean) + fabs (fv2[k] - mean))
103 + w21b[k] * (fabs (fv3[k] - mean) + fabs (fv4[k] - mean)));
105 resasc *= abs_half_length ;
108 result_kronrod = res21 * half_length;
110 err = rescale_error ((res21 - res10) * half_length, resabs, resasc) ;
112 /* test for convergence. */
114 if (err < epsabs || err < epsrel * fabs (result_kronrod))
116 * result = result_kronrod ;
122 /* compute the integral using the 43-point formula. */
124 res43 = w43b[11] * f_center;
126 for (k = 0; k < 10; k++)
128 res43 += savfun[k] * w43a[k];
131 for (k = 0; k < 11; k++)
133 const double abscissa = half_length * x3[k];
134 const double fval = (GSL_FN_EVAL(f, center + abscissa)
135 + GSL_FN_EVAL(f, center - abscissa));
136 res43 += fval * w43b[k];
137 savfun[k + 10] = fval;
140 /* test for convergence */
142 result_kronrod = res43 * half_length;
143 err = rescale_error ((res43 - res21) * half_length, resabs, resasc);
145 if (err < epsabs || err < epsrel * fabs (result_kronrod))
147 * result = result_kronrod ;
153 /* compute the integral using the 87-point formula. */
155 res87 = w87b[22] * f_center;
157 for (k = 0; k < 21; k++)
159 res87 += savfun[k] * w87a[k];
162 for (k = 0; k < 22; k++)
164 const double abscissa = half_length * x4[k];
165 res87 += w87b[k] * (GSL_FN_EVAL(f, center + abscissa)
166 + GSL_FN_EVAL(f, center - abscissa));
169 /* test for convergence */
171 result_kronrod = res87 * half_length ;
173 err = rescale_error ((res87 - res43) * half_length, resabs, resasc);
175 if (err < epsabs || err < epsrel * fabs (result_kronrod))
177 * result = result_kronrod ;
183 /* failed to converge */
185 * result = result_kronrod ;
189 GSL_ERROR("failed to reach tolerance with highest-order rule", GSL_ETOL) ;