/* 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 ;
}

