Blame integration/qawf.c

Packit 67cb25
/* integration/qawf.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <math.h>
Packit 67cb25
#include <float.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_integration.h>
Packit 67cb25
Packit 67cb25
#include "initialise.c"
Packit 67cb25
#include "append.c"
Packit 67cb25
#include "qelg.c"
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_integration_qawf (gsl_function * f,
Packit 67cb25
                      const double a,
Packit 67cb25
                      const double epsabs,
Packit 67cb25
                      const size_t limit,
Packit 67cb25
                      gsl_integration_workspace * workspace,
Packit 67cb25
                      gsl_integration_workspace * cycle_workspace,
Packit 67cb25
                      gsl_integration_qawo_table * wf,
Packit 67cb25
                      double *result, double *abserr)
Packit 67cb25
{
Packit 67cb25
  double area, errsum;
Packit 67cb25
  double res_ext, err_ext;
Packit 67cb25
  double correc, total_error = 0.0, truncation_error;
Packit 67cb25
Packit 67cb25
  size_t ktmin = 0;
Packit 67cb25
  size_t iteration = 0;
Packit 67cb25
Packit 67cb25
  struct extrapolation_table table;
Packit 67cb25
Packit 67cb25
  double cycle;
Packit 67cb25
  double omega = wf->omega;
Packit 67cb25
Packit 67cb25
  const double p = 0.9;
Packit 67cb25
  double factor = 1;
Packit 67cb25
  double initial_eps, eps;
Packit 67cb25
  int error_type = 0;
Packit 67cb25
Packit 67cb25
  /* Initialize results */
Packit 67cb25
Packit 67cb25
  initialise (workspace, a, a);
Packit 67cb25
Packit 67cb25
  *result = 0;
Packit 67cb25
  *abserr = 0;
Packit 67cb25
Packit 67cb25
  if (limit > workspace->limit)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("iteration limit exceeds available workspace", GSL_EINVAL) ;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Test on accuracy */
Packit 67cb25
Packit 67cb25
  if (epsabs <= 0)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("absolute tolerance epsabs must be positive", GSL_EBADTOL) ;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (omega == 0.0)
