Blame integration/qc25f.c

Packit 67cb25
/* integration/qc25f.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
struct fn_fourier_params
Packit 67cb25
{
Packit 67cb25
  gsl_function *function;
Packit 67cb25
  double omega;
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static double fn_sin (double t, void *params);
Packit 67cb25
static double fn_cos (double t, void *params);
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
qc25f (gsl_function * f, double a, double b, 
Packit 67cb25
       gsl_integration_qawo_table * wf, size_t level,
Packit 67cb25
       double *result, double *abserr, double *resabs, double *resasc);
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
qc25f (gsl_function * f, double a, double b, 
Packit 67cb25
       gsl_integration_qawo_table * wf, size_t level,
Packit 67cb25
       double *result, double *abserr, double *resabs, double *resasc)
Packit 67cb25
{
Packit 67cb25
  const double center = 0.5 * (a + b);
Packit 67cb25
  const double half_length = 0.5 * (b - a);
Packit 67cb25
  const double omega = wf->omega ;
Packit 67cb25
  
Packit 67cb25
  const double par = omega * half_length;
Packit 67cb25
Packit 67cb25
  if (fabs (par) < 2)
Packit 67cb25
    {
Packit 67cb25
      gsl_function weighted_function;
Packit 67cb25
      struct fn_fourier_params fn_params;
Packit 67cb25
Packit 67cb25
      fn_params.function = f;
Packit 67cb25
      fn_params.omega = omega;
Packit 67cb25
Packit 67cb25
      if (wf->sine == GSL_INTEG_SINE) 
Packit 67cb25
        {
Packit 67cb25
          weighted_function.function = &fn_sin;
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          weighted_function.function = &fn_cos;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      weighted_function.params = &fn_params;
Packit 67cb25
Packit 67cb25
      gsl_integration_qk15 (&weighted_function, a, b, result, abserr,
Packit 67cb25
                            resabs, resasc);
Packit 67cb25
      
Packit 67cb25
      return;
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      double *moment;
Packit 67cb25
      double cheb12[13], cheb24[25];
Packit 67cb25
      double result_abs, res12_cos, res12_sin, res24_cos, res24_sin;
Packit 67cb25
      double est_cos, est_sin;
Packit 67cb25
      double c, s;
Packit 67cb25
      size_t i;
Packit 67cb25
Packit 67cb25
      gsl_integration_qcheb (f, a, b, cheb12, cheb24);
Packit 67cb25
Packit 67cb25
      if (level >= wf->n)
Packit 67cb25
        {
Packit 67cb25
          /* table overflow should not happen, check before calling */
Packit 67cb25
          GSL_ERROR_VOID("table overflow in internal function", GSL_ESANITY);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      /* obtain moments from the table */
Packit 67cb25
Packit 67cb25
      moment = wf->chebmo + 25 * level;
Packit 67cb25
Packit 67cb25
      res12_cos = cheb12[12] * moment[12];
Packit 67cb25
      res12_sin = 0 ;
Packit 67cb25
Packit 67cb25
      for (i = 0; i < 6; i++)
Packit 67cb25
        {
Packit 67cb25
          size_t k = 10 - 2 * i;
Packit 67cb25
          res12_cos += cheb12[k] * moment[k];
Packit 67cb25
          res12_sin += cheb12[k + 1] * moment[k + 1];
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      res24_cos = cheb24[24] * moment[24];
Packit 67cb25
      res24_sin = 0 ;
Packit 67cb25
Packit 67cb25
      result_abs = fabs(cheb24[24]) ;
Packit 67cb25
Packit 67cb25
      for (i = 0; i < 12; i++)
Packit 67cb25
        {
Packit 67cb25
          size_t k = 22 - 2 * i;
Packit 67cb25
          res24_cos += cheb24[k] * moment[k];
Packit 67cb25
          res24_sin += cheb24[k + 1] * moment[k + 1];
Packit 67cb25
          result_abs += fabs(cheb24[k]) + fabs(cheb24[k+1]);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      est_cos = fabs(res24_cos - res12_cos);
Packit 67cb25
      est_sin = fabs(res24_sin - res12_sin);
Packit 67cb25
Packit 67cb25
      c = half_length * cos(center * omega);
Packit 67cb25
      s = half_length * sin(center * omega);
Packit 67cb25
Packit 67cb25
      if (wf->sine == GSL_INTEG_SINE)
Packit 67cb25
        {
Packit 67cb25
          *result = c * res24_sin + s * res24_cos;
Packit 67cb25
          *abserr = fabs(c * est_sin) + fabs(s * est_cos);
Packit 67cb25
        }
Packit 67cb25
      else
Packit 67cb25
        {
Packit 67cb25
          *result = c * res24_cos - s * res24_sin;
Packit 67cb25
          *abserr = fabs(c * est_cos) + fabs(s * est_sin);
Packit 67cb25
        }
Packit 67cb25
      
Packit 67cb25
      *resabs = result_abs * half_length;
Packit 67cb25
      *resasc = GSL_DBL_MAX;
Packit 67cb25
Packit 67cb25
      return;
Packit 67cb25
    }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
fn_sin (double x, void *params)
Packit 67cb25
{
Packit 67cb25
  struct fn_fourier_params *p = (struct fn_fourier_params *) params;
Packit 67cb25
  gsl_function *f = p->function;
Packit 67cb25
  double w = p->omega;
Packit 67cb25
  double wx = w * x;
Packit 67cb25
  double sinwx = sin(wx) ;
Packit 67cb25
  return GSL_FN_EVAL (f, x) * sinwx;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
fn_cos (double x, void *params)
Packit 67cb25
{
Packit 67cb25
  struct fn_fourier_params *p = (struct fn_fourier_params *) params;
Packit 67cb25
  gsl_function *f = p->function;
Packit 67cb25
  double w = p->omega;
Packit 67cb25
  double wx = w * x;
Packit 67cb25
  double coswx = cos(wx) ;
Packit 67cb25
  return GSL_FN_EVAL (f, x) * coswx ;
Packit 67cb25
}
Packit 67cb25