|
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 |
}
|