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.
22 #include <gsl/gsl_errno.h>
23 #include <gsl/gsl_integration.h>
25 #include "initialise.c"
26 #include "set_initial.c"
32 #include "positivity.c"
34 static int qags (const gsl_function * f, const double a, const double
35 b, const double epsabs, const double epsrel, const size_t limit,
36 gsl_integration_workspace * workspace, double *result, double *abserr,
37 gsl_integration_rule * q);
40 gsl_integration_qags (const gsl_function *f,
42 double epsabs, double epsrel, size_t limit,
43 gsl_integration_workspace * workspace,
44 double * result, double * abserr)
46 int status = qags (f, a, b, epsabs, epsrel, limit,
49 &gsl_integration_qk21) ;
53 /* QAGI: evaluate an integral over an infinite range using the
56 integrate(f(x),-Inf,Inf) = integrate((f((1-t)/t) + f(-(1-t)/t))/t^2,0,1)
60 static double i_transform (double t, void *params);
63 gsl_integration_qagi (gsl_function * f,
64 double epsabs, double epsrel, size_t limit,
65 gsl_integration_workspace * workspace,
66 double *result, double *abserr)
70 gsl_function f_transform;
72 f_transform.function = &i_transform;
73 f_transform.params = f;
75 status = qags (&f_transform, 0.0, 1.0,
76 epsabs, epsrel, limit,
79 &gsl_integration_qk15);
85 i_transform (double t, void *params)
87 gsl_function *f = (gsl_function *) params;
88 double x = (1 - t) / t;
89 double y = GSL_FN_EVAL (f, x) + GSL_FN_EVAL (f, -x);
94 /* QAGIL: Evaluate an integral over an infinite range using the
97 integrate(f(x),-Inf,b) = integrate(f(b-(1-t)/t)/t^2,0,1)
101 struct il_params { double b ; gsl_function * f ; } ;
103 static double il_transform (double t, void *params);
106 gsl_integration_qagil (gsl_function * f,
108 double epsabs, double epsrel, size_t limit,
109 gsl_integration_workspace * workspace,
110 double *result, double *abserr)
114 gsl_function f_transform;
115 struct il_params transform_params ;
117 transform_params.b = b ;
118 transform_params.f = f ;
120 f_transform.function = &il_transform;
121 f_transform.params = &transform_params;
123 status = qags (&f_transform, 0.0, 1.0,
124 epsabs, epsrel, limit,
127 &gsl_integration_qk15);
133 il_transform (double t, void *params)
135 struct il_params *p = (struct il_params *) params;
137 gsl_function * f = p->f;
138 double x = b - (1 - t) / t;
139 double y = GSL_FN_EVAL (f, x);
143 /* QAGIU: Evaluate an integral over an infinite range using the
146 integrate(f(x),a,Inf) = integrate(f(a+(1-t)/t)/t^2,0,1)
150 struct iu_params { double a ; gsl_function * f ; } ;
152 static double iu_transform (double t, void *params);
155 gsl_integration_qagiu (gsl_function * f,
157 double epsabs, double epsrel, size_t limit,
158 gsl_integration_workspace * workspace,
159 double *result, double *abserr)
163 gsl_function f_transform;
164 struct iu_params transform_params ;
166 transform_params.a = a ;
167 transform_params.f = f ;
169 f_transform.function = &iu_transform;
170 f_transform.params = &transform_params;
172 status = qags (&f_transform, 0.0, 1.0,
173 epsabs, epsrel, limit,
176 &gsl_integration_qk15);
182 iu_transform (double t, void *params)
184 struct iu_params *p = (struct iu_params *) params;
186 gsl_function * f = p->f;
187 double x = a + (1 - t) / t;
188 double y = GSL_FN_EVAL (f, x);
192 /* Main integration function */
195 qags (const gsl_function * f,
196 const double a, const double b,
197 const double epsabs, const double epsrel,
199 gsl_integration_workspace * workspace,
200 double *result, double *abserr,
201 gsl_integration_rule * q)
204 double res_ext, err_ext;
205 double result0, abserr0, resabs0, resasc0;
209 double error_over_large_intervals = 0;
210 double reseps = 0, abseps = 0, correc = 0;
212 int roundoff_type1 = 0, roundoff_type2 = 0, roundoff_type3 = 0;
213 int error_type = 0, error_type2 = 0;
215 size_t iteration = 0;
217 int positive_integrand = 0;
219 int disallow_extrapolation = 0;
221 struct extrapolation_table table;
223 /* Initialize results */
225 initialise (workspace, a, b);
230 if (limit > workspace->limit)
232 GSL_ERROR ("iteration limit exceeds available workspace", GSL_EINVAL) ;
235 /* Test on accuracy */
237 if (epsabs <= 0 && (epsrel < 50 * GSL_DBL_EPSILON || epsrel < 0.5e-28))
239 GSL_ERROR ("tolerance cannot be acheived with given epsabs and epsrel",
243 /* Perform the first integration */
245 q (f, a, b, &result0, &abserr0, &resabs0, &resasc0);
247 set_initial_result (workspace, result0, abserr0);
249 tolerance = GSL_MAX_DBL (epsabs, epsrel * fabs (result0));
251 if (abserr0 <= 100 * GSL_DBL_EPSILON * resabs0 && abserr0 > tolerance)
256 GSL_ERROR ("cannot reach tolerance because of roundoff error"
257 "on first attempt", GSL_EROUND);
259 else if ((abserr0 <= tolerance && abserr0 != resasc0) || abserr0 == 0.0)
271 GSL_ERROR ("a maximum of one iteration was insufficient", GSL_EMAXITER);
276 initialise_table (&table);
277 append_table (&table, result0);
283 err_ext = GSL_DBL_MAX;
285 positive_integrand = test_positivity (result0, resabs0);
291 size_t current_level;
292 double a1, b1, a2, b2;
293 double a_i, b_i, r_i, e_i;
294 double area1 = 0, area2 = 0, area12 = 0;
295 double error1 = 0, error2 = 0, error12 = 0;
296 double resasc1, resasc2;
297 double resabs1, resabs2;
300 /* Bisect the subinterval with the largest error estimate */
302 retrieve (workspace, &a_i, &b_i, &r_i, &e_i);
304 current_level = workspace->level[workspace->i] + 1;
307 b1 = 0.5 * (a_i + b_i);
313 q (f, a1, b1, &area1, &error1, &resabs1, &resasc1);
314 q (f, a2, b2, &area2, &error2, &resabs2, &resasc2);
316 area12 = area1 + area2;
317 error12 = error1 + error2;
320 /* Improve previous approximations to the integral and test for
323 We write these expressions in the same way as the original
324 QUADPACK code so that the rounding errors are the same, which
325 makes testing easier. */
327 errsum = errsum + error12 - e_i;
328 area = area + area12 - r_i;
330 tolerance = GSL_MAX_DBL (epsabs, epsrel * fabs (area));
332 if (resasc1 != error1 && resasc2 != error2)
334 double delta = r_i - area12;
336 if (fabs (delta) <= 1.0e-5 * fabs (area12) && error12 >= 0.99 * e_i)
347 if (iteration > 10 && error12 > e_i)
353 /* Test for roundoff and eventually set error flag */
355 if (roundoff_type1 + roundoff_type2 >= 10 || roundoff_type3 >= 20)
357 error_type = 2; /* round off error */
360 if (roundoff_type2 >= 5)
365 /* set error flag in the case of bad integrand behaviour at
366 a point of the integration range */
368 if (subinterval_too_small (a1, a2, b2))
373 /* append the newly-created intervals to the list */
375 update (workspace, a1, b1, area1, error1, a2, b2, area2, error2);
377 if (errsum <= tolerance)
387 if (iteration >= limit - 1)
393 if (iteration == 2) /* set up variables on first iteration */
395 error_over_large_intervals = errsum;
397 append_table (&table, area);
401 if (disallow_extrapolation)
406 error_over_large_intervals += -last_e_i;
408 if (current_level < workspace->maximum_level)
410 error_over_large_intervals += error12;
415 /* test whether the interval to be bisected next is the
416 smallest interval. */
418 if (large_interval (workspace))
422 workspace->nrmax = 1;
425 if (!error_type2 && error_over_large_intervals > ertest)
427 if (increase_nrmax (workspace))
431 /* Perform extrapolation */
433 append_table (&table, area);
435 qelg (&table, &reseps, &abseps);
439 if (ktmin > 5 && err_ext < 0.001 * errsum)
444 if (abseps < err_ext)
449 correc = error_over_large_intervals;
450 ertest = GSL_MAX_DBL (epsabs, epsrel * fabs (reseps));
451 if (err_ext <= ertest)
455 /* Prepare bisection of the smallest interval. */
459 disallow_extrapolation = 1;
467 /* work on interval with largest error */
469 reset_nrmax (workspace);
471 error_over_large_intervals = errsum;
474 while (iteration < limit);
479 if (err_ext == GSL_DBL_MAX)
482 if (error_type || error_type2)
492 if (res_ext != 0.0 && area != 0.0)
494 if (err_ext / fabs (res_ext) > errsum / fabs (area))
497 else if (err_ext > errsum)
501 else if (area == 0.0)
507 /* Test on divergence. */
510 double max_area = GSL_MAX_DBL (fabs (res_ext), fabs (area));
512 if (!positive_integrand && max_area < 0.01 * resabs0)
517 double ratio = res_ext / area;
519 if (ratio < 0.01 || ratio > 100.0 || errsum > fabs (area))
527 *result = sum_results (workspace);
541 else if (error_type == 1)
543 GSL_ERROR ("number of iterations was insufficient", GSL_EMAXITER);
545 else if (error_type == 2)
547 GSL_ERROR ("cannot reach tolerance because of roundoff error",
550 else if (error_type == 3)
552 GSL_ERROR ("bad integrand behavior found in the integration interval",
555 else if (error_type == 4)
557 GSL_ERROR ("roundoff error detected in the extrapolation table",
560 else if (error_type == 5)
562 GSL_ERROR ("integral is divergent, or slowly convergent",
567 GSL_ERROR ("could not integrate function", GSL_EFAILED);