Blame specfunc/hermite.c

Packit 67cb25
/* specfunc/hermite.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2011, 2012, 2013, 2014 Konrad Griessinger
Packit 67cb25
 * (konradg(at)gmx.net)
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
/*----------------------------------------------------------------------*
Packit 67cb25
 * "The purpose of computing is insight, not numbers." - R.W. Hamming   *
Packit 67cb25
 * Hermite polynomials, Hermite functions                               *
Packit 67cb25
 * and their respective arbitrary derivatives                           *
Packit 67cb25
 *----------------------------------------------------------------------*/
Packit 67cb25
Packit 67cb25
/* TODO:
Packit 67cb25
 * - array functions for derivatives of Hermite functions
Packit 67cb25
 * - asymptotic approximation for derivatives of Hermite functions
Packit 67cb25
 * - refine existing asymptotic approximations, especially around x=sqrt(2*n+1) or x=sqrt(2*n+1)*sqrt(2), respectively
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_sf_airy.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_sf_pow_int.h>
Packit 67cb25
#include <gsl/gsl_sf_gamma.h>
Packit 67cb25
#include <gsl/gsl_sf_hermite.h>
Packit 67cb25
Packit 67cb25
#include "error.h"
Packit 67cb25
#include "eval.h"
Packit 67cb25
Packit 67cb25
#define pow2(n) (gsl_sf_pow_int(2,n))
Packit 67cb25
Packit 67cb25
/* Evaluates the probabilists' Hermite polynomial of order n at position x using upward recurrence. */
Packit 67cb25
static int 
Packit 67cb25
gsl_sf_hermite_prob_iter_e(const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  result->val = 0.;
Packit 67cb25
  result->err = 0.;
Packit 67cb25
Packit 67cb25
  if(n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    result->val = 1.;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1) {
Packit 67cb25
    result->val = x;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(x == 0.){
Packit 67cb25
    if(GSL_IS_ODD(n)){
Packit 67cb25
      result->val = 0.;
Packit 67cb25
      result->err = 0.;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      if(n < 301){
Packit 67cb25
	/*
Packit 67cb25
	double f;
Packit 67cb25
	int j;
Packit 67cb25
	f = (GSL_IS_ODD(n/2)?-1.:1.);
Packit 67cb25
	for(j=1; j < n; j+=2) {
Packit 67cb25
	  f*=j;
Packit 67cb25
	}
Packit 67cb25
	result->val = f;
Packit 67cb25
	result->err = 0.;
Packit 67cb25
	*/
Packit 67cb25
	if(n < 297){
Packit 67cb25
	  gsl_sf_doublefact_e(n-1, result);
Packit 67cb25
	  (GSL_IS_ODD(n/2)?result->val = -result->val:1.);
Packit 67cb25
	}
Packit 67cb25
	else if (n == 298){
Packit 67cb25
	  result->val = (GSL_IS_ODD(n/2)?-1.:1.)*1.25527562259930633890922678431e304;
Packit 67cb25
	  result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
	}
Packit 67cb25
	else{
Packit 67cb25
	  result->val = (GSL_IS_ODD(n/2)?-1.:1.)*3.7532741115719259533385880851e306;
Packit 67cb25
	  result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
	}
Packit 67cb25
      }
Packit 67cb25
      else{
Packit 67cb25
	result->val = (GSL_IS_ODD(n/2)?GSL_NEGINF:GSL_POSINF);
Packit 67cb25
	result->err = GSL_POSINF;
Packit 67cb25
      }
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
/*
Packit 67cb25
  else if(x*x < 4.0*n && n > 100000) {
Packit 67cb25
    // asymptotic formula
Packit 67cb25
    double f = 1.0;
Packit 67cb25
    int j;
Packit 67cb25
    if(GSL_IS_ODD(n)) {
Packit 67cb25
      f=gsl_sf_fact((n-1)/2)*gsl_sf_pow_int(2,n/2)*M_SQRT2/M_SQRTPI;
Packit 67cb25
    }
Packit 67cb25
    else {
Packit 67cb25
      for(j=1; j < n; j+=2) {
Packit 67cb25
	f*=j;
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
    return f*exp(x*x/4)*cos(x*sqrt(n)-(n%4)*M_PI_2)/sqrt(sqrt(1-x*x/4.0/n));
Packit 67cb25
    // return f*exp(x*x/4)*cos(x*sqrt(n)-n*M_PI_2)/sqrt(sqrt(1-x*x/4.0/n));
Packit 67cb25
  }
Packit 67cb25
*/
Packit 67cb25
  else{
Packit 67cb25
    /* upward recurrence: He_{n+1} = x He_n - n He_{n-1} */
Packit 67cb25
Packit 67cb25
    double p_n0 = 1.0;  /* He_0(x) */
Packit 67cb25
    double p_n1 = x;    /* He_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
Packit 67cb25
    double e_n0 = GSL_DBL_EPSILON;
Packit 67cb25
    double e_n1 = fabs(x)*GSL_DBL_EPSILON;
Packit 67cb25
    double e_n = e_n1;
Packit 67cb25
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=1; j <= n-1; j++){
Packit 67cb25
      if (gsl_isnan(p_n) == 1){
Packit 67cb25
	break;
Packit 67cb25
      }
Packit 67cb25
      p_n  = x*p_n1-j*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      e_n  = (fabs(x)*e_n1+j*e_n0);
Packit 67cb25
      e_n0 = e_n1;
Packit 67cb25
      e_n1 = e_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 *= 0.5;
Packit 67cb25
	e_n1 *= 0.5;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 *= 2.0;
Packit 67cb25
	e_n1 *= 2.0;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    /*
Packit 67cb25
    // check to see that the correct values are computed, even when overflow strikes in the end; works, thus very large results are accessible by determining mantissa and exponent separately
Packit 67cb25
    double lg2 = 0.30102999566398119521467838;
Packit 67cb25
    double ln10 = 2.3025850929940456840179914546843642076011014886;
Packit 67cb25
    printf("res= %g\n", p_n*pow(10.,((lg2*c)-((long)(lg2*c)))) );
Packit 67cb25
    printf("res= %g * 10^(%ld)\n", p_n*pow(10.,((lg2*c)-((long)(lg2*c))))/pow(10.,((long)(log(fabs(p_n*pow(10.,((lg2*c)-((long)(lg2*c))))))/ln10))), ((long)(log(fabs(p_n*pow(10.,((lg2*c)-((long)(lg2*c))))))/ln10))+((long)(lg2*c)) );
Packit 67cb25
    */
Packit 67cb25
Packit 67cb25
    result->val = pow2(c)*p_n;
Packit 67cb25
    result->err = pow2(c)*e_n + fabs(result->val)*GSL_DBL_EPSILON;
Packit 67cb25
    /* result->err = e_n + n*fabs(p_n)*GSL_DBL_EPSILON;
Packit 67cb25
       no idea, where the factor n came from => removed
Packit 67cb25
     */
Packit 67cb25
Packit 67cb25
    if (gsl_isnan(result->val) != 1){
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      return GSL_ERANGE;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Approximatively evaluates the probabilists' Hermite polynomial of order n at position x.
Packit 67cb25
 * An approximation depending on the x-range (see Szego, Gabor (1939, 1958, 1967), Orthogonal Polynomials, American Mathematical Society) is used. */
Packit 67cb25
static int 
Packit 67cb25
gsl_sf_hermite_prob_appr_e(const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  /* Plancherel-Rotach approximation (note: Szego defines the Airy function differently!) */
Packit 67cb25
  const double aizero1 = -2.3381074104597670384891972524467; /* first zero of the Airy function Ai */
Packit 67cb25
  double z = fabs(x)*M_SQRT1_2;
Packit 67cb25
  double f = 1.;
Packit 67cb25
  int j;
Packit 67cb25
  for(j=1; j <= n; j++) {
Packit 67cb25
    f*=sqrt(j);
Packit 67cb25
  }
Packit 67cb25
  if (z < sqrt(2*n+1.)+aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
    double phi = acos(z/sqrt(2*n+1.));
Packit 67cb25
    result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*pow(2./n,0.25)/sqrt(M_SQRTPI*sin(phi))*sin(M_PI*0.75+(0.5*n+0.25)*(sin(2*phi)-2*phi))*exp(0.5*z*z);
Packit 67cb25
    result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if (z > sqrt(2*n+1.)-aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
    double phi = acosh(z/sqrt(2*n+1.));
Packit 67cb25
    result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*pow(n,-0.25)/M_SQRT2/sqrt(M_SQRT2*M_SQRTPI*sinh(phi))*exp((0.5*n+0.25)*(2*phi-sinh(2*phi)))*exp(0.5*z*z);
Packit 67cb25
    result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else{
Packit 67cb25
    gsl_sf_result Ai;
Packit 67cb25
    gsl_sf_airy_Ai_e((z-sqrt(2*n+1.))*M_SQRT2*pow(n,1/6.),0,&Ai;;
Packit 67cb25
    result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*sqrt(M_SQRTPI*M_SQRT2)*pow(n,-1/12.)*Ai.val*exp(0.5*z*z);
Packit 67cb25
    result->err = f*sqrt(M_SQRTPI*M_SQRT2)*pow(n,-1/12.)*Ai.err*exp(0.5*z*z) + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the probabilists' Hermite polynomial of order n at position x.
Packit 67cb25
 * For small n upward recurrence is employed, while for large n and NaNs from the iteration an approximation depending on the x-range (see Szego, Gabor (1939, 1958, 1967), Orthogonal Polynomials, American Mathematical Society) is used. */
Packit 67cb25
int 
Packit 67cb25
gsl_sf_hermite_prob_e(const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if( (x==0. || n<=100000) && (gsl_sf_hermite_prob_iter_e(n,x,result)==GSL_SUCCESS) ){
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else{
Packit 67cb25
    return gsl_sf_hermite_prob_appr_e(n,x,result);
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double gsl_sf_hermite_prob(const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_prob_e(n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the m-th derivative of the probabilists' Hermite polynomial of order n at position x.
Packit 67cb25
 * The direct formula He^{(m)}_n = n!/(n-m)!*He_{n-m}(x) (where He_j(x) is the j-th probabilists' Hermite polynomial and He^{(m)}_j(x) its m-th derivative) is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_der_e(const int m, const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n < 0 || m < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n < m) {
Packit 67cb25
    result->val = 0.;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else{
Packit 67cb25
    double f = gsl_sf_choose(n,m)*gsl_sf_fact(m);
Packit 67cb25
    gsl_sf_result He;
Packit 67cb25
    gsl_sf_hermite_prob_e(n-m,x,&He;;
Packit 67cb25
    result->val = He.val*f;
Packit 67cb25
    result->err = He.err*f + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_prob_der(const int m, const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_prob_der_e(m, n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the physicists' Hermite polynomial of order n at position x.
Packit 67cb25
 * For small n upward recurrence is employed, while for large n and NaNs from the iteration an approximation depending on the x-range (see Szego, Gabor (1939, 1958, 1967), Orthogonal Polynomials, American Mathematical Society) is used. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_e(const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  result->val = 0.;
Packit 67cb25
  result->err = 0.;
Packit 67cb25
Packit 67cb25
  if(n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    result->val = 1.;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1) {
Packit 67cb25
    result->val = 2.0*x;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(x == 0.){
Packit 67cb25
    if(GSL_IS_ODD(n)){
Packit 67cb25
      result->val = 0.;
Packit 67cb25
      result->err = 0.;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      if(n < 269){
Packit 67cb25
	double f = pow2(n/2);
Packit 67cb25
	gsl_sf_doublefact_e(n-1, result);
Packit 67cb25
	result->val *= f;
Packit 67cb25
	result->err *= f;
Packit 67cb25
	(GSL_IS_ODD(n/2)?result->val = -result->val:1.);
Packit 67cb25
	/*
Packit 67cb25
	double f;
Packit 67cb25
	int j;
Packit 67cb25
	f = (GSL_IS_ODD(n/2)?-1.:1.);
Packit 67cb25
	for(j=1; j < n; j+=2) {
Packit 67cb25
	  f*=2*j;
Packit 67cb25
	}
Packit 67cb25
	result->val = f;
Packit 67cb25
	result->err = 0.;
Packit 67cb25
	*/
Packit 67cb25
      }
Packit 67cb25
      else{
Packit 67cb25
	result->val = (GSL_IS_ODD(n/2)?GSL_NEGINF:GSL_POSINF);
Packit 67cb25
	result->err = GSL_POSINF;
Packit 67cb25
      }
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
  /*
Packit 67cb25
  else if(x*x < 2.0*n && n > 100000) {
Packit 67cb25
    // asymptotic formula
Packit 67cb25
    double f = 1.0;
Packit 67cb25
    int j;
Packit 67cb25
    if(GSL_IS_ODD(n)) {
Packit 67cb25
      f=gsl_sf_fact((n-1)/2)*gsl_sf_pow_int(2,n)/M_SQRTPI;
Packit 67cb25
    }
Packit 67cb25
    else {
Packit 67cb25
      for(j=1; j < n; j+=2) {
Packit 67cb25
	f*=j;
Packit 67cb25
      }
Packit 67cb25
      f*=gsl_sf_pow_int(2,n/2);
Packit 67cb25
    }
Packit 67cb25
    return f*exp(x*x/2)*cos(x*sqrt(2.0*n)-(n%4)*M_PI_2)/sqrt(sqrt(1-x*x/2.0/n));
Packit 67cb25
    // return f*exp(x*x/2)*cos(x*sqrt(2.0*n)-n*M_PI_2)/sqrt(sqrt(1-x*x/2.0/n));
Packit 67cb25
  }
Packit 67cb25
  */
Packit 67cb25
  else if (n <= 100000){
Packit 67cb25
    /* upward recurrence: H_{n+1} = 2x H_n - 2j H_{n-1} */
Packit 67cb25
Packit 67cb25
    double p_n0 = 1.0;    /* H_0(x) */
Packit 67cb25
    double p_n1 = 2.0*x;  /* H_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
Packit 67cb25
    double e_n0 = GSL_DBL_EPSILON;
Packit 67cb25
    double e_n1 = 2.*fabs(x)*GSL_DBL_EPSILON;
Packit 67cb25
    double e_n = e_n1;
Packit 67cb25
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=1; j <= n-1; j++){
Packit 67cb25
      if (gsl_isnan(p_n) == 1){
Packit 67cb25
	break;
Packit 67cb25
      }
Packit 67cb25
      p_n  = 2.0*x*p_n1-2.0*j*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      e_n  = 2.*(fabs(x)*e_n1+j*e_n0);
Packit 67cb25
      e_n0 = e_n1;
Packit 67cb25
      e_n1 = e_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 *= 0.5;
Packit 67cb25
	e_n1 *= 0.5;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 *= 2.0;
Packit 67cb25
	e_n1 *= 2.0;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result->val = pow2(c)*p_n;
Packit 67cb25
    result->err = pow2(c)*e_n + fabs(result->val)*GSL_DBL_EPSILON;
Packit 67cb25
    /* result->err = e_n + n*fabs(p_n)*GSL_DBL_EPSILON;
Packit 67cb25
       no idea, where the factor n came from => removed */
Packit 67cb25
    if (gsl_isnan(result->val) != 1){
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* the following condition is implied by the logic above */
Packit 67cb25
  {
Packit 67cb25
    /* Plancherel-Rotach approximation (note: Szego defines the Airy function differently!) */
Packit 67cb25
    const double aizero1 = -2.3381074104597670384891972524467; /* first zero of the Airy function Ai */
Packit 67cb25
    double z = fabs(x);
Packit 67cb25
    double f = 1.;
Packit 67cb25
    int j;
Packit 67cb25
    for(j=1; j <= n; j++) {
Packit 67cb25
      f*=sqrt(j);
Packit 67cb25
    }
Packit 67cb25
    if (z < sqrt(2*n+1.)+aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
      double phi = acos(z/sqrt(2*n+1.));
Packit 67cb25
      result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*(GSL_IS_ODD(n)?M_SQRT2:1.)*pow2(n/2)*pow(2./n,0.25)/sqrt(M_SQRTPI*sin(phi))*sin(M_PI*0.75+(0.5*n+0.25)*(sin(2*phi)-2*phi))*exp(0.5*z*z);
Packit 67cb25
      result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else if (z > sqrt(2*n+1.)-aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
      double phi = acosh(z/sqrt(2*n+1.));
Packit 67cb25
      result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*(GSL_IS_ODD(n)?1.:M_SQRT1_2)*pow2(n/2)*pow(n,-0.25)/sqrt(M_SQRT2*M_SQRTPI*sinh(phi))*exp((0.5*n+0.25)*(2*phi-sinh(2*phi)))*exp(0.5*z*z);
Packit 67cb25
      result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      gsl_sf_result Ai;
Packit 67cb25
      gsl_sf_airy_Ai_e((z-sqrt(2*n+1.))*M_SQRT2*pow(n,1/6.),0,&Ai;;
Packit 67cb25
      result->val = f*(GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*(GSL_IS_ODD(n)?M_SQRT2:1.)*sqrt(M_SQRTPI*M_SQRT2)*pow2(n/2)*pow(n,-1/12.)*Ai.val*exp(0.5*z*z);
Packit 67cb25
      result->err = f*(GSL_IS_ODD(n)?M_SQRT2:1.)*pow2(n/2)*sqrt(M_SQRTPI*M_SQRT2)*pow(n,-1/12.)*Ai.err*exp(0.5*z*z) + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_phys(const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_phys_e(n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the m-th derivative of the physicists' Hermite polynomial of order n at position x.
Packit 67cb25
 * The direct formula H^{(m)}_n = 2**m*n!/(n-m)!*H_{n-m}(x) (where H_j(x) is the j-th physicists' Hermite polynomial and H^{(m)}_j(x) its m-th derivative) is employed. */
Packit 67cb25
int 
Packit 67cb25
gsl_sf_hermite_phys_der_e(const int m, const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n < 0 || m < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n < m) {
Packit 67cb25
    result->val = 0.;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else{
Packit 67cb25
    double f = gsl_sf_choose(n,m)*gsl_sf_fact(m)*pow2(m);
Packit 67cb25
    gsl_sf_result H;
Packit 67cb25
    gsl_sf_hermite_phys_e(n-m,x,&H);
Packit 67cb25
    result->val = H.val*f;
Packit 67cb25
    result->err = H.err*f + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_phys_der(const int m, const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_phys_der_e(m, n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the Hermite function of order n at position x.
Packit 67cb25
 * For large n an approximation depending on the x-range (see Szego, Gabor (1939, 1958, 1967), Orthogonal Polynomials, American Mathematical Society) is used, while for small n the direct formula via the probabilists' Hermite polynomial is applied. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_func_e(const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  /*
Packit 67cb25
  if (x*x < 2.0*n && n > 100000){
Packit 67cb25
    // asymptotic formula
Packit 67cb25
    double f = 1.0;
Packit 67cb25
    int j;
Packit 67cb25
    // return f*exp(x*x/4)*cos(x*sqrt(n)-n*M_PI_2)/sqrt(sqrt(1-x*x/4.0/n));
Packit 67cb25
    return cos(x*sqrt(2.0*n)-(n%4)*M_PI_2)/sqrt(sqrt(0.5*n/M_PI*(1-0.5*x*x/n)))/M_PI;
Packit 67cb25
  }
Packit 67cb25
  */
Packit 67cb25
  if (n < 0){
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0 && x != 0.) {
Packit 67cb25
    result->val = exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1 && x != 0.) {
Packit 67cb25
    result->val = M_SQRT2*x*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if (x == 0.){
Packit 67cb25
    if (GSL_IS_ODD(n)){
Packit 67cb25
      result->val = 0.;
Packit 67cb25
      result->err = 0.;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      double f;
Packit 67cb25
      int j;
Packit 67cb25
      f = (GSL_IS_ODD(n/2)?-1.:1.);
Packit 67cb25
      for(j=1; j < n; j+=2) {
Packit 67cb25
	f*=sqrt(j/(j+1.));
Packit 67cb25
      }
Packit 67cb25
      result->val = f/sqrt(M_SQRTPI);
Packit 67cb25
      result->err = GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
  else if (n <= 100000){
Packit 67cb25
    double f = exp(-0.5*x*x)/sqrt(M_SQRTPI*gsl_sf_fact(n));
Packit 67cb25
    gsl_sf_result He;
Packit 67cb25
    gsl_sf_hermite_prob_iter_e(n,M_SQRT2*x,&He;;
Packit 67cb25
    result->val = He.val*f;
Packit 67cb25
    result->err = He.err*f + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    if (gsl_isnan(result->val) != 1 && f > GSL_DBL_MIN && gsl_finite(He.val) == 1){
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* upward recurrence: Psi_{n+1} = sqrt(2/(n+1))*x Psi_n - sqrt(n/(n+1)) Psi_{n-1} */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    double tw = exp(-x*x*0.5/n); /* "twiddle factor" (in the spirit of FFT) */
Packit 67cb25
    double p_n0 = tw/sqrt(M_SQRTPI); /* Psi_0(x) */
Packit 67cb25
    double p_n1 = p_n0*M_SQRT2*x;    /* Psi_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    double e_n0 = p_n0*GSL_DBL_EPSILON;
Packit 67cb25
    double e_n1 = p_n1*GSL_DBL_EPSILON;
Packit 67cb25
    double e_n = e_n1;
Packit 67cb25
  
Packit 67cb25
    int j;
Packit 67cb25
Packit 67cb25
    int c = 0;
Packit 67cb25
    for (j=1;j
Packit 67cb25
      {
Packit 67cb25
        if (gsl_isnan(p_n) == 1){
Packit 67cb25
	  break;
Packit 67cb25
        }
Packit 67cb25
        p_n=tw*(M_SQRT2*x*p_n1-sqrt(j)*p_n0)/sqrt(j+1.);
Packit 67cb25
        p_n0=tw*p_n1;
Packit 67cb25
        p_n1=p_n;
Packit 67cb25
Packit 67cb25
        e_n=tw*(M_SQRT2*fabs(x)*e_n1+sqrt(j)*e_n0)/sqrt(j+1.);
Packit 67cb25
        e_n0=tw*e_n1;
Packit 67cb25
        e_n1=e_n;
Packit 67cb25
Packit 67cb25
        while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
  	p_n0 *= 0.5;
Packit 67cb25
  	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 *= 0.5;
Packit 67cb25
	e_n1 *= 0.5;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
	while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 = p_n0*2;
Packit 67cb25
	p_n1 = p_n1*2;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	e_n0 = e_n0*2;
Packit 67cb25
	e_n1 = e_n1*2;
Packit 67cb25
	e_n = e_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  result->val = p_n*pow2(c);
Packit 67cb25
  result->err = n*fabs(result->val)*GSL_DBL_EPSILON;
Packit 67cb25
Packit 67cb25
  if (gsl_isnan(result->val) != 1){
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    /* Plancherel-Rotach approximation (note: Szego defines the Airy function differently!) */
Packit 67cb25
    const double aizero1 = -2.3381074104597670384891972524467; /* first zero of the Airy function Ai */
Packit 67cb25
    double z = fabs(x);
Packit 67cb25
    if (z < sqrt(2*n+1.)+aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
      double phi = acos(z/sqrt(2*n+1.));
Packit 67cb25
      result->val = (GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*pow(2./n,0.25)/M_SQRTPI/sqrt(sin(phi))*sin(M_PI*0.75+(0.5*n+0.25)*(sin(2*phi)-2*phi));
Packit 67cb25
      result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else if (z > sqrt(2*n+1.)-aizero1/M_SQRT2/pow(n,1/6.)){
Packit 67cb25
      double phi = acosh(z/sqrt(2*n+1.));
Packit 67cb25
      result->val = (GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*pow(n,-0.25)/
Packit 67cb25
2/M_SQRTPI/sqrt(sinh(phi)/M_SQRT2)*exp((0.5*n+0.25)*(2*phi-sinh(2*phi)));
Packit 67cb25
      result->err = 2. * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else{
Packit 67cb25
      gsl_sf_result Ai;
Packit 67cb25
      gsl_sf_airy_Ai_e((z-sqrt(2*n+1.))*M_SQRT2*pow(n,1/6.),0,&Ai;;
Packit 67cb25
      result->val = (GSL_IS_ODD(n)&&(x<0.)?-1.:1.)*sqrt(M_SQRT2)*pow(n,-1/12.)*Ai.val;
Packit 67cb25
      result->err = sqrt(M_SQRT2)*pow(n,-1/12.)*Ai.err +  GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_func(const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_func_e(n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates all probabilists' Hermite polynomials up to order nmax at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_array(const int nmax, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(nmax < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 0) {
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 1) {
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    result_array[1] = x;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence: He_{n+1} = x He_n - n He_{n-1} */
Packit 67cb25
Packit 67cb25
    double p_n0 = 1.0;    /* He_0(x) */
Packit 67cb25
    double p_n1 = x;      /* He_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    result_array[1] = x;
Packit 67cb25
Packit 67cb25
    for(j=1; j <= nmax-1; j++){
Packit 67cb25
      p_n  = x*p_n1-j*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j+1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates the m-th derivative of all probabilists' Hermite polynomials up to order nmax at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_array_der(const int m, const int nmax, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(nmax < 0 || m < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(m == 0) {
Packit 67cb25
    gsl_sf_hermite_prob_array(nmax, x, result_array);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax < m) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j <= nmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == m) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    result_array[nmax] = gsl_sf_fact(m);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == m+1) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    result_array[nmax-1] = gsl_sf_fact(m);
Packit 67cb25
    result_array[nmax] = result_array[nmax-1]*(m+1)*x;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence: He^{(m)}_{n+1} = (n+1)/(n-m+1)*(x He^{(m)}_n - n He^{(m)}_{n-1}) */
Packit 67cb25
Packit 67cb25
    double p_n0 = gsl_sf_fact(m);    /* He^{(m)}_{m}(x) */
Packit 67cb25
    double p_n1 = p_n0*(m+1)*x;      /* He^{(m)}_{m+1}(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result_array[m] = p_n0;
Packit 67cb25
    result_array[m+1] = p_n1;
Packit 67cb25
Packit 67cb25
    for(j=m+1; j <= nmax-1; j++){
Packit 67cb25
      p_n  = (x*p_n1-j*p_n0)*(j+1)/(j-m+1);
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j+1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates all derivatives (starting from 0) up to the mmax-th derivative of the probabilists' Hermite polynomial of order n at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_der_array(const int mmax, const int n, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(n < 0 || mmax < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    int j;
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    for(j=1; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1 && mmax > 0) {
Packit 67cb25
    int j;
Packit 67cb25
    result_array[0] = x;
Packit 67cb25
    result_array[1] = 1.0;
Packit 67cb25
    for(j=2; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if( mmax == 0) {
Packit 67cb25
    result_array[0] = gsl_sf_hermite_prob(n,x);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if( mmax == 1) {
Packit 67cb25
    result_array[0] = gsl_sf_hermite_prob(n,x);
Packit 67cb25
    result_array[1] = n*gsl_sf_hermite_prob(n-1,x);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence */
Packit 67cb25
Packit 67cb25
    int k = GSL_MAX_INT(0,n-mmax);
Packit 67cb25
    /* Getting a bit lazy here... */
Packit 67cb25
    double p_n0 = gsl_sf_hermite_prob(k,x);        /* He_k(x) */
Packit 67cb25
    double p_n1 = gsl_sf_hermite_prob(k+1,x);      /* He_{k+1}(x) */
Packit 67cb25
    double p_n  = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=n+1; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result_array[GSL_MIN_INT(n,mmax)] = p_n0;
Packit 67cb25
    result_array[GSL_MIN_INT(n,mmax)-1] = p_n1;
Packit 67cb25
Packit 67cb25
    for(j=GSL_MIN_INT(mmax,n)-1; j > 0; j--){
Packit 67cb25
      k++;
Packit 67cb25
      p_n  = x*p_n1-k*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j-1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    p_n = 1.0;
Packit 67cb25
    for(j=1; j <= GSL_MIN_INT(n,mmax); j++){
Packit 67cb25
      p_n  = p_n*(n-j+1);
Packit 67cb25
      result_array[j] = p_n*result_array[j];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the series sum_{j=0}^n a_j*He_j(x) with He_j being the j-th probabilists' Hermite polynomial.
Packit 67cb25
 * For improved numerical stability the Clenshaw algorithm (Clenshaw, C. W. (July 1955). "A note on the summation of Chebyshev series". Mathematical Tables and other Aids to Computation 9 (51): 118–110.) adapted to probabilists' Hermite polynomials is used. */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_series_e(const int n, const double x, const double * a, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    result->val = a[0];
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1) {
Packit 67cb25
    result->val = a[0]+a[1]*x;
Packit 67cb25
    result->err = 2.*GSL_DBL_EPSILON * (fabs(a[0]) + fabs(a[1]*x)) ;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* downward recurrence: b_n = a_n + x b_{n+1} - (n+1) b_{n+2} */
Packit 67cb25
Packit 67cb25
    double b0 = 0.;
Packit 67cb25
    double b1 = 0.;
Packit 67cb25
    double btmp = 0.;
Packit 67cb25
Packit 67cb25
    double e0 = 0.;
Packit 67cb25
    double e1 = 0.;
Packit 67cb25
    double etmp = e1;
Packit 67cb25
Packit 67cb25
    int j;
Packit 67cb25
Packit 67cb25
    for(j=n; j >= 0; j--){
Packit 67cb25
      btmp = b0;
Packit 67cb25
      b0  = a[j]+x*b0-(j+1)*b1;
Packit 67cb25
      b1 = btmp;
Packit 67cb25
Packit 67cb25
      etmp = e0;
Packit 67cb25
      e0  = (GSL_DBL_EPSILON*fabs(a[j])+fabs(x)*e0+(j+1)*e1);
Packit 67cb25
      e1 = etmp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result->val = b0;
Packit 67cb25
    result->err = e0 + fabs(b0)*GSL_DBL_EPSILON;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_prob_series(const int n, const double x, const double * a)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_prob_series_e(n, x, a, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates all physicists' Hermite polynomials up to order nmax at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_array(const int nmax, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(nmax < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 0) {
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 1) {
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    result_array[1] = 2.0*x;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence: H_{n+1} = 2x H_n - 2n H_{n-1} */
Packit 67cb25
Packit 67cb25
    double p_n0 = 1.0;      /* H_0(x) */
Packit 67cb25
    double p_n1 = 2.0*x;    /* H_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    result_array[1] = 2.0*x;
Packit 67cb25
Packit 67cb25
    for(j=1; j <= nmax-1; j++){
Packit 67cb25
      p_n  = 2.0*x*p_n1-2.0*j*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j+1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates the m-th derivative of all physicists' Hermite polynomials up to order nmax at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_array_der(const int m, const int nmax, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(nmax < 0 || m < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(m == 0) {
Packit 67cb25
    gsl_sf_hermite_phys_array(nmax, x, result_array);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax < m) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j <= nmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == m) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    result_array[nmax] = pow2(m)*gsl_sf_fact(m);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == m+1) {
Packit 67cb25
    int j;
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    result_array[nmax-1] = pow2(m)*gsl_sf_fact(m);
Packit 67cb25
    result_array[nmax] = result_array[nmax-1]*2*(m+1)*x;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence: H^{(m)}_{n+1} = 2(n+1)/(n-m+1)*(x H^{(m)}_n - n H^{(m)}_{n-1}) */
Packit 67cb25
Packit 67cb25
    double p_n0 = pow2(m)*gsl_sf_fact(m);    /* H^{(m)}_{m}(x) */
Packit 67cb25
    double p_n1 = p_n0*2*(m+1)*x;    /* H^{(m)}_{m+1}(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=0; j < m; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result_array[m] = p_n0;
Packit 67cb25
    result_array[m+1] = p_n1;
Packit 67cb25
Packit 67cb25
    for(j=m+1; j <= nmax-1; j++){
Packit 67cb25
      p_n  = (x*p_n1-j*p_n0)*2*(j+1)/(j-m+1);
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j+1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates all derivatives (starting from 0) up to the mmax-th derivative of the physicists' Hermite polynomial of order n at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_der_array(const int mmax, const int n, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(n < 0 || mmax < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    int j;
Packit 67cb25
    result_array[0] = 1.0;
Packit 67cb25
    for(j=1; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1 && mmax > 0) {
Packit 67cb25
    int j;
Packit 67cb25
    result_array[0] = 2*x;
Packit 67cb25
    result_array[1] = 1.0;
Packit 67cb25
    for(j=2; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if( mmax == 0) {
Packit 67cb25
    result_array[0] = gsl_sf_hermite_phys(n,x);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if( mmax == 1) {
Packit 67cb25
    result_array[0] = gsl_sf_hermite_phys(n,x);
Packit 67cb25
    result_array[1] = 2*n*gsl_sf_hermite_phys(n-1,x);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence */
Packit 67cb25
Packit 67cb25
    int k = GSL_MAX_INT(0,n-mmax);
Packit 67cb25
    /* Getting a bit lazy here... */
Packit 67cb25
    double p_n0 = gsl_sf_hermite_phys(k,x);        /* H_k(x) */
Packit 67cb25
    double p_n1 = gsl_sf_hermite_phys(k+1,x);      /* H_{k+1}(x) */
Packit 67cb25
    double p_n  = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    for(j=n+1; j <= mmax; j++){
Packit 67cb25
      result_array[j] = 0.0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result_array[GSL_MIN_INT(n,mmax)] = p_n0;
Packit 67cb25
    result_array[GSL_MIN_INT(n,mmax)-1] = p_n1;
Packit 67cb25
Packit 67cb25
    for(j=GSL_MIN_INT(mmax,n)-1; j > 0; j--){
Packit 67cb25
      k++;
Packit 67cb25
      p_n  = 2*x*p_n1-2*k*p_n0;
Packit 67cb25
      p_n0 = p_n1;
Packit 67cb25
      p_n1 = p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j-1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    p_n = 1.0;
Packit 67cb25
    for(j=1; j <= GSL_MIN_INT(n,mmax); j++){
Packit 67cb25
      p_n  = p_n*(n-j+1)*2;
Packit 67cb25
      result_array[j] = p_n*result_array[j];
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates the series sum_{j=0}^n a_j*H_j(x) with H_j being the j-th physicists' Hermite polynomial.
Packit 67cb25
 * For improved numerical stability the Clenshaw algorithm (Clenshaw, C. W. (July 1955). "A note on the summation of Chebyshev series". Mathematical Tables and other Aids to Computation 9 (51): 118–110.) adapted to physicists' Hermite polynomials is used. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_series_e(const int n, const double x, const double * a, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    result->val = a[0];
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1) {
Packit 67cb25
    result->val = a[0]+a[1]*2.*x;
Packit 67cb25
    result->err = 2.*GSL_DBL_EPSILON * (fabs(a[0]) + fabs(a[1]*2.*x)) ;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* downward recurrence: b_n = a_n + 2x b_{n+1} - 2(n+1) b_{n+2} */
Packit 67cb25
Packit 67cb25
    double b0 = 0.;
Packit 67cb25
    double b1 = 0.;
Packit 67cb25
    double btmp = 0.;
Packit 67cb25
Packit 67cb25
    double e0 = 0.;
Packit 67cb25
    double e1 = 0.;
Packit 67cb25
    double etmp = e1;
Packit 67cb25
Packit 67cb25
    int j;
Packit 67cb25
Packit 67cb25
    for(j=n; j >= 0; j--){
Packit 67cb25
      btmp = b0;
Packit 67cb25
      b0  = a[j]+2.*x*b0-2.*(j+1)*b1;
Packit 67cb25
      b1 = btmp;
Packit 67cb25
Packit 67cb25
      etmp = e0;
Packit 67cb25
      e0  = (GSL_DBL_EPSILON*fabs(a[j])+fabs(2.*x)*e0+2.*(j+1)*e1);
Packit 67cb25
      e1 = etmp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result->val = b0;
Packit 67cb25
    result->err = e0 + fabs(b0)*GSL_DBL_EPSILON;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_phys_series(const int n, const double x, const double * a)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_phys_series_e(n, x, a, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates all Hermite functions up to order nmax at position x. The results are stored in result_array.
Packit 67cb25
 * Since all polynomial orders are needed, upward recurrence is employed. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_func_array(const int nmax, const double x, double * result_array)
Packit 67cb25
{
Packit 67cb25
  if(nmax < 0) {
Packit 67cb25
    GSL_ERROR ("domain error", GSL_EDOM);
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 0) {
Packit 67cb25
    result_array[0] = exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(nmax == 1) {
Packit 67cb25
    result_array[0] = exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result_array[1] = result_array[0]*M_SQRT2*x;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* upward recurrence: Psi_{n+1} = sqrt(2/(n+1))*x Psi_n - sqrt(n/(n+1)) Psi_{n-1} */
Packit 67cb25
Packit 67cb25
    double p_n0 = exp(-0.5*x*x)/sqrt(M_SQRTPI);   /* Psi_0(x) */
Packit 67cb25
    double p_n1 = p_n0*M_SQRT2*x;                 /* Psi_1(x) */
Packit 67cb25
    double p_n = p_n1;
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
Packit 67cb25
    result_array[0] = p_n0;
Packit 67cb25
    result_array[1] = p_n1;
Packit 67cb25
Packit 67cb25
  for (j=1;j<=nmax-1;j++)
Packit 67cb25
    {
Packit 67cb25
      p_n=(M_SQRT2*x*p_n1-sqrt(j)*p_n0)/sqrt(j+1.);
Packit 67cb25
      p_n0=p_n1;
Packit 67cb25
      p_n1=p_n;
Packit 67cb25
Packit 67cb25
      while(( GSL_MIN(fabs(p_n0),fabs(p_n1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 0.5;
Packit 67cb25
	p_n1 *= 0.5;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c++;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      while(( ( ( fabs(p_n0) < GSL_SQRT_DBL_MIN ) && ( p_n0 != 0) ) || ( ( fabs(p_n1) < GSL_SQRT_DBL_MIN ) && ( p_n1 != 0) ) ) && ( GSL_MAX(fabs(p_n0),fabs(p_n1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	p_n0 *= 2.0;
Packit 67cb25
	p_n1 *= 2.0;
Packit 67cb25
	p_n = p_n1;
Packit 67cb25
	c--;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      result_array[j+1] = pow2(c)*p_n;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* Evaluates the series sum_{j=0}^n a_j*Psi_j(x) with Psi_j being the j-th Hermite function.
Packit 67cb25
 * For improved numerical stability the Clenshaw algorithm (Clenshaw, C. W. (July 1955). "A note on the summation of Chebyshev series". Mathematical Tables and other Aids to Computation 9 (51): 118–110.) adapted to Hermite functions is used. */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_func_series_e(const int n, const double x, const double * a, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(n == 0) {
Packit 67cb25
    result->val = a[0]*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n == 1) {
Packit 67cb25
    result->val = (a[0]+a[1]*M_SQRT2*x)*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = 2.*GSL_DBL_EPSILON*(fabs(a[0])+fabs(a[1]*M_SQRT2*x))*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* downward recurrence: b_n = a_n + sqrt(2/(n+1))*x b_{n+1} - sqrt((n+1)/(n+2)) b_{n+2} */
Packit 67cb25
Packit 67cb25
    double b0 = 0.;
Packit 67cb25
    double b1 = 0.;
Packit 67cb25
    double btmp = 0.;
Packit 67cb25
Packit 67cb25
    double e0 = 0.;
Packit 67cb25
    double e1 = 0.;
Packit 67cb25
    double etmp = e1;
Packit 67cb25
Packit 67cb25
    int j;
Packit 67cb25
Packit 67cb25
    for(j=n; j >= 0; j--){
Packit 67cb25
      btmp = b0;
Packit 67cb25
      b0  = a[j]+sqrt(2./(j+1))*x*b0-sqrt((j+1.)/(j+2.))*b1;
Packit 67cb25
      b1 = btmp;
Packit 67cb25
Packit 67cb25
      etmp = e0;
Packit 67cb25
      e0  = (GSL_DBL_EPSILON*fabs(a[j])+sqrt(2./(j+1))*fabs(x)*e0+sqrt((j+1.)/(j+2.))*e1);
Packit 67cb25
      e1 = etmp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
    result->val = b0*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = e0 + fabs(result->val)*GSL_DBL_EPSILON;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_func_series(const int n, const double x, const double * a)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_func_series_e(n, x, a, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Evaluates the m-th derivative of the Hermite function of order n at position x.
Packit 67cb25
 * A summation including upward recurrences is used. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_func_der_e(const int m, const int n, const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  /* FIXME: asymptotic formula! */
Packit 67cb25
  if(m < 0 || n < 0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(m == 0){
Packit 67cb25
    return gsl_sf_hermite_func_e(n,x,result);
Packit 67cb25
  }
Packit 67cb25
  else{
Packit 67cb25
    int j=0, c=0;
Packit 67cb25
    double r,er,b;
Packit 67cb25
    double h0 = 1.;
Packit 67cb25
    double h1 = x;
Packit 67cb25
    double eh0 = GSL_DBL_EPSILON;
Packit 67cb25
    double eh1 = GSL_DBL_EPSILON;
Packit 67cb25
    double p0 = 1.;
Packit 67cb25
    double p1 = M_SQRT2*x;
Packit 67cb25
    double ep0 = GSL_DBL_EPSILON;
Packit 67cb25
    double ep1 = M_SQRT2*GSL_DBL_EPSILON;
Packit 67cb25
    double f = 1.;
Packit 67cb25
    for (j=GSL_MAX_INT(1,n-m+1);j<=n;j++)
Packit 67cb25
      {
Packit 67cb25
	f *= sqrt(2.*j);
Packit 67cb25
      }
Packit 67cb25
    if (m>n)
Packit 67cb25
      {
Packit 67cb25
	f = (GSL_IS_ODD(m-n)?-f:f);
Packit 67cb25
	for (j=0;j
Packit 67cb25
	  {
Packit 67cb25
	    f *= (m-j)/(j+1.);
Packit 67cb25
	  }
Packit 67cb25
      }
Packit 67cb25
    c = 0;
Packit 67cb25
    for (j=1;j<=m-n;j++)
Packit 67cb25
      {
Packit 67cb25
	b = x*h1-j*h0;
Packit 67cb25
	h0 = h1;
Packit 67cb25
	h1 = b;
Packit 67cb25
	
Packit 67cb25
	b  = (fabs(x)*eh1+j*eh0);
Packit 67cb25
	eh0 = eh1;
Packit 67cb25
	eh1 = b;
Packit 67cb25
Packit 67cb25
	while(( GSL_MIN(fabs(h0),fabs(h1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(h0),fabs(h1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	  h0 *= 0.5;
Packit 67cb25
	  h1 *= 0.5;
Packit 67cb25
	  eh0 *= 0.5;
Packit 67cb25
	  eh1 *= 0.5;
Packit 67cb25
	  c++;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
	while(( ( (fabs(h0) < GSL_SQRT_DBL_MIN) && (h0 != 0) ) || ( (fabs(h1) < GSL_SQRT_DBL_MIN) && (h1 != 0) ) ) && ( GSL_MAX(fabs(h0),fabs(h1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	  h0 *= 2.0;
Packit 67cb25
	  h1 *= 2.0;
Packit 67cb25
	  eh0 *= 2.0;
Packit 67cb25
	  eh1 *= 2.0;
Packit 67cb25
	  c--;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
      }
Packit 67cb25
    h0 *= pow2(c);
Packit 67cb25
    h1 *= pow2(c);
Packit 67cb25
    eh0 *= pow2(c);
Packit 67cb25
    eh1 *= pow2(c);
Packit 67cb25
Packit 67cb25
    b = 0.;
Packit 67cb25
    c = 0;
Packit 67cb25
    for (j=1;j<=n-m;j++)
Packit 67cb25
      {
Packit 67cb25
	b = (M_SQRT2*x*p1-sqrt(j)*p0)/sqrt(j+1.);
Packit 67cb25
	p0 = p1;
Packit 67cb25
	p1 = b;
Packit 67cb25
	
Packit 67cb25
	b  = (M_SQRT2*fabs(x)*ep1+sqrt(j)*ep0)/sqrt(j+1.);
Packit 67cb25
	ep0 = ep1;
Packit 67cb25
	ep1 = b;
Packit 67cb25
Packit 67cb25
	while(( GSL_MIN(fabs(p0),fabs(p1)) > 2.0*GSL_SQRT_DBL_MIN ) && ( GSL_MAX(fabs(p0),fabs(p1)) > GSL_SQRT_DBL_MAX )){
Packit 67cb25
	  p0 *= 0.5;
Packit 67cb25
	  p1 *= 0.5;
Packit 67cb25
	  ep0 *= 0.5;
Packit 67cb25
	  ep1 *= 0.5;
Packit 67cb25
	  c++;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
	while(( ( (fabs(p0) < GSL_SQRT_DBL_MIN) && (p0 != 0) ) || ( (fabs(p1) < GSL_SQRT_DBL_MIN) && (p1 != 0) ) ) && ( GSL_MAX(fabs(p0),fabs(p1)) < 0.5*GSL_SQRT_DBL_MAX )){
Packit 67cb25
	  p0 = p0*2;
Packit 67cb25
	  p1 = p1*2;
Packit 67cb25
	  ep0 = ep0*2;
Packit 67cb25
	  ep1 = ep1*2;
Packit 67cb25
	  c--;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
      }
Packit 67cb25
    p0 *= pow2(c);
Packit 67cb25
    p1 *= pow2(c);
Packit 67cb25
    ep0 *= pow2(c);
Packit 67cb25
    ep1 *= pow2(c);
Packit 67cb25
Packit 67cb25
    c = 0;
Packit 67cb25
    b = 0.;
Packit 67cb25
    r = 0.;
Packit 67cb25
    er = 0.;
Packit 67cb25
    for (j=GSL_MAX_INT(0,m-n);j<=m;j++)
Packit 67cb25
      {
Packit 67cb25
	r += f*h0*p0;
Packit 67cb25
	er += eh0*fabs(f*p0)+ep0*fabs(f*h0)+GSL_DBL_EPSILON*fabs(f*h0*p0);
Packit 67cb25
	
Packit 67cb25
	b = x*h1-(j+1.)*h0;
Packit 67cb25
	h0 = h1;
Packit 67cb25
	h1 = b;
Packit 67cb25
	
Packit 67cb25
	b  = 0.5*(fabs(x)*eh1+(j+1.)*eh0);
Packit 67cb25
	eh0 = eh1;
Packit 67cb25
	eh1 = b;
Packit 67cb25
	
Packit 67cb25
	b = (M_SQRT2*x*p1-sqrt(n-m+j+1.)*p0)/sqrt(n-m+j+2.);
Packit 67cb25
	p0 = p1;
Packit 67cb25
	p1 = b;
Packit 67cb25
	
Packit 67cb25
	b  = 0.5*(M_SQRT2*fabs(x)*ep1+sqrt(n-m+j+1.)*ep0)/sqrt(n-m+j+2.);
Packit 67cb25
	ep0 = ep1;
Packit 67cb25
	ep1 = b;
Packit 67cb25
	
Packit 67cb25
	f *= -(m-j)/(j+1.)/sqrt(n-m+j+1.)*M_SQRT1_2;
Packit 67cb25
Packit 67cb25
	while(( (fabs(h0) > 2.0*GSL_SQRT_DBL_MIN) && (fabs(h1) > 2.0*GSL_SQRT_DBL_MIN) && (fabs(p0) > 2.0*GSL_SQRT_DBL_MIN) && (fabs(p1) > 2.0*GSL_SQRT_DBL_MIN) && (fabs(r) > 4.0*GSL_SQRT_DBL_MIN) ) && ( (fabs(h0) > GSL_SQRT_DBL_MAX) || (fabs(h1) > GSL_SQRT_DBL_MAX) || (fabs(p0) > GSL_SQRT_DBL_MAX) || (fabs(p1) > GSL_SQRT_DBL_MAX) || (fabs(r) > GSL_SQRT_DBL_MAX) )){
Packit 67cb25
	  h0 *= 0.5;
Packit 67cb25
	  h1 *= 0.5;
Packit 67cb25
	  eh0 *= 0.5;
Packit 67cb25
	  eh1 *= 0.5;
Packit 67cb25
	  p0 *= 0.5;
Packit 67cb25
	  p1 *= 0.5;
Packit 67cb25
	  ep0 *= 0.5;
Packit 67cb25
	  ep1 *= 0.5;
Packit 67cb25
	  r *= 0.25;
Packit 67cb25
	  er *= 0.25;
Packit 67cb25
	  c++;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
	while(( ( (fabs(h0) < GSL_SQRT_DBL_MIN) && (h0 != 0) ) || ( (fabs(h1) < GSL_SQRT_DBL_MIN) && (h1 != 0) ) || ( (fabs(p0) < GSL_SQRT_DBL_MIN) && (p0 != 0) ) || ( (fabs(p1) < GSL_SQRT_DBL_MIN) && (p1 != 0) ) || ( (fabs(r) < GSL_SQRT_DBL_MIN) && (r != 0) ) ) && ( (fabs(h0) < 0.5*GSL_SQRT_DBL_MAX) && (fabs(h1) < 0.5*GSL_SQRT_DBL_MAX) && (fabs(p0) < 0.5*GSL_SQRT_DBL_MAX) && (fabs(p1) < 0.5*GSL_SQRT_DBL_MAX) && (fabs(r) < 0.25*GSL_SQRT_DBL_MAX) )){
Packit 67cb25
	  p0 *= 2.0;
Packit 67cb25
	  p1 *= 2.0;
Packit 67cb25
	  ep0 *= 2.0;
Packit 67cb25
	  ep1 *= 2.0;
Packit 67cb25
	  h0 *= 2.0;
Packit 67cb25
	  h1 *= 2.0;
Packit 67cb25
	  eh0 *= 2.0;
Packit 67cb25
	  eh1 *= 2.0;
Packit 67cb25
	  r *= 4.0;
Packit 67cb25
	  er *= 4.0;
Packit 67cb25
	  c--;
Packit 67cb25
	}
Packit 67cb25
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    r *= pow2(2*c);
Packit 67cb25
    er *= pow2(2*c);
Packit 67cb25
    result->val = r*exp(-0.5*x*x)/sqrt(M_SQRTPI);
Packit 67cb25
    result->err = er*fabs(exp(-0.5*x*x)/sqrt(M_SQRTPI)) + GSL_DBL_EPSILON*fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_func_der(const int m, const int n, const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_func_der_e(m, n, x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static double
Packit 67cb25
H_zero_init(const int n, const int k)
Packit 67cb25
{
Packit 67cb25
  double p = 1., x = 1., y = 1.;
Packit 67cb25
  if (k == 1 && n > 50) {
Packit 67cb25
    x = (GSL_IS_ODD(n)?1./sqrt((n-1)/6.):1./sqrt(0.5*n));
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    p = -0.7937005259840997373758528196*gsl_sf_airy_zero_Ai(n/2-k+1);
Packit 67cb25
    x = sqrt(2*n+1.);
Packit 67cb25
    y = pow(2*n+1.,1/6.);
Packit 67cb25
    x = x - p/y - 0.1*p*p/(x*y*y) + (9/280. - p*p*p*11/350.)/(x*x*x) + (p*277/12600. - gsl_sf_pow_int(p,4)*823/63000.)/gsl_sf_pow_int(x,4)/y;
Packit 67cb25
  }
Packit 67cb25
  p = acos(x/sqrt(2*n+1.));
Packit 67cb25
  y = M_PI*(-2*(n/2-k)-1.5)/(n+0.5);
Packit 67cb25
  if(gsl_fcmp(y,sin(2.*p)-2*p,GSL_SQRT_DBL_EPSILON)==0) return x; /* initial approx sufficiently accurate */
Packit 67cb25
  if (y > -GSL_DBL_EPSILON) return sqrt(2*n+1.);
Packit 67cb25
  if (p < GSL_DBL_EPSILON) p = GSL_DBL_EPSILON;
Packit 67cb25
  if (p > M_PI_2) p = M_PI_2;
Packit 67cb25
  if (sin(2.*p)-2*p > y){
Packit 67cb25
    x = GSL_MAX((sin(2.*p)-2*p-y)/4.,GSL_SQRT_DBL_EPSILON);
Packit 67cb25
    do{
Packit 67cb25
      x *= 2.;
Packit 67cb25
      p += x;
Packit 67cb25
    } while (sin(2.*p)-2*p > y);
Packit 67cb25
  }
Packit 67cb25
  do {
Packit 67cb25
    x = p;
Packit 67cb25
    p -= (sin(2.*p)-2.*p-y)/(2.*cos(2.*p)-2.);
Packit 67cb25
    if (p<0.||p>M_PI_2) p = M_PI_2;
Packit 67cb25
  } while (gsl_fcmp(x,p,100*GSL_DBL_EPSILON)!=0);
Packit 67cb25
  return sqrt(2*n+1.)*cos(p);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* lookup table for the positive zeros of the probabilists' Hermite polynomials of order 3 through 20 */
Packit 67cb25
static double He_zero_tab[99] = {
Packit 67cb25
  1.73205080756887729352744634151,
Packit 67cb25
  0.741963784302725857648513596726,
Packit 67cb25
  2.33441421833897723931751226721,
Packit 67cb25
  1.35562617997426586583052129087,
Packit 67cb25
  2.85697001387280565416230426401,
Packit 67cb25
  0.616706590192594152193686099399,
Packit 67cb25
  1.88917587775371067550566789858,
Packit 67cb25
  3.32425743355211895236183546247,
Packit 67cb25
  1.154405394739968127239597758838,
Packit 67cb25
  2.36675941073454128861885646856,
Packit 67cb25
  3.75043971772574225630392202571,
Packit 67cb25
  0.539079811351375108072461918694,
Packit 67cb25
  1.63651904243510799922544657297,
Packit 67cb25
  2.80248586128754169911301080618,
Packit 67cb25
  4.14454718612589433206019783917,
Packit 67cb25
  1.023255663789132524828148225810,
Packit 67cb25
  2.07684797867783010652215614374,
Packit 67cb25
  3.20542900285646994336567590292,
Packit 67cb25
  4.51274586339978266756667884317,
Packit 67cb25
  0.484935707515497653046233483105,
Packit 67cb25
  1.46598909439115818325066466416,
Packit 67cb25
  2.48432584163895458087625118368,
Packit 67cb25
  3.58182348355192692277623675546,
Packit 67cb25
  4.85946282833231215015516494660,
Packit 67cb25
  0.928868997381063940144111999584,
Packit 67cb25
  1.87603502015484584534137013967,
Packit 67cb25
  2.86512316064364499771968407254,
Packit 67cb25
  3.93616660712997692868589612142,
Packit 67cb25
  5.18800122437487094818666404539,
Packit 67cb25
  0.444403001944138945299732445510,
Packit 67cb25
  1.34037519715161672153112945211,
Packit 67cb25
  2.25946445100079912386492979448,
Packit 67cb25
  3.22370982877009747166319001956,
Packit 67cb25
  4.27182584793228172295999293076,
Packit 67cb25
  5.50090170446774760081221630899,
Packit 67cb25
  0.856679493519450033897376121795,
Packit 67cb25
  1.72541837958823916151095838741,
Packit 67cb25
  2.62068997343221478063807762201,
Packit 67cb25
  3.56344438028163409162493844661,
Packit 67cb25
  4.59139844893652062705231872720,
Packit 67cb25
  5.80016725238650030586450565322,
Packit 67cb25
  0.412590457954601838167454145167,
Packit 67cb25
  1.24268895548546417895063983219,
Packit 67cb25
  2.08834474570194417097139675101,
Packit 67cb25
  2.96303657983866750254927123447,
Packit 67cb25
  3.88692457505976938384755016476,
Packit 67cb25
  4.89693639734556468372449782879,
Packit 67cb25
  6.08740954690129132226890147034,
Packit 67cb25
  0.799129068324547999424888414207,
Packit 67cb25
  1.60671006902872973652322479373,
Packit 67cb25
  2.43243682700975804116311571682,
Packit 67cb25
  3.28908242439876638890856229770,
Packit 67cb25
  4.19620771126901565957404160583,
Packit 67cb25
  5.19009359130478119946445431715,
Packit 67cb25
  6.36394788882983831771116094427,
Packit 67cb25
  0.386760604500557347721047189801,
Packit 67cb25
  1.16382910055496477419336819907,
Packit 67cb25
  1.95198034571633346449212362880,
Packit 67cb25
  2.76024504763070161684598142269,
Packit 67cb25
  3.60087362417154828824902745506,
Packit 67cb25
  4.49295530252001124266582263095,
Packit 67cb25
  5.47222570594934308841242925805,
Packit 67cb25
  6.63087819839312848022981922233,
Packit 67cb25
  0.751842600703896170737870774614,
Packit 67cb25
  1.50988330779674075905491513417,
Packit 67cb25
  2.28101944025298889535537879396,
Packit 67cb25
  3.07379717532819355851658337833,
Packit 67cb25
  3.90006571719800990903311840097,
Packit 67cb25
  4.77853158962998382710540812497,
Packit 67cb25
  5.74446007865940618125547815768,
Packit 67cb25
  6.88912243989533223256205432938,
Packit 67cb25
  0.365245755507697595916901619097,
Packit 67cb25
  1.09839551809150122773848360538,
Packit 67cb25
  1.83977992150864548966395498992,
Packit 67cb25
  2.59583368891124032910545091458,
Packit 67cb25
  3.37473653577809099529779309480,
Packit 67cb25
  4.18802023162940370448450911428,
Packit 67cb25
  5.05407268544273984538327527397,
Packit 67cb25
  6.00774591135959752029303858752,
Packit 67cb25
  7.13946484914647887560975631213,
Packit 67cb25
  0.712085044042379940413609979021,
Packit 67cb25
  1.42887667607837287134157901452,
Packit 67cb25
  2.15550276131693514033871248449,
Packit 67cb25
  2.89805127651575312007902775275,
Packit 67cb25
  3.66441654745063847665304033851,
Packit 67cb25
  4.46587262683103133615452574019,
Packit 67cb25
  5.32053637733603803162823765939,
Packit 67cb25
  6.26289115651325170419416064557,
Packit 67cb25
  7.38257902403043186766326977122,
Packit 67cb25
  0.346964157081355927973322447164,
Packit 67cb25
  1.04294534880275103146136681143,
Packit 67cb25
  1.74524732081412671493067861704,
Packit 67cb25
  2.45866361117236775131735057433,
Packit 67cb25
  3.18901481655338941485371744116,
Packit 67cb25
  3.94396735065731626033176813604,
Packit 67cb25
  4.73458133404605534390170946748,
Packit 67cb25
  5.57873880589320115268040332802,
Packit 67cb25
  6.51059015701365448636289263918,
Packit 67cb25
  7.61904854167975829138128156060
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/* Computes the s-th zero the probabilists' Hermite polynomial of order n.
Packit 67cb25
A Newton iteration using a continued fraction representation adapted from [E.T. Whittaker (1914), On the continued fractions which represent the functions of Hermite and other functions defined by differential equations, Proceedings of the Edinburgh Mathematical Society, 32, 65-74] is performed with the initial approximation from [Arpad Elbert and Martin E. Muldoon, Approximations for zeros of Hermite functions, pp. 117-126 in D. Dominici and R. S. Maier, eds, "Special Functions and Orthogonal Polynomials", Contemporary Mathematics, vol 471 (2008)] refined via the bisection method. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_prob_zero_e(const int n, const int s, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n <= 0 || s < 0 || s > n/2) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(s == 0) {
Packit 67cb25
    if (GSL_IS_ODD(n) == 1) {
Packit 67cb25
      result->val = 0.;
Packit 67cb25
      result->err = 0.;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else {
Packit 67cb25
      DOMAIN_ERROR(result);
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
  else if(n == 2) {
Packit 67cb25
    result->val = 1.;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n < 21) {
Packit 67cb25
    result->val = He_zero_tab[(GSL_IS_ODD(n)?n/2:0)+((n/2)*(n/2-1))+s-2];
Packit 67cb25
    result->err = GSL_DBL_EPSILON*(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    double d = 1., x = 1., x0 = 1.;
Packit 67cb25
    int j;
Packit 67cb25
    x = H_zero_init(n,s) * M_SQRT2;
Packit 67cb25
    do {
Packit 67cb25
      x0 = x;
Packit 67cb25
      d = 0.;
Packit 67cb25
      for (j=1; j
Packit 67cb25
      x -= (x-d)/n;
Packit 67cb25
    /* gsl_fcmp can be used since the smallest zero approaches 1/sqrt(n) or 1/sqrt((n-1)/3.) for large n and thus all zeros are non-zero (except for the trivial case handled above) */
Packit 67cb25
    } while (gsl_fcmp(x,x0,10*GSL_DBL_EPSILON)!=0);
Packit 67cb25
    result->val = x;
Packit 67cb25
    result->err = 2*GSL_DBL_EPSILON*x + fabs(x-x0);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_prob_zero(const int n, const int s)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_prob_zero_e(n, s, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* lookup table for the positive zeros of the physicists' Hermite polynomials of order 3 through 20 */
Packit 67cb25
static double H_zero_tab[99] = {
Packit 67cb25
  1.22474487139158904909864203735,
Packit 67cb25
  0.524647623275290317884060253835,
Packit 67cb25
  1.65068012388578455588334111112,
Packit 67cb25
  0.958572464613818507112770593893,
Packit 67cb25
  2.02018287045608563292872408814,
Packit 67cb25
  0.436077411927616508679215948251,
Packit 67cb25
  1.335849074013696949714895282970,
Packit 67cb25
  2.35060497367449222283392198706,
Packit 67cb25
  0.816287882858964663038710959027,
Packit 67cb25
  1.67355162876747144503180139830,
Packit 67cb25
  2.65196135683523349244708200652,
Packit 67cb25
  0.381186990207322116854718885584,
Packit 67cb25
  1.157193712446780194720765779063,
Packit 67cb25
  1.98165675669584292585463063977,
Packit 67cb25
  2.93063742025724401922350270524,
Packit 67cb25
  0.723551018752837573322639864579,
Packit 67cb25
  1.46855328921666793166701573925,
Packit 67cb25
  2.26658058453184311180209693284,
Packit 67cb25
  3.19099320178152760723004779538,
Packit 67cb25
  0.342901327223704608789165025557,
Packit 67cb25
  1.03661082978951365417749191676,
Packit 67cb25
  1.75668364929988177345140122011,
Packit 67cb25
  2.53273167423278979640896079775,
Packit 67cb25
  3.43615911883773760332672549432,
Packit 67cb25
  0.656809566882099765024611575383,
Packit 67cb25
  1.32655708449493285594973473558,
Packit 67cb25
  2.02594801582575533516591283121,
Packit 67cb25
  2.78329009978165177083671870152,
Packit 67cb25
  3.66847084655958251845837146485,
Packit 67cb25
  0.314240376254359111276611634095,
Packit 67cb25
  0.947788391240163743704578131060,
Packit 67cb25
  1.59768263515260479670966277090,
Packit 67cb25
  2.27950708050105990018772856942,
Packit 67cb25
  3.02063702512088977171067937518,
Packit 67cb25
  3.88972489786978191927164274724,
Packit 67cb25
  0.605763879171060113080537108602,
Packit 67cb25
  1.22005503659074842622205526637,
Packit 67cb25
  1.85310765160151214200350644316,
Packit 67cb25
  2.51973568567823788343040913628,
Packit 67cb25
  3.24660897837240998812205115236,
Packit 67cb25
  4.10133759617863964117891508007,
Packit 67cb25
  0.291745510672562078446113075799,
Packit 67cb25
  0.878713787329399416114679311861,
Packit 67cb25
  1.47668273114114087058350654421,
Packit 67cb25
  2.09518325850771681573497272630,
Packit 67cb25
  2.74847072498540256862499852415,
Packit 67cb25
  3.46265693360227055020891736115,
Packit 67cb25
  4.30444857047363181262129810037,
Packit 67cb25
  0.565069583255575748526020337198,
Packit 67cb25
  1.13611558521092066631913490556,
Packit 67cb25
  1.71999257518648893241583152515,
Packit 67cb25
  2.32573248617385774545404479449,
Packit 67cb25
  2.96716692790560324848896036355,
Packit 67cb25
  3.66995037340445253472922383312,
Packit 67cb25
  4.49999070730939155366438053053,
Packit 67cb25
  0.273481046138152452158280401965,
Packit 67cb25
  0.822951449144655892582454496734,
Packit 67cb25
  1.38025853919888079637208966969,
Packit 67cb25
  1.95178799091625397743465541496,
Packit 67cb25
  2.54620215784748136215932870545,
Packit 67cb25
  3.17699916197995602681399455926,
Packit 67cb25
  3.86944790486012269871942409801,
Packit 67cb25
  4.68873893930581836468849864875,
Packit 67cb25
  0.531633001342654731349086553718,
Packit 67cb25
  1.06764872574345055363045773799,
Packit 67cb25
  1.61292431422123133311288254454,
Packit 67cb25
  2.17350282666662081927537907149,
Packit 67cb25
  2.75776291570388873092640349574,
Packit 67cb25
  3.37893209114149408338327069289,
Packit 67cb25
  4.06194667587547430689245559698,
Packit 67cb25
  4.87134519367440308834927655662,
Packit 67cb25
  0.258267750519096759258116098711,
Packit 67cb25
  0.776682919267411661316659462284,
Packit 67cb25
  1.30092085838961736566626555439,
Packit 67cb25
  1.83553160426162889225383944409,
Packit 67cb25
  2.38629908916668600026459301424,
Packit 67cb25
  2.96137750553160684477863254906,
Packit 67cb25
  3.57376906848626607950067599377,
Packit 67cb25
  4.24811787356812646302342016090,
Packit 67cb25
  5.04836400887446676837203757885,
Packit 67cb25
  0.503520163423888209373811765050,
Packit 67cb25
  1.01036838713431135136859873726,
Packit 67cb25
  1.52417061939353303183354859367,
Packit 67cb25
  2.04923170985061937575050838669,
Packit 67cb25
  2.59113378979454256492128084112,
Packit 67cb25
  3.15784881834760228184318034120,
Packit 67cb25
  3.76218735196402009751489394104,
Packit 67cb25
  4.42853280660377943723498532226,
Packit 67cb25
  5.22027169053748216460967142500,
Packit 67cb25
  0.245340708300901249903836530634,
Packit 67cb25
  0.737473728545394358705605144252,
Packit 67cb25
  1.23407621539532300788581834696,
Packit 67cb25
  1.73853771211658620678086566214,
Packit 67cb25
  2.25497400208927552308233334473,
Packit 67cb25
  2.78880605842813048052503375640,
Packit 67cb25
  3.34785456738321632691492452300,
Packit 67cb25
  3.94476404011562521037562880052,
Packit 67cb25
  4.60368244955074427307767524898,
Packit 67cb25
  5.38748089001123286201690041068
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/* Computes the s-th zero the physicists' Hermite polynomial of order n, thus also the s-th zero of the Hermite function of order n.
Packit 67cb25
A Newton iteration using a continued fraction representation adapted from [E.T. Whittaker (1914), On the continued fractions which represent the functions of Hermite and other functions defined by differential equations, Proceedings of the Edinburgh Mathematical Society, 32, 65-74] is performed with the initial approximation from [Arpad Elbert and Martin E. Muldoon, Approximations for zeros of Hermite functions, pp. 117-126 in D. Dominici and R. S. Maier, eds, "Special Functions and Orthogonal Polynomials", Contemporary Mathematics, vol 471 (2008)] refined via the bisection method. */
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_phys_zero_e(const int n, const int s, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  if(n <= 0 || s < 0 || s > n/2) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(s == 0) {
Packit 67cb25
    if (GSL_IS_ODD(n) == 1) {
Packit 67cb25
      result->val = 0.;
Packit 67cb25
      result->err = 0.;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
    else {
Packit 67cb25
      DOMAIN_ERROR(result);
Packit 67cb25
    }
Packit 67cb25
  }
Packit 67cb25
  else if(n == 2) {
Packit 67cb25
    result->val = M_SQRT1_2;
Packit 67cb25
    result->err = 0.;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(n < 21) {
Packit 67cb25
    result->val = H_zero_tab[(GSL_IS_ODD(n)?n/2:0)+((n/2)*(n/2-1))+s-2];
Packit 67cb25
    result->err = GSL_DBL_EPSILON*(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    double d = 1., x = 1., x0 = 1.;
Packit 67cb25
    int j;
Packit 67cb25
    x = H_zero_init(n,s);
Packit 67cb25
    do {
Packit 67cb25
      x0 = x;
Packit 67cb25
      d = 0.;
Packit 67cb25
      for (j=1; j
Packit 67cb25
      x -= (2*x-d)*0.5/n;
Packit 67cb25
    /* gsl_fcmp can be used since the smallest zero approaches 1/sqrt(n) or 1/sqrt((n-1)/3.) for large n and thus all zeros are non-zero (except for the trivial case handled above) */
Packit 67cb25
    } while (gsl_fcmp(x,x0,10*GSL_DBL_EPSILON)!=0);
Packit 67cb25
    result->val = x;
Packit 67cb25
    result->err = 2*GSL_DBL_EPSILON*x + fabs(x-x0);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_phys_zero(const int n, const int s)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_phys_zero_e(n, s, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_sf_hermite_func_zero_e(const int n, const int s, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  return gsl_sf_hermite_phys_zero_e(n, s, result);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_sf_hermite_func_zero(const int n, const int s)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_hermite_func_zero_e(n, s, &result));
Packit 67cb25
}