Packit 67cb25
    {
Packit 67cb25
      if (wf->sine == GSL_INTEG_SINE)
Packit 67cb25
        {
Packit 67cb25
          /* The function sin(w x) f(x) is always zero for w = 0 */
Packit 67cb25
Packit 67cb25
          *result = 0;
Packit 67cb25
          *abserr = 0;
Packit 67cb25
Packit 67cb25
          return GSL_SUCCESS;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          /* The function cos(w x) f(x) is always f(x) for w = 0 */
Packit 67cb25
Packit 67cb25
          int status = gsl_integration_qagiu (f, a, epsabs, 0.0,
Packit 67cb25
                                              cycle_workspace->limit,
Packit 67cb25
                                              cycle_workspace,
Packit 67cb25
                                              result, abserr);
Packit 67cb25
          return status;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (epsabs > GSL_DBL_MIN / (1 - p))
Packit 67cb25
    {
Packit 67cb25
      eps = epsabs * (1 - p);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      eps = epsabs;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  initial_eps = eps;
Packit 67cb25
Packit 67cb25
  area = 0;
Packit 67cb25
  errsum = 0;
Packit 67cb25
Packit 67cb25
  res_ext = 0;
Packit 67cb25
  err_ext = GSL_DBL_MAX;
Packit 67cb25
  correc = 0;
Packit 67cb25
Packit 67cb25
  cycle = (2 * floor (fabs (omega)) + 1) * M_PI / fabs (omega);
Packit 67cb25
Packit 67cb25
  gsl_integration_qawo_table_set_length (wf, cycle);
Packit 67cb25
Packit 67cb25
  initialise_table (&table);
Packit 67cb25
Packit 67cb25
  for (iteration = 0; iteration < limit; iteration++)
Packit 67cb25
    {
Packit 67cb25
      double area1, error1, reseps, erreps;
Packit 67cb25
Packit 67cb25
      double a1 = a + iteration * cycle;
Packit 67cb25
      double b1 = a1 + cycle;
Packit 67cb25
Packit 67cb25
      double epsabs1 = eps * factor;
Packit 67cb25
Packit 67cb25
      int status = gsl_integration_qawo (f, a1, epsabs1, 0.0, limit,
Packit 67cb25
                                         cycle_workspace, wf,
Packit 67cb25
                                         &area1, &error1);
Packit 67cb25
Packit 67cb25
      append_interval (workspace, a1, b1, area1, error1);
Packit 67cb25
Packit 67cb25
      factor *= p;
Packit 67cb25
Packit 67cb25
      area = area + area1;
Packit 67cb25
      errsum = errsum + error1;
Packit 67cb25
Packit 67cb25
      /* estimate the truncation error as 50 times the final term */
Packit 67cb25
Packit 67cb25
      truncation_error = 50 * fabs (area1);
Packit 67cb25
Packit 67cb25
      total_error = errsum + truncation_error;
Packit 67cb25
Packit 67cb25
      if (total_error < epsabs && iteration > 4)
Packit 67cb25
        {
Packit 67cb25
          goto compute_result;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (error1 > correc)
Packit 67cb25
        {
Packit 67cb25
          correc = error1;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (status)
Packit 67cb25
        {
Packit 67cb25
          eps = GSL_MAX_DBL (initial_eps, correc * (1.0 - p));
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (status && total_error < 10 * correc && iteration > 3)
Packit 67cb25
        {
Packit 67cb25
          goto compute_result;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      append_table (&table, area);
Packit 67cb25
Packit 67cb25
      if (table.n < 2)
Packit 67cb25
        {
Packit 67cb25
          continue;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      qelg (&table, &reseps, &erreps);
Packit 67cb25
Packit 67cb25
      ktmin++;
Packit 67cb25
Packit 67cb25
      if (ktmin >= 15 && err_ext < 0.001 * total_error)
Packit 67cb25
        {
Packit 67cb25
          error_type = 4;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      if (erreps < err_ext)
Packit 67cb25
        {
Packit 67cb25
          ktmin = 0;
Packit 67cb25
          err_ext = erreps;
Packit 67cb25
          res_ext = reseps;
Packit 67cb25
Packit 67cb25
          if (err_ext + 10 * correc <= epsabs)
Packit 67cb25
            break;
Packit 67cb25
          if (err_ext <= epsabs && 10 * correc >= epsabs)
Packit 67cb25
            break;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (iteration == limit)
Packit 67cb25
    error_type = 1;
Packit 67cb25
Packit 67cb25
  if (err_ext == GSL_DBL_MAX)
Packit 67cb25
    goto compute_result;
Packit 67cb25
Packit 67cb25
  err_ext = err_ext + 10 * correc;
Packit 67cb25
Packit 67cb25
  *result = res_ext;
Packit 67cb25
  *abserr = err_ext;
Packit 67cb25
Packit 67cb25
  if (error_type == 0)
Packit 67cb25
    {
Packit 67cb25
      return GSL_SUCCESS ;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (res_ext != 0.0 && area != 0.0)
Packit 67cb25
    {
Packit 67cb25
      if (err_ext / fabs (res_ext) > errsum / fabs (area))
Packit 67cb25
        goto compute_result;
Packit 67cb25
    }
Packit 67cb25
  else if (err_ext > errsum)
Packit 67cb25
    {
Packit 67cb25
      goto compute_result;
Packit 67cb25
    }
Packit 67cb25
  else if (area == 0.0)
Packit 67cb25
    {
Packit 67cb25
      goto return_error;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  if (error_type == 4)
Packit 67cb25
    {
Packit 67cb25
      err_ext = err_ext + truncation_error;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  goto return_error;
Packit 67cb25
Packit 67cb25
compute_result:
Packit 67cb25
Packit 67cb25
  *result = area;
Packit 67cb25
  *abserr = total_error;
Packit 67cb25
Packit 67cb25
return_error:
Packit 67cb25
Packit 67cb25
  if (error_type > 2)
Packit 67cb25
    error_type--;
Packit 67cb25
Packit 67cb25
  if (error_type == 0)
Packit 67cb25
    {
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  else if (error_type == 1)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("number of iterations was insufficient", GSL_EMAXITER);
Packit 67cb25
    }
Packit 67cb25
  else if (error_type == 2)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("cannot reach tolerance because of roundoff error",
Packit 67cb25
                 GSL_EROUND);
Packit 67cb25
    }
Packit 67cb25
  else if (error_type == 3)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("bad integrand behavior found in the integration interval",
Packit 67cb25
                 GSL_ESING);
Packit 67cb25
    }
Packit 67cb25
  else if (error_type == 4)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("roundoff error detected in the extrapolation table",
Packit 67cb25
                 GSL_EROUND);
Packit 67cb25
    }
Packit 67cb25
  else if (error_type == 5)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("integral is divergent, or slowly convergent",
Packit 67cb25
                 GSL_EDIVERGE);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("could not integrate function", GSL_EFAILED);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
}
Packit 67cb25