Blame specfunc/mathieu_angfunc.c

Packit 67cb25
/* specfunc/mathieu_angfunc.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2002 Lowell Johnson
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
/* Author:  L. Johnson */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <stdlib.h>
Packit 67cb25
#include <stdio.h>
Packit 67cb25
#include <math.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_sf_mathieu.h>
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_mathieu_ce_e(int order, double qq, double zz, gsl_sf_result *result)
Packit 67cb25
{
Packit 67cb25
  int even_odd, ii, status;
Packit 67cb25
  double coeff[GSL_SF_MATHIEU_COEFF], norm, fn, factor;
Packit 67cb25
  gsl_sf_result aa;
Packit 67cb25
Packit 67cb25
Packit 67cb25
  norm = 0.0;
Packit 67cb25
  even_odd = 0;
Packit 67cb25
  if (order % 2 != 0)
Packit 67cb25
      even_odd = 1;
Packit 67cb25
  
Packit 67cb25
  /* Handle the trivial case where q = 0. */
Packit 67cb25
  if (qq == 0.0)
Packit 67cb25
  {
Packit 67cb25
      norm = 1.0;
Packit 67cb25
      if (order == 0)
Packit 67cb25
          norm = sqrt(2.0);
Packit 67cb25
Packit 67cb25
      fn = cos(order*zz)/norm;
Packit 67cb25
      
Packit 67cb25
      result->val = fn;
Packit 67cb25
      result->err = 2.0*GSL_DBL_EPSILON;
Packit 67cb25
      factor = fabs(fn);
Packit 67cb25
      if (factor > 1.0)
Packit 67cb25
          result->err *= factor;
Packit 67cb25
      
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  /* Use symmetry characteristics of the functions to handle cases with
Packit 67cb25
     negative order. */
Packit 67cb25
  if (order < 0)
Packit 67cb25
      order *= -1;
Packit 67cb25
Packit 67cb25
  /* Compute the characteristic value. */
Packit 67cb25
  status = gsl_sf_mathieu_a_e(order, qq, &aa);
Packit 67cb25
  if (status != GSL_SUCCESS)
Packit 67cb25
  {
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  /* Compute the series coefficients. */
Packit 67cb25
  status = gsl_sf_mathieu_a_coeff(order, qq, aa.val, coeff);
Packit 67cb25
  if (status != GSL_SUCCESS)
Packit 67cb25
  {
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  if (even_odd == 0)
Packit 67cb25
  {
Packit 67cb25
      fn = 0.0;
Packit 67cb25
      norm = coeff[0]*coeff[0];
Packit 67cb25
      for (ii=0; ii
Packit 67cb25
      {
Packit 67cb25
          fn += coeff[ii]*cos(2.0*ii*zz);
Packit 67cb25
          norm += coeff[ii]*coeff[ii];
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
  else
Packit 67cb25
  {
Packit 67cb25
      fn = 0.0;
Packit 67cb25
      for (ii=0; ii
Packit 67cb25
      {
Packit 67cb25
          fn += coeff[ii]*cos((2.0*ii + 1.0)*zz);
Packit 67cb25
          norm += coeff[ii]*coeff[ii];
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  norm = sqrt(norm);
Packit 67cb25
  fn /= norm;
Packit 67cb25
Packit 67cb25
  result->val = fn;
Packit 67cb25
  result->err = 2.0*GSL_DBL_EPSILON;
Packit 67cb25
  factor = fabs(fn);
Packit 67cb25
  if (factor > 1.0)
Packit 67cb25
      result->err *= factor;
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_mathieu_se_e(int order, double qq, double zz, gsl_sf_result *result)
Packit 67cb25
{
Packit 67cb25
  int even_odd, ii, status;
Packit 67cb25
  double coeff[GSL_SF_MATHIEU_COEFF], norm, fn, factor;
Packit 67cb25
  gsl_sf_result aa;
Packit 67cb25
Packit 67cb25
Packit 67cb25
  norm = 0.0;
Packit 67cb25
  even_odd = 0;
Packit 67cb25
  if (order % 2 != 0)
Packit 67cb25
      even_odd = 1;
Packit 67cb25
  
Packit 67cb25
  /* Handle the trivial cases where order = 0 and/or q = 0. */
Packit 67cb25
  if (order == 0)
Packit 67cb25
  {
Packit 67cb25
      result->val = 0.0;
Packit 67cb25
      result->err = 0.0;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  if (qq == 0.0)
Packit 67cb25
  {
Packit 67cb25
      norm = 1.0;
Packit 67cb25
      fn = sin(order*zz);
Packit 67cb25
      
Packit 67cb25
      result->val = fn;
Packit 67cb25
      result->err = 2.0*GSL_DBL_EPSILON;
Packit 67cb25
      factor = fabs(fn);
Packit 67cb25
      if (factor > 1.0)
Packit 67cb25
          result->err *= factor;
Packit 67cb25
      
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  /* Use symmetry characteristics of the functions to handle cases with
Packit 67cb25
     negative order. */
Packit 67cb25
  if (order < 0)
Packit 67cb25
      order *= -1;
Packit 67cb25
Packit 67cb25
  /* Compute the characteristic value. */
Packit 67cb25
  status = gsl_sf_mathieu_b_e(order, qq, &aa);
Packit 67cb25
  if (status != GSL_SUCCESS)
Packit 67cb25
  {
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  /* Compute the series coefficients. */
Packit 67cb25
  status = gsl_sf_mathieu_b_coeff(order, qq, aa.val, coeff);
Packit 67cb25
  if (status != GSL_SUCCESS)
Packit 67cb25
  {
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  if (even_odd == 0)
Packit 67cb25
  {
Packit 67cb25
      fn = 0.0;
Packit 67cb25
      for (ii=0; ii
Packit 67cb25
      {
Packit 67cb25
          norm += coeff[ii]*coeff[ii];
Packit 67cb25
          fn += coeff[ii]*sin(2.0*(ii + 1)*zz);
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
  else
Packit 67cb25
  {
Packit 67cb25
      fn = 0.0;
Packit 67cb25
      for (ii=0; ii
Packit 67cb25
      {
Packit 67cb25
          norm += coeff[ii]*coeff[ii];
Packit 67cb25
          fn += coeff[ii]*sin((2.0*ii + 1)*zz);
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
  norm = sqrt(norm);
Packit 67cb25
  fn /= norm;
Packit 67cb25
Packit 67cb25
  result->val = fn;
Packit 67cb25
  result->err = 2.0*GSL_DBL_EPSILON;
Packit 67cb25
  factor = fabs(fn);
Packit 67cb25
  if (factor > 1.0)
Packit 67cb25
      result->err *= factor;
Packit 67cb25
  
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_mathieu_ce_array(int nmin, int nmax, double qq, double zz,
Packit 67cb25
                            gsl_sf_mathieu_workspace *work,
Packit 67cb25
                            double result_array[])
Packit 67cb25
{
Packit 67cb25
  int even_odd, order, ii, jj, status;
Packit 67cb25
  double coeff[GSL_SF_MATHIEU_COEFF], *aa = work->aa, norm;
Packit 67cb25
  
Packit 67cb25
Packit 67cb25
  /* Initialize the result array to zeroes. */
Packit 67cb25
  for (ii=0; ii
Packit 67cb25
      result_array[ii] = 0.0;
Packit 67cb25
  
Packit 67cb25
  /* Ensure that the workspace is large enough to accomodate. */
Packit 67cb25
  if (work->size < (unsigned int)nmax)
Packit 67cb25
  {
Packit 67cb25
      GSL_ERROR("Work space not large enough", GSL_EINVAL);
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  if (nmin < 0 || nmax < nmin)
Packit 67cb25
  {
Packit 67cb25
      GSL_ERROR("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Compute all of the eigenvalues up to nmax. */
Packit 67cb25
  gsl_sf_mathieu_a_array(0, nmax, qq, work, aa);
Packit 67cb25
Packit 67cb25
  for (ii=0, order=nmin; order<=nmax; ii++, order++)
Packit 67cb25
  {
Packit 67cb25
      norm = 0.0;
Packit 67cb25
      even_odd = 0;
Packit 67cb25
      if (order % 2 != 0)
Packit 67cb25
          even_odd = 1;
Packit 67cb25
  
Packit 67cb25
      /* Handle the trivial case where q = 0. */
Packit 67cb25
      if (qq == 0.0)
Packit 67cb25
      {
Packit 67cb25
          norm = 1.0;
Packit 67cb25
          if (order == 0)
Packit 67cb25
              norm = sqrt(2.0);
Packit 67cb25
Packit 67cb25
          result_array[ii] = cos(order*zz)/norm;
Packit 67cb25
Packit 67cb25
          continue;
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      /* Compute the series coefficients. */
Packit 67cb25
      status = gsl_sf_mathieu_a_coeff(order, qq, aa[order], coeff);
Packit 67cb25
      if (status != GSL_SUCCESS)
Packit 67cb25
          return status;
Packit 67cb25
  
Packit 67cb25
      if (even_odd == 0)
Packit 67cb25
      {
Packit 67cb25
          norm = coeff[0]*coeff[0];
Packit 67cb25
          for (jj=0; jj
Packit 67cb25
          {
Packit 67cb25
              result_array[ii] += coeff[jj]*cos(2.0*jj*zz);
Packit 67cb25
              norm += coeff[jj]*coeff[jj];
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
      else
Packit 67cb25
      {
Packit 67cb25
          for (jj=0; jj
Packit 67cb25
          {
Packit 67cb25
              result_array[ii] += coeff[jj]*cos((2.0*jj + 1.0)*zz);
Packit 67cb25
              norm += coeff[jj]*coeff[jj];
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      norm = sqrt(norm);
Packit 67cb25
      result_array[ii] /= norm;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_mathieu_se_array(int nmin, int nmax, double qq, double zz,
Packit 67cb25
                            gsl_sf_mathieu_workspace *work,
Packit 67cb25
                            double result_array[])
Packit 67cb25
{
Packit 67cb25
  int even_odd, order, ii, jj, status;
Packit 67cb25
  double coeff[GSL_SF_MATHIEU_COEFF], *bb = work->bb, norm;
Packit 67cb25
  
Packit 67cb25
Packit 67cb25
  /* Initialize the result array to zeroes. */
Packit 67cb25
  for (ii=0; ii
Packit 67cb25
      result_array[ii] = 0.0;
Packit 67cb25
  
Packit 67cb25
  /* Ensure that the workspace is large enough to accomodate. */
Packit 67cb25
  if (work->size < (unsigned int)nmax)
Packit 67cb25
  {
Packit 67cb25
      GSL_ERROR("Work space not large enough", GSL_EINVAL);
Packit 67cb25
  }
Packit 67cb25
  
Packit 67cb25
  if (nmin < 0 || nmax < nmin)
Packit 67cb25
  {
Packit 67cb25
      GSL_ERROR("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Compute all of the eigenvalues up to nmax. */
Packit 67cb25
  gsl_sf_mathieu_b_array(0, nmax, qq, work, bb);
Packit 67cb25
Packit 67cb25
  for (ii=0, order=nmin; order<=nmax; ii++, order++)
Packit 67cb25
  {
Packit 67cb25
      norm = 0.0;
Packit 67cb25
      even_odd = 0;
Packit 67cb25
      if (order % 2 != 0)
Packit 67cb25
          even_odd = 1;
Packit 67cb25
  
Packit 67cb25
      /* Handle the trivial cases where order = 0 and/or q = 0. */
Packit 67cb25
      if (order == 0)
Packit 67cb25
      {
Packit 67cb25
          norm = 1.0;
Packit 67cb25
          result_array[ii] = 0.0;
Packit 67cb25
          continue;
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      if (qq == 0.0)
Packit 67cb25
      {
Packit 67cb25
          norm = 1.0;
Packit 67cb25
          result_array[ii] = sin(order*zz);
Packit 67cb25
Packit 67cb25
          continue;
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      /* Compute the series coefficients. */
Packit 67cb25
      status = gsl_sf_mathieu_b_coeff(order, qq, bb[order], coeff);
Packit 67cb25
      if (status != GSL_SUCCESS)
Packit 67cb25
      {
Packit 67cb25
          return status;
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      if (even_odd == 0)
Packit 67cb25
      {
Packit 67cb25
          for (jj=0; jj
Packit 67cb25
          {
Packit 67cb25
              result_array[ii] += coeff[jj]*sin(2.0*(jj + 1)*zz);
Packit 67cb25
              norm += coeff[jj]*coeff[jj];
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
      else
Packit 67cb25
      {
Packit 67cb25
          for (jj=0; jj
Packit 67cb25
          {
Packit 67cb25
              result_array[ii] += coeff[jj]*sin((2.0*jj + 1.0)*zz);
Packit 67cb25
              norm += coeff[jj]*coeff[jj];
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
  
Packit 67cb25
      norm = sqrt(norm);
Packit 67cb25
      result_array[ii] /= norm;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
Packit 67cb25
Packit 67cb25
#include "eval.h"                                                           
Packit 67cb25
Packit 67cb25
double gsl_sf_mathieu_ce(int order, double qq, double zz)
Packit 67cb25
{
Packit 67cb25
	EVAL_RESULT(gsl_sf_mathieu_ce_e(order, qq, zz, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double gsl_sf_mathieu_se(int order, double qq, double zz)
Packit 67cb25
{
Packit 67cb25
	EVAL_RESULT(gsl_sf_mathieu_se_e(order, qq, zz, &result));
Packit 67cb25
}