|
Packit |
67cb25 |
/* specfunc/hyperg_U.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
|
|
Packit |
67cb25 |
* Copyright (C) 2009, 2010 Brian Gough
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
67cb25 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
67cb25 |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
67cb25 |
* your option) any later version.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
67cb25 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
* General Public License for more details.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
67cb25 |
* along with this program; if not, write to the Free Software
|
|
Packit |
67cb25 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Author: G. Jungman */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_math.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_exp.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_gamma.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_bessel.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_laguerre.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_pow_int.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_sf_hyperg.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include "error.h"
|
|
Packit |
67cb25 |
#include "hyperg.h"
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#define INT_THRESHOLD (1000.0*GSL_DBL_EPSILON)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#define SERIES_EVAL_OK(a,b,x) ((fabs(a) < 5 && b < 5 && x < 2.0) || (fabs(a) < 10 && b < 10 && x < 1.0))
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#define ASYMP_EVAL_OK(a,b,x) (GSL_MAX_DBL(fabs(a),1.0)*GSL_MAX_DBL(fabs(1.0+a-b),1.0) < 0.99*fabs(x))
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Log[U(a,2a,x)]
|
|
Packit |
67cb25 |
* [Abramowitz+stegun, 13.6.21]
|
|
Packit |
67cb25 |
* Assumes x > 0, a > 1/2.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_lnU_beq2a(const double a, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double lx = log(x);
|
|
Packit |
67cb25 |
const double nu = a - 0.5;
|
|
Packit |
67cb25 |
const double lnpre = 0.5*(x - M_LNPI) - nu*lx;
|
|
Packit |
67cb25 |
gsl_sf_result lnK;
|
|
Packit |
67cb25 |
gsl_sf_bessel_lnKnu_e(nu, 0.5*x, &lnK;;
|
|
Packit |
67cb25 |
result->val = lnpre + lnK.val;
|
|
Packit |
67cb25 |
result->err = 2.0 * GSL_DBL_EPSILON * (fabs(0.5*x) + 0.5*M_LNPI + fabs(nu*lx));
|
|
Packit |
67cb25 |
result->err += lnK.err;
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate u_{N+1}/u_N by Steed's continued fraction method.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* u_N := Gamma[a+N]/Gamma[a] U(a + N, b, x)
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* u_{N+1}/u_N = (a+N) U(a+N+1,b,x)/U(a+N,b,x)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_CF1(const double a, const double b, const int N, const double x,
|
|
Packit |
67cb25 |
double * result, int * count)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double RECUR_BIG = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
const int maxiter = 20000;
|
|
Packit |
67cb25 |
int n = 1;
|
|
Packit |
67cb25 |
double Anm2 = 1.0;
|
|
Packit |
67cb25 |
double Bnm2 = 0.0;
|
|
Packit |
67cb25 |
double Anm1 = 0.0;
|
|
Packit |
67cb25 |
double Bnm1 = 1.0;
|
|
Packit |
67cb25 |
double a1 = -(a + N);
|
|
Packit |
67cb25 |
double b1 = (b - 2.0*a - x - 2.0*(N+1));
|
|
Packit |
67cb25 |
double An = b1*Anm1 + a1*Anm2;
|
|
Packit |
67cb25 |
double Bn = b1*Bnm1 + a1*Bnm2;
|
|
Packit |
67cb25 |
double an, bn;
|
|
Packit |
67cb25 |
double fn = An/Bn;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
while(n < maxiter) {
|
|
Packit |
67cb25 |
double old_fn;
|
|
Packit |
67cb25 |
double del;
|
|
Packit |
67cb25 |
n++;
|
|
Packit |
67cb25 |
Anm2 = Anm1;
|
|
Packit |
67cb25 |
Bnm2 = Bnm1;
|
|
Packit |
67cb25 |
Anm1 = An;
|
|
Packit |
67cb25 |
Bnm1 = Bn;
|
|
Packit |
67cb25 |
an = -(a + N + n - b)*(a + N + n - 1.0);
|
|
Packit |
67cb25 |
bn = (b - 2.0*a - x - 2.0*(N+n));
|
|
Packit |
67cb25 |
An = bn*Anm1 + an*Anm2;
|
|
Packit |
67cb25 |
Bn = bn*Bnm1 + an*Bnm2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(fabs(An) > RECUR_BIG || fabs(Bn) > RECUR_BIG) {
|
|
Packit |
67cb25 |
An /= RECUR_BIG;
|
|
Packit |
67cb25 |
Bn /= RECUR_BIG;
|
|
Packit |
67cb25 |
Anm1 /= RECUR_BIG;
|
|
Packit |
67cb25 |
Bnm1 /= RECUR_BIG;
|
|
Packit |
67cb25 |
Anm2 /= RECUR_BIG;
|
|
Packit |
67cb25 |
Bnm2 /= RECUR_BIG;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
old_fn = fn;
|
|
Packit |
67cb25 |
fn = An/Bn;
|
|
Packit |
67cb25 |
del = old_fn/fn;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(fabs(del - 1.0) < 10.0*GSL_DBL_EPSILON) break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*result = fn;
|
|
Packit |
67cb25 |
*count = n;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(n == maxiter)
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EMAXITER);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Large x asymptotic for x^a U(a,b,x)
|
|
Packit |
67cb25 |
* Based on SLATEC D9CHU() [W. Fullerton]
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Uses a rational approximation due to Luke.
|
|
Packit |
67cb25 |
* See [Luke, Algorithms for the Computation of Special Functions, p. 252]
|
|
Packit |
67cb25 |
* [Luke, Utilitas Math. (1977)]
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* z^a U(a,b,z) ~ 2F0(a,1+a-b,-1/z)
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This assumes that a is not a negative integer and
|
|
Packit |
67cb25 |
* that 1+a-b is not a negative integer. If one of them
|
|
Packit |
67cb25 |
* is, then the 2F0 actually terminates, the above
|
|
Packit |
67cb25 |
* relation is an equality, and the sum should be
|
|
Packit |
67cb25 |
* evaluated directly [see below].
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
d9chu(const double a, const double b, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double EPS = 8.0 * GSL_DBL_EPSILON; /* EPS = 4.0D0*D1MACH(4) */
|
|
Packit |
67cb25 |
const int maxiter = 500;
|
|
Packit |
67cb25 |
double aa[4], bb[4];
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double bp = 1.0 + a - b;
|
|
Packit |
67cb25 |
double ab = a*bp;
|
|
Packit |
67cb25 |
double ct2 = 2.0 * (x - ab);
|
|
Packit |
67cb25 |
double sab = a + bp;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double ct3 = sab + 1.0 + ab;
|
|
Packit |
67cb25 |
double anbn = ct3 + sab + 3.0;
|
|
Packit |
67cb25 |
double ct1 = 1.0 + 2.0*x/anbn;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
bb[0] = 1.0;
|
|
Packit |
67cb25 |
aa[0] = 1.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
bb[1] = 1.0 + 2.0*x/ct3;
|
|
Packit |
67cb25 |
aa[1] = 1.0 + ct2/ct3;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
bb[2] = 1.0 + 6.0*ct1*x/ct3;
|
|
Packit |
67cb25 |
aa[2] = 1.0 + 6.0*ab/anbn + 3.0*ct1*ct2/ct3;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(i=4; i
|
|
Packit |
67cb25 |
int j;
|
|
Packit |
67cb25 |
double c2;
|
|
Packit |
67cb25 |
double d1z;
|
|
Packit |
67cb25 |
double g1, g2, g3;
|
|
Packit |
67cb25 |
double x2i1 = 2*i - 3;
|
|
Packit |
67cb25 |
ct1 = x2i1/(x2i1-2.0);
|
|
Packit |
67cb25 |
anbn += x2i1 + sab;
|
|
Packit |
67cb25 |
ct2 = (x2i1 - 1.0)/anbn;
|
|
Packit |
67cb25 |
c2 = x2i1*ct2 - 1.0;
|
|
Packit |
67cb25 |
d1z = 2.0*x2i1*x/anbn;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
ct3 = sab*ct2;
|
|
Packit |
67cb25 |
g1 = d1z + ct1*(c2+ct3);
|
|
Packit |
67cb25 |
g2 = d1z - c2;
|
|
Packit |
67cb25 |
g3 = ct1*(1.0 - ct3 - 2.0*ct2);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
bb[3] = g1*bb[2] + g2*bb[1] + g3*bb[0];
|
|
Packit |
67cb25 |
aa[3] = g1*aa[2] + g2*aa[1] + g3*aa[0];
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(fabs(aa[3]*bb[0]-aa[0]*bb[3]) < EPS*fabs(bb[3]*bb[0])) break;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(j=0; j<3; j++) {
|
|
Packit |
67cb25 |
aa[j] = aa[j+1];
|
|
Packit |
67cb25 |
bb[j] = bb[j+1];
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = aa[3]/bb[3];
|
|
Packit |
67cb25 |
result->err = 8.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(i == maxiter) {
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EMAXITER);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate asymptotic for z^a U(a,b,z) ~ 2F0(a,1+a-b,-1/z)
|
|
Packit |
67cb25 |
* We check for termination of the 2F0 as a special case.
|
|
Packit |
67cb25 |
* Assumes x > 0.
|
|
Packit |
67cb25 |
* Also assumes a,b are not too large compared to x.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_zaU_asymp(const double a, const double b, const double x, gsl_sf_result *result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double ap = a;
|
|
Packit |
67cb25 |
const double bp = 1.0 + a - b;
|
|
Packit |
67cb25 |
const double rintap = floor(ap + 0.5);
|
|
Packit |
67cb25 |
const double rintbp = floor(bp + 0.5);
|
|
Packit |
67cb25 |
const int ap_neg_int = ( ap < 0.0 && fabs(ap - rintap) < INT_THRESHOLD );
|
|
Packit |
67cb25 |
const int bp_neg_int = ( bp < 0.0 && fabs(bp - rintbp) < INT_THRESHOLD );
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(ap_neg_int || bp_neg_int) {
|
|
Packit |
67cb25 |
/* Evaluate 2F0 polynomial.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
double mxi = -1.0/x;
|
|
Packit |
67cb25 |
double nmax = -(int)(GSL_MIN(ap,bp) - 0.1);
|
|
Packit |
67cb25 |
double tn = 1.0;
|
|
Packit |
67cb25 |
double sum = 1.0;
|
|
Packit |
67cb25 |
double n = 1.0;
|
|
Packit |
67cb25 |
double sum_err = 0.0;
|
|
Packit |
67cb25 |
while(n <= nmax) {
|
|
Packit |
67cb25 |
double apn = (ap+n-1.0);
|
|
Packit |
67cb25 |
double bpn = (bp+n-1.0);
|
|
Packit |
67cb25 |
tn *= ((apn/n)*mxi)*bpn;
|
|
Packit |
67cb25 |
sum += tn;
|
|
Packit |
67cb25 |
sum_err += 2.0 * GSL_DBL_EPSILON * fabs(tn);
|
|
Packit |
67cb25 |
n += 1.0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
result->val = sum;
|
|
Packit |
67cb25 |
result->err = sum_err;
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * (fabs(nmax)+1.0) * fabs(sum);
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return d9chu(a,b,x,result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate finite sum which appears below.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_finite_sum(int N, double a, double b, double x, double xeps,
|
|
Packit |
67cb25 |
gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
double sum_val;
|
|
Packit |
67cb25 |
double sum_err;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(N <= 0) {
|
|
Packit |
67cb25 |
double t_val = 1.0;
|
|
Packit |
67cb25 |
double t_err = 0.0;
|
|
Packit |
67cb25 |
gsl_sf_result poch;
|
|
Packit |
67cb25 |
int stat_poch;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sum_val = 1.0;
|
|
Packit |
67cb25 |
sum_err = 0.0;
|
|
Packit |
67cb25 |
for(i=1; i<= -N; i++) {
|
|
Packit |
67cb25 |
const double xi1 = i - 1;
|
|
Packit |
67cb25 |
const double mult = (a+xi1)*x/((b+xi1)*(xi1+1.0));
|
|
Packit |
67cb25 |
t_val *= mult;
|
|
Packit |
67cb25 |
t_err += fabs(mult) * t_err + fabs(t_val) * 8.0 * 2.0 * GSL_DBL_EPSILON;
|
|
Packit |
67cb25 |
sum_val += t_val;
|
|
Packit |
67cb25 |
sum_err += t_err;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
stat_poch = gsl_sf_poch_e(1.0+a-b, -a, &poch);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = sum_val * poch.val;
|
|
Packit |
67cb25 |
result->err = fabs(sum_val) * poch.err + sum_err * fabs(poch.val);
|
|
Packit |
67cb25 |
result->err += fabs(poch.val) * (fabs(N) + 2.0) * GSL_DBL_EPSILON * fabs(sum_val);
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
result->err *= 2.0; /* FIXME: fudge factor... why is the error estimate too small? */
|
|
Packit |
67cb25 |
return stat_poch;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
const int M = N - 2;
|
|
Packit |
67cb25 |
if(M < 0) {
|
|
Packit |
67cb25 |
result->val = 0.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
gsl_sf_result gbm1;
|
|
Packit |
67cb25 |
gsl_sf_result gamr;
|
|
Packit |
67cb25 |
int stat_gbm1;
|
|
Packit |
67cb25 |
int stat_gamr;
|
|
Packit |
67cb25 |
double t_val = 1.0;
|
|
Packit |
67cb25 |
double t_err = 0.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sum_val = 1.0;
|
|
Packit |
67cb25 |
sum_err = 0.0;
|
|
Packit |
67cb25 |
for(i=1; i<=M; i++) {
|
|
Packit |
67cb25 |
const double mult = (a-b+i)*x/((1.0-b+i)*i);
|
|
Packit |
67cb25 |
t_val *= mult;
|
|
Packit |
67cb25 |
t_err += t_err * fabs(mult) + fabs(t_val) * 8.0 * 2.0 * GSL_DBL_EPSILON;
|
|
Packit |
67cb25 |
sum_val += t_val;
|
|
Packit |
67cb25 |
sum_err += t_err;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
stat_gbm1 = gsl_sf_gamma_e(b-1.0, &gbm1);
|
|
Packit |
67cb25 |
stat_gamr = gsl_sf_gammainv_e(a, &gamr;;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(stat_gbm1 == GSL_SUCCESS) {
|
|
Packit |
67cb25 |
gsl_sf_result powx1N;
|
|
Packit |
67cb25 |
int stat_p = gsl_sf_pow_int_e(x, 1-N, &powx1N);
|
|
Packit |
67cb25 |
double pe_val = powx1N.val * xeps;
|
|
Packit |
67cb25 |
double pe_err = powx1N.err * fabs(xeps) + 2.0 * GSL_DBL_EPSILON * fabs(pe_val);
|
|
Packit |
67cb25 |
double coeff_val = gbm1.val * gamr.val * pe_val;
|
|
Packit |
67cb25 |
double coeff_err = gbm1.err * fabs(gamr.val * pe_val)
|
|
Packit |
67cb25 |
+ gamr.err * fabs(gbm1.val * pe_val)
|
|
Packit |
67cb25 |
+ fabs(gbm1.val * gamr.val) * pe_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(coeff_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = sum_val * coeff_val;
|
|
Packit |
67cb25 |
result->err = fabs(sum_val) * coeff_err + sum_err * fabs(coeff_val);
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * (M+2.0) * fabs(result->val);
|
|
Packit |
67cb25 |
result->err *= 2.0; /* FIXME: fudge factor... why is the error estimate too small? */
|
|
Packit |
67cb25 |
return stat_p;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
result->val = 0.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
return stat_gbm1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate infinite sum which appears below.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_infinite_sum_stable(int N, double a, double bint, double b, double beps, double x, double xeps, gsl_sf_result sum,
|
|
Packit |
67cb25 |
gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double EPS = 2.0 * GSL_DBL_EPSILON; /* EPS = D1MACH(3) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int istrt = ( N < 1 ? 1-N : 0 );
|
|
Packit |
67cb25 |
double xi = istrt;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result gamr;
|
|
Packit |
67cb25 |
gsl_sf_result powx;
|
|
Packit |
67cb25 |
int stat_gamr = gsl_sf_gammainv_e(1.0+a-b, &gamr;;
|
|
Packit |
67cb25 |
int stat_powx = gsl_sf_pow_int_e(x, istrt, &powx);
|
|
Packit |
67cb25 |
double sarg = beps*M_PI;
|
|
Packit |
67cb25 |
double sfact = ( sarg != 0.0 ? sarg/sin(sarg) : 1.0 );
|
|
Packit |
67cb25 |
double factor_val = sfact * ( GSL_IS_ODD(N) ? -1.0 : 1.0 ) * gamr.val * powx.val;
|
|
Packit |
67cb25 |
double factor_err = fabs(gamr.val) * powx.err + fabs(powx.val) * gamr.err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(factor_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochai;
|
|
Packit |
67cb25 |
gsl_sf_result gamri1;
|
|
Packit |
67cb25 |
gsl_sf_result gamrni;
|
|
Packit |
67cb25 |
int stat_pochai = gsl_sf_poch_e(a, xi, &pochai);
|
|
Packit |
67cb25 |
int stat_gamri1 = gsl_sf_gammainv_e(xi + 1.0, &gamri1);
|
|
Packit |
67cb25 |
int stat_gamrni = gsl_sf_gammainv_e(bint + xi, &gamrni);
|
|
Packit |
67cb25 |
int stat_gam123 = GSL_ERROR_SELECT_3(stat_gamr, stat_gamri1, stat_gamrni);
|
|
Packit |
67cb25 |
int stat_gamall = GSL_ERROR_SELECT_3(stat_gam123, stat_pochai, stat_powx);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochaxibeps;
|
|
Packit |
67cb25 |
gsl_sf_result gamrxi1beps;
|
|
Packit |
67cb25 |
int stat_pochaxibeps = gsl_sf_poch_e(a, xi-beps, &pochaxibeps);
|
|
Packit |
67cb25 |
int stat_gamrxi1beps = gsl_sf_gammainv_e(xi + 1.0 - beps, &gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int stat_all = GSL_ERROR_SELECT_3(stat_gamall, stat_pochaxibeps, stat_gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double b0_val = factor_val * pochaxibeps.val * gamrni.val * gamrxi1beps.val;
|
|
Packit |
67cb25 |
double b0_err = fabs(factor_val * pochaxibeps.val * gamrni.val) * gamrxi1beps.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochaxibeps.val * gamrxi1beps.val) * gamrni.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamrni.val * gamrxi1beps.val) * pochaxibeps.err
|
|
Packit |
67cb25 |
+ fabs(pochaxibeps.val * gamrni.val * gamrxi1beps.val) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(b0_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
C X**(-BEPS) IS VERY DIFFERENT FROM 1.0, SO THE
|
|
Packit |
67cb25 |
C STRAIGHTFORWARD FORMULATION IS STABLE.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
double dchu_val;
|
|
Packit |
67cb25 |
double dchu_err;
|
|
Packit |
67cb25 |
double t_val;
|
|
Packit |
67cb25 |
double t_err;
|
|
Packit |
67cb25 |
gsl_sf_result dgamrbxi;
|
|
Packit |
67cb25 |
int stat_dgamrbxi = gsl_sf_gammainv_e(b+xi, &dgamrbxi);
|
|
Packit |
67cb25 |
double a0_val = factor_val * pochai.val * dgamrbxi.val * gamri1.val / beps;
|
|
Packit |
67cb25 |
double a0_err = fabs(factor_val * pochai.val * dgamrbxi.val / beps) * gamri1.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochai.val * gamri1.val / beps) * dgamrbxi.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * dgamrbxi.val * gamri1.val / beps) * pochai.err
|
|
Packit |
67cb25 |
+ fabs(pochai.val * dgamrbxi.val * gamri1.val / beps) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(a0_val);
|
|
Packit |
67cb25 |
stat_all = GSL_ERROR_SELECT_2(stat_all, stat_dgamrbxi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
b0_val = xeps * b0_val / beps;
|
|
Packit |
67cb25 |
b0_err = fabs(xeps / beps) * b0_err + 4.0 * GSL_DBL_EPSILON * fabs(b0_val);
|
|
Packit |
67cb25 |
dchu_val = sum.val + a0_val - b0_val;
|
|
Packit |
67cb25 |
dchu_err = sum.err + a0_err + b0_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * (fabs(sum.val) + fabs(a0_val) + fabs(b0_val));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(i=1; i<2000; i++) {
|
|
Packit |
67cb25 |
double xi = istrt + i;
|
|
Packit |
67cb25 |
double xi1 = istrt + i - 1;
|
|
Packit |
67cb25 |
double a0_multiplier = (a+xi1)*x/((b+xi1)*xi);
|
|
Packit |
67cb25 |
double b0_multiplier = (a+xi1-beps)*x/((bint+xi1)*(xi-beps));
|
|
Packit |
67cb25 |
a0_val *= a0_multiplier;
|
|
Packit |
67cb25 |
a0_err += fabs(a0_multiplier) * a0_err;
|
|
Packit |
67cb25 |
b0_val *= b0_multiplier;
|
|
Packit |
67cb25 |
b0_err += fabs(b0_multiplier) * b0_err;
|
|
Packit |
67cb25 |
t_val = a0_val - b0_val;
|
|
Packit |
67cb25 |
t_err = a0_err + b0_err;
|
|
Packit |
67cb25 |
dchu_val += t_val;
|
|
Packit |
67cb25 |
dchu_err += t_err;
|
|
Packit |
67cb25 |
if(fabs(t_val) < EPS*fabs(dchu_val)) break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = dchu_val;
|
|
Packit |
67cb25 |
result->err = 2.0 * dchu_err;
|
|
Packit |
67cb25 |
result->err += 2.0 * fabs(t_val);
|
|
Packit |
67cb25 |
result->err += 4.0 * GSL_DBL_EPSILON * (i+2.0) * fabs(dchu_val);
|
|
Packit |
67cb25 |
result->err *= 2.0; /* FIXME: fudge factor */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(i >= 2000) {
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EMAXITER);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return stat_all;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_infinite_sum_simple(int N, double a, double bint, double b, double beps, double x, double xeps, gsl_sf_result sum,
|
|
Packit |
67cb25 |
gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double EPS = 2.0 * GSL_DBL_EPSILON; /* EPS = D1MACH(3) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int istrt = ( N < 1 ? 1-N : 0 );
|
|
Packit |
67cb25 |
double xi = istrt;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result powx;
|
|
Packit |
67cb25 |
int stat_powx = gsl_sf_pow_int_e(x, istrt, &powx);
|
|
Packit |
67cb25 |
double sarg = beps*M_PI;
|
|
Packit |
67cb25 |
double sfact = ( sarg != 0.0 ? sarg/sin(sarg) : 1.0 );
|
|
Packit |
67cb25 |
double factor_val = sfact * ( GSL_IS_ODD(N) ? -1.0 : 1.0 ) * powx.val;
|
|
Packit |
67cb25 |
double factor_err = fabs(powx.err) + 2.0 * GSL_DBL_EPSILON * fabs(factor_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochai;
|
|
Packit |
67cb25 |
gsl_sf_result gamri1;
|
|
Packit |
67cb25 |
gsl_sf_result gamrni;
|
|
Packit |
67cb25 |
int stat_pochai = gsl_sf_poch_e(a, xi, &pochai);
|
|
Packit |
67cb25 |
int stat_gamri1 = gsl_sf_gammainv_e(xi + 1.0, &gamri1);
|
|
Packit |
67cb25 |
int stat_gamrni = gsl_sf_gammainv_e(bint + xi, &gamrni);
|
|
Packit |
67cb25 |
int stat_gam123 = GSL_ERROR_SELECT_2(stat_gamri1, stat_gamrni);
|
|
Packit |
67cb25 |
int stat_gamall = GSL_ERROR_SELECT_3(stat_gam123, stat_pochai, stat_powx);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochaxibeps;
|
|
Packit |
67cb25 |
gsl_sf_result gamrxi1beps;
|
|
Packit |
67cb25 |
int stat_pochaxibeps = gsl_sf_poch_e(a, xi-beps, &pochaxibeps);
|
|
Packit |
67cb25 |
int stat_gamrxi1beps = gsl_sf_gammainv_e(xi + 1.0 - beps, &gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int stat_all = GSL_ERROR_SELECT_3(stat_gamall, stat_pochaxibeps, stat_gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double X = sfact * ( GSL_IS_ODD(N) ? -1.0 : 1.0 ) * powx.val * gsl_sf_poch(1 + a - b, xi - 1 + b - beps) * gsl_sf_gammainv(a);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double b0_val = X * gamrni.val * gamrxi1beps.val;
|
|
Packit |
67cb25 |
double b0_err = fabs(factor_val * pochaxibeps.val * gamrni.val) * gamrxi1beps.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochaxibeps.val * gamrxi1beps.val) * gamrni.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamrni.val * gamrxi1beps.val) * pochaxibeps.err
|
|
Packit |
67cb25 |
+ fabs(pochaxibeps.val * gamrni.val * gamrxi1beps.val) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(b0_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
C X**(-BEPS) IS VERY DIFFERENT FROM 1.0, SO THE
|
|
Packit |
67cb25 |
C STRAIGHTFORWARD FORMULATION IS STABLE.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
double dchu_val;
|
|
Packit |
67cb25 |
double dchu_err;
|
|
Packit |
67cb25 |
double t_val;
|
|
Packit |
67cb25 |
double t_err;
|
|
Packit |
67cb25 |
gsl_sf_result gamr;
|
|
Packit |
67cb25 |
gsl_sf_result dgamrbxi;
|
|
Packit |
67cb25 |
int stat_gamr = gsl_sf_gammainv_e(1.0+a-b, &gamr;;
|
|
Packit |
67cb25 |
int stat_dgamrbxi = gsl_sf_gammainv_e(b+xi, &dgamrbxi);
|
|
Packit |
67cb25 |
double a0_val = factor_val * gamr.val * pochai.val * dgamrbxi.val * gamri1.val / beps;
|
|
Packit |
67cb25 |
double a0_err = fabs(factor_val * pochai.val * dgamrbxi.val * gamri1.val / beps) * gamr.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamr.val * dgamrbxi.val * gamri1.val / beps) * pochai.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamr.val * pochai.val * gamri1.val / beps) * dgamrbxi.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamr.val * pochai.val * dgamrbxi.val / beps) * gamri1.err
|
|
Packit |
67cb25 |
+ fabs(pochai.val * gamr.val * dgamrbxi.val * gamri1.val / beps) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(a0_val);
|
|
Packit |
67cb25 |
stat_all = GSL_ERROR_SELECT_3(stat_all, stat_gamr, stat_dgamrbxi);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
b0_val = xeps * b0_val / beps;
|
|
Packit |
67cb25 |
b0_err = fabs(xeps / beps) * b0_err + 4.0 * GSL_DBL_EPSILON * fabs(b0_val);
|
|
Packit |
67cb25 |
dchu_val = sum.val + a0_val - b0_val;
|
|
Packit |
67cb25 |
dchu_err = sum.err + a0_err + b0_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * (fabs(sum.val) + fabs(a0_val) + fabs(b0_val));
|
|
Packit |
67cb25 |
for(i=1; i<2000; i++) {
|
|
Packit |
67cb25 |
double xi = istrt + i;
|
|
Packit |
67cb25 |
double xi1 = istrt + i - 1;
|
|
Packit |
67cb25 |
double a0_multiplier = (a+xi1)*x/((b+xi1)*xi);
|
|
Packit |
67cb25 |
double b0_multiplier = (a+xi1-beps)*x/((bint+xi1)*(xi-beps));
|
|
Packit |
67cb25 |
a0_val *= a0_multiplier;
|
|
Packit |
67cb25 |
a0_err += fabs(a0_multiplier) * a0_err;
|
|
Packit |
67cb25 |
b0_val *= b0_multiplier;
|
|
Packit |
67cb25 |
b0_err += fabs(b0_multiplier) * b0_err;
|
|
Packit |
67cb25 |
t_val = a0_val - b0_val;
|
|
Packit |
67cb25 |
t_err = a0_err + b0_err;
|
|
Packit |
67cb25 |
dchu_val += t_val;
|
|
Packit |
67cb25 |
dchu_err += t_err;
|
|
Packit |
67cb25 |
if(!gsl_finite(t_val) || fabs(t_val) < EPS*fabs(dchu_val)) break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = dchu_val;
|
|
Packit |
67cb25 |
result->err = 2.0 * dchu_err;
|
|
Packit |
67cb25 |
result->err += 2.0 * fabs(t_val);
|
|
Packit |
67cb25 |
result->err += 4.0 * GSL_DBL_EPSILON * (i+2.0) * fabs(dchu_val);
|
|
Packit |
67cb25 |
result->err *= 2.0; /* FIXME: fudge factor */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(i >= 2000) {
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EMAXITER);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return stat_all;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_infinite_sum_improved(int N, double a, double bint, double b, double beps, double x, double xeps, gsl_sf_result sum,
|
|
Packit |
67cb25 |
gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double EPS = 2.0 * GSL_DBL_EPSILON; /* EPS = D1MACH(3) */
|
|
Packit |
67cb25 |
const double lnx = log(x);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int istrt = ( N < 1 ? 1-N : 0 );
|
|
Packit |
67cb25 |
double xi = istrt;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result gamr;
|
|
Packit |
67cb25 |
gsl_sf_result powx;
|
|
Packit |
67cb25 |
int stat_gamr = gsl_sf_gammainv_e(1.0+a-b, &gamr;;
|
|
Packit |
67cb25 |
int stat_powx = gsl_sf_pow_int_e(x, istrt, &powx);
|
|
Packit |
67cb25 |
double sarg = beps*M_PI;
|
|
Packit |
67cb25 |
double sfact = ( sarg != 0.0 ? sarg/sin(sarg) : 1.0 );
|
|
Packit |
67cb25 |
double factor_val = sfact * ( GSL_IS_ODD(N) ? -1.0 : 1.0 ) * gamr.val * powx.val;
|
|
Packit |
67cb25 |
double factor_err = fabs(gamr.val) * powx.err + fabs(powx.val) * gamr.err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(factor_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochai;
|
|
Packit |
67cb25 |
gsl_sf_result gamri1;
|
|
Packit |
67cb25 |
gsl_sf_result gamrni;
|
|
Packit |
67cb25 |
int stat_pochai = gsl_sf_poch_e(a, xi, &pochai);
|
|
Packit |
67cb25 |
int stat_gamri1 = gsl_sf_gammainv_e(xi + 1.0, &gamri1);
|
|
Packit |
67cb25 |
int stat_gamrni = gsl_sf_gammainv_e(bint + xi, &gamrni);
|
|
Packit |
67cb25 |
int stat_gam123 = GSL_ERROR_SELECT_3(stat_gamr, stat_gamri1, stat_gamrni);
|
|
Packit |
67cb25 |
int stat_gamall = GSL_ERROR_SELECT_3(stat_gam123, stat_pochai, stat_powx);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
gsl_sf_result pochaxibeps;
|
|
Packit |
67cb25 |
gsl_sf_result gamrxi1beps;
|
|
Packit |
67cb25 |
int stat_pochaxibeps = gsl_sf_poch_e(a, xi-beps, &pochaxibeps);
|
|
Packit |
67cb25 |
int stat_gamrxi1beps = gsl_sf_gammainv_e(xi + 1.0 - beps, &gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int stat_all = GSL_ERROR_SELECT_3(stat_gamall, stat_pochaxibeps, stat_gamrxi1beps);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double b0_val = factor_val * pochaxibeps.val * gamrni.val * gamrxi1beps.val;
|
|
Packit |
67cb25 |
double b0_err = fabs(factor_val * pochaxibeps.val * gamrni.val) * gamrxi1beps.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochaxibeps.val * gamrxi1beps.val) * gamrni.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamrni.val * gamrxi1beps.val) * pochaxibeps.err
|
|
Packit |
67cb25 |
+ fabs(pochaxibeps.val * gamrni.val * gamrxi1beps.val) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(b0_val);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
C X**(-BEPS) IS CLOSE TO 1.0D0, SO WE MUST BE
|
|
Packit |
67cb25 |
C CAREFUL IN EVALUATING THE DIFFERENCES.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int i;
|
|
Packit |
67cb25 |
gsl_sf_result pch1ai;
|
|
Packit |
67cb25 |
gsl_sf_result pch1i;
|
|
Packit |
67cb25 |
gsl_sf_result poch1bxibeps;
|
|
Packit |
67cb25 |
int stat_pch1ai = gsl_sf_pochrel_e(a + xi, -beps, &pch1ai);
|
|
Packit |
67cb25 |
int stat_pch1i = gsl_sf_pochrel_e(xi + 1.0 - beps, beps, &pch1i);
|
|
Packit |
67cb25 |
int stat_poch1bxibeps = gsl_sf_pochrel_e(b+xi, -beps, &poch1bxibeps);
|
|
Packit |
67cb25 |
double c0_t1_val = beps*pch1ai.val*pch1i.val;
|
|
Packit |
67cb25 |
double c0_t1_err = fabs(beps) * fabs(pch1ai.val) * pch1i.err
|
|
Packit |
67cb25 |
+ fabs(beps) * fabs(pch1i.val) * pch1ai.err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(c0_t1_val);
|
|
Packit |
67cb25 |
double c0_t2_val = -poch1bxibeps.val + pch1ai.val - pch1i.val + c0_t1_val;
|
|
Packit |
67cb25 |
double c0_t2_err = poch1bxibeps.err + pch1ai.err + pch1i.err + c0_t1_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(c0_t2_val);
|
|
Packit |
67cb25 |
double c0_val = factor_val * pochai.val * gamrni.val * gamri1.val * c0_t2_val;
|
|
Packit |
67cb25 |
double c0_err = fabs(factor_val * pochai.val * gamrni.val * gamri1.val) * c0_t2_err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochai.val * gamrni.val * c0_t2_val) * gamri1.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * pochai.val * gamri1.val * c0_t2_val) * gamrni.err
|
|
Packit |
67cb25 |
+ fabs(factor_val * gamrni.val * gamri1.val * c0_t2_val) * pochai.err
|
|
Packit |
67cb25 |
+ fabs(pochai.val * gamrni.val * gamri1.val * c0_t2_val) * factor_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(c0_val);
|
|
Packit |
67cb25 |
/*
|
|
Packit |
67cb25 |
C XEPS1 = (1.0 - X**(-BEPS))/BEPS = (X**(-BEPS) - 1.0)/(-BEPS)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result dexprl;
|
|
Packit |
67cb25 |
int stat_dexprl = gsl_sf_exprel_e(-beps*lnx, &dexprl);
|
|
Packit |
67cb25 |
double xeps1_val = lnx * dexprl.val;
|
|
Packit |
67cb25 |
double xeps1_err = 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(beps*lnx)) * fabs(dexprl.val)
|
|
Packit |
67cb25 |
+ fabs(lnx) * dexprl.err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * fabs(xeps1_val);
|
|
Packit |
67cb25 |
double dchu_val = sum.val + c0_val + xeps1_val*b0_val;
|
|
Packit |
67cb25 |
double dchu_err = sum.err + c0_err
|
|
Packit |
67cb25 |
+ fabs(xeps1_val)*b0_err + xeps1_err * fabs(b0_val)
|
|
Packit |
67cb25 |
+ fabs(b0_val*lnx)*dexprl.err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * (fabs(sum.val) + fabs(c0_val) + fabs(xeps1_val*b0_val));
|
|
Packit |
67cb25 |
double xn = N;
|
|
Packit |
67cb25 |
double t_val;
|
|
Packit |
67cb25 |
double t_err;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
stat_all = GSL_ERROR_SELECT_5(stat_all, stat_dexprl, stat_poch1bxibeps, stat_pch1i, stat_pch1ai);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(i=1; i<2000; i++) {
|
|
Packit |
67cb25 |
const double xi = istrt + i;
|
|
Packit |
67cb25 |
const double xi1 = istrt + i - 1;
|
|
Packit |
67cb25 |
const double tmp = (a-1.0)*(xn+2.0*xi-1.0) + xi*(xi-beps);
|
|
Packit |
67cb25 |
const double b0_multiplier = (a+xi1-beps)*x/((xn+xi1)*(xi-beps));
|
|
Packit |
67cb25 |
const double c0_multiplier_1 = (a+xi1)*x/((b+xi1)*xi);
|
|
Packit |
67cb25 |
const double c0_multiplier_2 = tmp / (xi*(b+xi1)*(a+xi1-beps));
|
|
Packit |
67cb25 |
b0_val *= b0_multiplier;
|
|
Packit |
67cb25 |
b0_err += fabs(b0_multiplier) * b0_err + fabs(b0_val) * 8.0 * 2.0 * GSL_DBL_EPSILON;
|
|
Packit |
67cb25 |
c0_val = c0_multiplier_1 * c0_val - c0_multiplier_2 * b0_val;
|
|
Packit |
67cb25 |
c0_err = fabs(c0_multiplier_1) * c0_err
|
|
Packit |
67cb25 |
+ fabs(c0_multiplier_2) * b0_err
|
|
Packit |
67cb25 |
+ fabs(c0_val) * 8.0 * 2.0 * GSL_DBL_EPSILON
|
|
Packit |
67cb25 |
+ fabs(b0_val * c0_multiplier_2) * 16.0 * 2.0 * GSL_DBL_EPSILON;
|
|
Packit |
67cb25 |
t_val = c0_val + xeps1_val*b0_val;
|
|
Packit |
67cb25 |
t_err = c0_err + fabs(xeps1_val)*b0_err;
|
|
Packit |
67cb25 |
t_err += fabs(b0_val*lnx) * dexprl.err;
|
|
Packit |
67cb25 |
t_err += fabs(b0_val)*xeps1_err;
|
|
Packit |
67cb25 |
dchu_val += t_val;
|
|
Packit |
67cb25 |
dchu_err += t_err;
|
|
Packit |
67cb25 |
if(fabs(t_val) < EPS*fabs(dchu_val)) break;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = dchu_val;
|
|
Packit |
67cb25 |
result->err = 2.0 * dchu_err;
|
|
Packit |
67cb25 |
result->err += 2.0 * fabs(t_val);
|
|
Packit |
67cb25 |
result->err += 4.0 * GSL_DBL_EPSILON * (i+2.0) * fabs(dchu_val);
|
|
Packit |
67cb25 |
result->err *= 2.0; /* FIXME: fudge factor */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(i >= 2000) {
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EMAXITER);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return stat_all;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Based on SLATEC DCHU() [W. Fullerton]
|
|
Packit |
67cb25 |
* Assumes x > 0.
|
|
Packit |
67cb25 |
* This is just a series summation method, and
|
|
Packit |
67cb25 |
* it is not good for large a.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* I patched up the window for 1+a-b near zero. [GJ]
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_series(const double a, const double b, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double SQRT_EPS = M_SQRT2 * GSL_SQRT_DBL_EPSILON;
|
|
Packit |
67cb25 |
double bint = ( b < 0.0 ? ceil(b-0.5) : floor(b+0.5) );
|
|
Packit |
67cb25 |
double beps = b - bint;
|
|
Packit |
67cb25 |
double a_beps = a - beps;
|
|
Packit |
67cb25 |
double r_a_beps = floor(a_beps + 0.5);
|
|
Packit |
67cb25 |
double a_beps_int = ( fabs(a_beps - r_a_beps) < INT_THRESHOLD );
|
|
Packit |
67cb25 |
/* double a_b_1 = a-b+1;
|
|
Packit |
67cb25 |
double r_a_b_1 = floor(a_b_1+0.5);
|
|
Packit |
67cb25 |
double r_a_b_1_int = (fabs(a_b_1-r_a_b_1)< INT_THRESHOLD);
|
|
Packit |
67cb25 |
Check for (a-beps) being a member of -N; N being 0,1,... */
|
|
Packit |
67cb25 |
if (a_beps_int && a_beps <= 0)
|
|
Packit |
67cb25 |
{ beps=beps - 1 + floor(a_beps);bint=bint + 1 - floor(a_beps);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(fabs(1.0 + a - b) < SQRT_EPS) {
|
|
Packit |
67cb25 |
/* Original Comment: ALGORITHM IS BAD WHEN 1+A-B IS NEAR ZERO FOR SMALL X
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
/* We can however do the following:
|
|
Packit |
67cb25 |
* U(a,b,x) = U(a,a+1,x) when 1+a-b=0
|
|
Packit |
67cb25 |
* and U(a,a+1,x) = x^(-a).
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
double lnr = -a * log(x);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_e(lnr, result);
|
|
Packit |
67cb25 |
result->err += 2.0 * SQRT_EPS * fabs(result->val);
|
|
Packit |
67cb25 |
return stat_e;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
int N = (int) bint;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double lnx = log(x);
|
|
Packit |
67cb25 |
double xeps = exp(-beps*lnx);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate finite sum.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result sum;
|
|
Packit |
67cb25 |
int stat_sum = hyperg_U_finite_sum(N, a, b, x, xeps, &sum);
|
|
Packit |
67cb25 |
int stat_inf;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Evaluate infinite sum. */
|
|
Packit |
67cb25 |
if(fabs(xeps-1.0) > 0.5 ) {
|
|
Packit |
67cb25 |
stat_inf = hyperg_U_infinite_sum_stable(N, a, bint, b, beps, x, xeps, sum, result);
|
|
Packit |
67cb25 |
} else if (1+a-b < 0 && 1+a-b==floor(1+a-b) && beps != 0) {
|
|
Packit |
67cb25 |
stat_inf = hyperg_U_infinite_sum_simple(N, a, bint, b, beps, x, xeps, sum, result);
|
|
Packit |
67cb25 |
} else {
|
|
Packit |
67cb25 |
stat_inf = hyperg_U_infinite_sum_improved(N, a, bint, b, beps, x, xeps, sum, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_sum, stat_inf);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Assumes b > 0 and x > 0.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_small_ab(const double a, const double b, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if(a == -1.0) {
|
|
Packit |
67cb25 |
/* U(-1,c+1,x) = Laguerre[c,0,x] = -b + x
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
result->val = -b + x;
|
|
Packit |
67cb25 |
result->err = 2.0 * GSL_DBL_EPSILON * (fabs(b) + fabs(x));
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a == 0.0) {
|
|
Packit |
67cb25 |
/* U(0,c+1,x) = Laguerre[c,0,x] = 1
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
result->val = 1.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(ASYMP_EVAL_OK(a,b,x)) {
|
|
Packit |
67cb25 |
double p = pow(x, -a);
|
|
Packit |
67cb25 |
gsl_sf_result asymp;
|
|
Packit |
67cb25 |
int stat_asymp = hyperg_zaU_asymp(a, b, x, &asymp);
|
|
Packit |
67cb25 |
result->val = asymp.val * p;
|
|
Packit |
67cb25 |
result->err = asymp.err * p;
|
|
Packit |
67cb25 |
result->err += fabs(asymp.val) * GSL_DBL_EPSILON * fabs(a) * p;
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
return stat_asymp;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
return hyperg_U_series(a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Assumes b > 0 and x > 0.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_small_a_bgt0(const double a, const double b, const double x,
|
|
Packit |
67cb25 |
gsl_sf_result * result,
|
|
Packit |
67cb25 |
double * ln_multiplier
|
|
Packit |
67cb25 |
)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if(a == 0.0) {
|
|
Packit |
67cb25 |
result->val = 1.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
*ln_multiplier = 0.0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if( (b > 5000.0 && x < 0.90 * fabs(b))
|
|
Packit |
67cb25 |
|| (b > 500.0 && x < 0.50 * fabs(b))
|
|
Packit |
67cb25 |
) {
|
|
Packit |
67cb25 |
int stat = gsl_sf_hyperg_U_large_b_e(a, b, x, result, ln_multiplier);
|
|
Packit |
67cb25 |
if(stat == GSL_EOVRFLW)
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
return stat;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(b > 15.0) {
|
|
Packit |
67cb25 |
/* Recurse up from b near 1.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
double eps = b - floor(b);
|
|
Packit |
67cb25 |
double b0 = 1.0 + eps;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ubm1;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ub;
|
|
Packit |
67cb25 |
int stat_0 = hyperg_U_small_ab(a, b0, x, &r_Ubm1);
|
|
Packit |
67cb25 |
int stat_1 = hyperg_U_small_ab(a, b0+1.0, x, &r_Ub);
|
|
Packit |
67cb25 |
double Ubm1 = r_Ubm1.val;
|
|
Packit |
67cb25 |
double Ub = r_Ub.val;
|
|
Packit |
67cb25 |
double Ubp1;
|
|
Packit |
67cb25 |
double bp;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(bp = b0+1.0; bp
|
|
Packit |
67cb25 |
Ubp1 = ((1.0+a-bp)*Ubm1 + (bp+x-1.0)*Ub)/x;
|
|
Packit |
67cb25 |
Ubm1 = Ub;
|
|
Packit |
67cb25 |
Ub = Ubp1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
result->val = Ub;
|
|
Packit |
67cb25 |
result->err = (fabs(r_Ubm1.err/r_Ubm1.val) + fabs(r_Ub.err/r_Ub.val)) * fabs(Ub);
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * (fabs(b-b0)+1.0) * fabs(Ub);
|
|
Packit |
67cb25 |
*ln_multiplier = 0.0;
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_0, stat_1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
*ln_multiplier = 0.0;
|
|
Packit |
67cb25 |
return hyperg_U_small_ab(a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* We use this to keep track of large
|
|
Packit |
67cb25 |
* dynamic ranges in the recursions.
|
|
Packit |
67cb25 |
* This can be important because sometimes
|
|
Packit |
67cb25 |
* we want to calculate a very large and
|
|
Packit |
67cb25 |
* a very small number and the answer is
|
|
Packit |
67cb25 |
* the product, of order 1. This happens,
|
|
Packit |
67cb25 |
* for instance, when we apply a Kummer
|
|
Packit |
67cb25 |
* transform to make b positive and
|
|
Packit |
67cb25 |
* both x and b are large.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
#define RESCALE_2(u0,u1,factor,count) \
|
|
Packit |
67cb25 |
do { \
|
|
Packit |
67cb25 |
double au0 = fabs(u0); \
|
|
Packit |
67cb25 |
if(au0 > factor) { \
|
|
Packit |
67cb25 |
u0 /= factor; \
|
|
Packit |
67cb25 |
u1 /= factor; \
|
|
Packit |
67cb25 |
count++; \
|
|
Packit |
67cb25 |
} \
|
|
Packit |
67cb25 |
else if(au0 < 1.0/factor) { \
|
|
Packit |
67cb25 |
u0 *= factor; \
|
|
Packit |
67cb25 |
u1 *= factor; \
|
|
Packit |
67cb25 |
count--; \
|
|
Packit |
67cb25 |
} \
|
|
Packit |
67cb25 |
} while (0)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Specialization to b >= 1, for integer parameters.
|
|
Packit |
67cb25 |
* Assumes x > 0.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_int_bge1(const int a, const int b, const double x,
|
|
Packit |
67cb25 |
gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if(a == 0) {
|
|
Packit |
67cb25 |
result->val = 1.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a == -1) {
|
|
Packit |
67cb25 |
result->val = -b + x;
|
|
Packit |
67cb25 |
result->err = 2.0 * GSL_DBL_EPSILON * (fabs(b) + fabs(x));
|
|
Packit |
67cb25 |
result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(b == a + 1) {
|
|
Packit |
67cb25 |
/* U(a,a+1,x) = x^(-a)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
return gsl_sf_exp_e10_e(-a*log(x), result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(ASYMP_EVAL_OK(a,b,x)) {
|
|
Packit |
67cb25 |
const double ln_pre_val = -a*log(x);
|
|
Packit |
67cb25 |
const double ln_pre_err = 2.0 * GSL_DBL_EPSILON * fabs(ln_pre_val);
|
|
Packit |
67cb25 |
gsl_sf_result asymp;
|
|
Packit |
67cb25 |
int stat_asymp = hyperg_zaU_asymp(a, b, x, &asymp);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_mult_err_e10_e(ln_pre_val, ln_pre_err,
|
|
Packit |
67cb25 |
asymp.val, asymp.err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_asymp);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(SERIES_EVAL_OK(a,b,x) && 1 + a - b > 0) {
|
|
Packit |
67cb25 |
gsl_sf_result ser;
|
|
Packit |
67cb25 |
const int stat_ser = hyperg_U_series(a, b, x, &ser;;
|
|
Packit |
67cb25 |
result->val = ser.val;
|
|
Packit |
67cb25 |
result->err = ser.err;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return stat_ser;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a < 0) {
|
|
Packit |
67cb25 |
/* Recurse backward from a = -1,0.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
double lnscale;
|
|
Packit |
67cb25 |
double Uap1 = 1.0; /* U(0,b,x) */
|
|
Packit |
67cb25 |
double Ua = -b + x; /* U(-1,b,x) */
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
int ap;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(ap=-1; ap>a; ap--) {
|
|
Packit |
67cb25 |
Uam1 = ap*(b-ap-1.0)*Uap1 + (x+2.0*ap-b)*Ua;
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
lnm.val = scale_count*lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * fabs(lnm.val);
|
|
Packit |
67cb25 |
y.val = Ua;
|
|
Packit |
67cb25 |
y.err = 4.0 * GSL_DBL_EPSILON * (fabs(a)+1.0) * fabs(Ua);
|
|
Packit |
67cb25 |
return gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(b >= 2.0*a + x) {
|
|
Packit |
67cb25 |
/* Recurse forward from a = 0,1.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ua;
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
double lnscale;
|
|
Packit |
67cb25 |
double lm;
|
|
Packit |
67cb25 |
int stat_1 = hyperg_U_small_a_bgt0(1.0, b, x, &r_Ua, &lm); /* U(1,b,x) */
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
double Uam1 = 1.0; /* U(0,b,x) */
|
|
Packit |
67cb25 |
double Ua = r_Ua.val;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
int ap;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Uam1 *= exp(-lm);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(ap=1; ap
|
|
Packit |
67cb25 |
Uap1 = -(Uam1 + (b-2.0*ap-x)*Ua)/(ap*(1.0+ap-b));
|
|
Packit |
67cb25 |
Uam1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uap1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uam1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
lnm.val = lm + scale_count * lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm) + fabs(scale_count*lnscale));
|
|
Packit |
67cb25 |
y.val = Ua;
|
|
Packit |
67cb25 |
y.err = fabs(r_Ua.err/r_Ua.val) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err += 2.0 * GSL_DBL_EPSILON * (fabs(a) + 1.0) * fabs(Ua);
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
if(b <= x) {
|
|
Packit |
67cb25 |
/* Recurse backward either to the b=a+1 line
|
|
Packit |
67cb25 |
* or to a=0, whichever we hit.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
int stat_CF1;
|
|
Packit |
67cb25 |
double ru;
|
|
Packit |
67cb25 |
int CF1_count;
|
|
Packit |
67cb25 |
int a_target;
|
|
Packit |
67cb25 |
double lnU_target;
|
|
Packit |
67cb25 |
double Ua;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
int ap;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(b < a + 1) {
|
|
Packit |
67cb25 |
a_target = b-1;
|
|
Packit |
67cb25 |
lnU_target = -a_target*log(x);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
a_target = 0;
|
|
Packit |
67cb25 |
lnU_target = 0.0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
stat_CF1 = hyperg_U_CF1(a, b, 0, x, &ru, &CF1_count);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Ua = 1.0;
|
|
Packit |
67cb25 |
Uap1 = ru/a * Ua;
|
|
Packit |
67cb25 |
for(ap=a; ap>a_target; ap--) {
|
|
Packit |
67cb25 |
Uam1 = -((b-2.0*ap-x)*Ua + ap*(1.0+ap-b)*Uap1);
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(Ua == 0.0) {
|
|
Packit |
67cb25 |
result->val = 0.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EZERODIV);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
double lnscl = -scale_count*log(scale_factor);
|
|
Packit |
67cb25 |
double lnpre_val = lnU_target + lnscl;
|
|
Packit |
67cb25 |
double lnpre_err = 2.0 * GSL_DBL_EPSILON * (fabs(lnU_target) + fabs(lnscl));
|
|
Packit |
67cb25 |
double oUa_err = 2.0 * (fabs(a_target-a) + CF1_count + 1.0) * GSL_DBL_EPSILON * fabs(1.0/Ua);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_mult_err_e10_e(lnpre_val, lnpre_err,
|
|
Packit |
67cb25 |
1.0/Ua, oUa_err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_CF1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Recurse backward to near the b=2a+x line, then
|
|
Packit |
67cb25 |
* determine normalization by either direct evaluation
|
|
Packit |
67cb25 |
* or by a forward recursion. The direct evaluation
|
|
Packit |
67cb25 |
* is needed when x is small (which is precisely
|
|
Packit |
67cb25 |
* when it is easy to do).
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
int scale_count_for = 0;
|
|
Packit |
67cb25 |
int scale_count_bck = 0;
|
|
Packit |
67cb25 |
int a0 = 1;
|
|
Packit |
67cb25 |
int a1 = a0 + ceil(0.5*(b-x) - a0);
|
|
Packit |
67cb25 |
double Ua1_bck_val;
|
|
Packit |
67cb25 |
double Ua1_bck_err;
|
|
Packit |
67cb25 |
double Ua1_for_val;
|
|
Packit |
67cb25 |
double Ua1_for_err;
|
|
Packit |
67cb25 |
int stat_for;
|
|
Packit |
67cb25 |
int stat_bck;
|
|
Packit |
67cb25 |
gsl_sf_result lm_for;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Recurse back to determine U(a1,b), sans normalization.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
double ru;
|
|
Packit |
67cb25 |
int CF1_count;
|
|
Packit |
67cb25 |
int stat_CF1 = hyperg_U_CF1(a, b, 0, x, &ru, &CF1_count);
|
|
Packit |
67cb25 |
double Ua = 1.0;
|
|
Packit |
67cb25 |
double Uap1 = ru/a * Ua;
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
int ap;
|
|
Packit |
67cb25 |
for(ap=a; ap>a1; ap--) {
|
|
Packit |
67cb25 |
Uam1 = -((b-2.0*ap-x)*Ua + ap*(1.0+ap-b)*Uap1);
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count_bck);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
Ua1_bck_val = Ua;
|
|
Packit |
67cb25 |
Ua1_bck_err = 2.0 * GSL_DBL_EPSILON * (fabs(a1-a)+CF1_count+1.0) * fabs(Ua);
|
|
Packit |
67cb25 |
stat_bck = stat_CF1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(b == 2*a1 && a1 > 1) {
|
|
Packit |
67cb25 |
/* This can happen when x is small, which is
|
|
Packit |
67cb25 |
* precisely when we need to be careful with
|
|
Packit |
67cb25 |
* this evaluation.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
hyperg_lnU_beq2a((double)a1, x, &lm_for);
|
|
Packit |
67cb25 |
Ua1_for_val = 1.0;
|
|
Packit |
67cb25 |
Ua1_for_err = 0.0;
|
|
Packit |
67cb25 |
stat_for = GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(b == 2*a1 - 1 && a1 > 1) {
|
|
Packit |
67cb25 |
/* Similar to the above. Happens when x is small.
|
|
Packit |
67cb25 |
* Use
|
|
Packit |
67cb25 |
* U(a,2a-1) = (x U(a,2a) - U(a-1,2(a-1))) / (2a - 2)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result lnU00, lnU12;
|
|
Packit |
67cb25 |
gsl_sf_result U00, U12;
|
|
Packit |
67cb25 |
hyperg_lnU_beq2a(a1-1.0, x, &lnU00);
|
|
Packit |
67cb25 |
hyperg_lnU_beq2a(a1, x, &lnU12);
|
|
Packit |
67cb25 |
if(lnU00.val > lnU12.val) {
|
|
Packit |
67cb25 |
lm_for.val = lnU00.val;
|
|
Packit |
67cb25 |
lm_for.err = lnU00.err;
|
|
Packit |
67cb25 |
U00.val = 1.0;
|
|
Packit |
67cb25 |
U00.err = 0.0;
|
|
Packit |
67cb25 |
gsl_sf_exp_err_e(lnU12.val - lm_for.val, lnU12.err + lm_for.err, &U12);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
lm_for.val = lnU12.val;
|
|
Packit |
67cb25 |
lm_for.err = lnU12.err;
|
|
Packit |
67cb25 |
U12.val = 1.0;
|
|
Packit |
67cb25 |
U12.err = 0.0;
|
|
Packit |
67cb25 |
gsl_sf_exp_err_e(lnU00.val - lm_for.val, lnU00.err + lm_for.err, &U00);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
Ua1_for_val = (x * U12.val - U00.val) / (2.0*a1 - 2.0);
|
|
Packit |
67cb25 |
Ua1_for_err = (fabs(x)*U12.err + U00.err) / fabs(2.0*a1 - 2.0);
|
|
Packit |
67cb25 |
Ua1_for_err += 2.0 * GSL_DBL_EPSILON * fabs(Ua1_for_val);
|
|
Packit |
67cb25 |
stat_for = GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Recurse forward to determine U(a1,b) with
|
|
Packit |
67cb25 |
* absolute normalization.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result r_Ua;
|
|
Packit |
67cb25 |
double Uam1 = 1.0; /* U(a0-1,b,x) = U(0,b,x) */
|
|
Packit |
67cb25 |
double Ua;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
int ap;
|
|
Packit |
67cb25 |
double lm_for_local;
|
|
Packit |
67cb25 |
stat_for = hyperg_U_small_a_bgt0(a0, b, x, &r_Ua, &lm_for_local); /* U(1,b,x) */
|
|
Packit |
67cb25 |
Ua = r_Ua.val;
|
|
Packit |
67cb25 |
Uam1 *= exp(-lm_for_local);
|
|
Packit |
67cb25 |
lm_for.val = lm_for_local;
|
|
Packit |
67cb25 |
lm_for.err = 0.0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(ap=a0; ap
|
|
Packit |
67cb25 |
Uap1 = -(Uam1 + (b-2.0*ap-x)*Ua)/(ap*(1.0+ap-b));
|
|
Packit |
67cb25 |
Uam1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uap1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uam1,scale_factor,scale_count_for);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
Ua1_for_val = Ua;
|
|
Packit |
67cb25 |
Ua1_for_err = fabs(Ua) * fabs(r_Ua.err/r_Ua.val);
|
|
Packit |
67cb25 |
Ua1_for_err += 2.0 * GSL_DBL_EPSILON * (fabs(a1-a0)+1.0) * fabs(Ua1_for_val);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Now do the matching to produce the final result.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
if(Ua1_bck_val == 0.0) {
|
|
Packit |
67cb25 |
result->val = 0.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
GSL_ERROR ("error", GSL_EZERODIV);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(Ua1_for_val == 0.0) {
|
|
Packit |
67cb25 |
/* Should never happen. */
|
|
Packit |
67cb25 |
UNDERFLOW_ERROR_E10(result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
double lns = (scale_count_for - scale_count_bck)*log(scale_factor);
|
|
Packit |
67cb25 |
double ln_for_val = log(fabs(Ua1_for_val));
|
|
Packit |
67cb25 |
double ln_for_err = GSL_DBL_EPSILON + fabs(Ua1_for_err/Ua1_for_val);
|
|
Packit |
67cb25 |
double ln_bck_val = log(fabs(Ua1_bck_val));
|
|
Packit |
67cb25 |
double ln_bck_err = GSL_DBL_EPSILON + fabs(Ua1_bck_err/Ua1_bck_val);
|
|
Packit |
67cb25 |
double lnr_val = lm_for.val + ln_for_val - ln_bck_val + lns;
|
|
Packit |
67cb25 |
double lnr_err = lm_for.err + ln_for_err + ln_bck_err
|
|
Packit |
67cb25 |
+ 2.0 * GSL_DBL_EPSILON * (fabs(lm_for.val) + fabs(ln_for_val) + fabs(ln_bck_val) + fabs(lns));
|
|
Packit |
67cb25 |
double sgn = GSL_SIGN(Ua1_for_val) * GSL_SIGN(Ua1_bck_val);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_err_e10_e(lnr_val, lnr_err, result);
|
|
Packit |
67cb25 |
result->val *= sgn;
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_3(stat_e, stat_bck, stat_for);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Handle b >= 1 for generic a,b values.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
static
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
hyperg_U_bge1(const double a, const double b, const double x,
|
|
Packit |
67cb25 |
gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double rinta = floor(a+0.5);
|
|
Packit |
67cb25 |
const int a_neg_integer = (a < 0.0 && fabs(a - rinta) < INT_THRESHOLD);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(a == 0.0) {
|
|
Packit |
67cb25 |
result->val = 1.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a_neg_integer && fabs(rinta) < INT_MAX) {
|
|
Packit |
67cb25 |
/* U(-n,b,x) = (-1)^n n! Laguerre[n,b-1,x]
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const int n = -(int)rinta;
|
|
Packit |
67cb25 |
const double sgn = (GSL_IS_ODD(n) ? -1.0 : 1.0);
|
|
Packit |
67cb25 |
gsl_sf_result lnfact;
|
|
Packit |
67cb25 |
gsl_sf_result L;
|
|
Packit |
67cb25 |
const int stat_L = gsl_sf_laguerre_n_e(n, b-1.0, x, &L);
|
|
Packit |
67cb25 |
gsl_sf_lnfact_e(n, &lnfact);
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const int stat_e = gsl_sf_exp_mult_err_e10_e(lnfact.val, lnfact.err,
|
|
Packit |
67cb25 |
sgn*L.val, L.err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_L);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(ASYMP_EVAL_OK(a,b,x)) {
|
|
Packit |
67cb25 |
const double ln_pre_val = -a*log(x);
|
|
Packit |
67cb25 |
const double ln_pre_err = 2.0 * GSL_DBL_EPSILON * fabs(ln_pre_val);
|
|
Packit |
67cb25 |
gsl_sf_result asymp;
|
|
Packit |
67cb25 |
int stat_asymp = hyperg_zaU_asymp(a, b, x, &asymp);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_mult_err_e10_e(ln_pre_val, ln_pre_err,
|
|
Packit |
67cb25 |
asymp.val, asymp.err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_asymp);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(fabs(a) <= 1.0) {
|
|
Packit |
67cb25 |
gsl_sf_result rU;
|
|
Packit |
67cb25 |
double ln_multiplier;
|
|
Packit |
67cb25 |
int stat_U = hyperg_U_small_a_bgt0(a, b, x, &rU, &ln_multiplier);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_mult_err_e10_e(ln_multiplier, 2.0*GSL_DBL_EPSILON*fabs(ln_multiplier), rU.val, rU.err, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_U, stat_e);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(SERIES_EVAL_OK(a,b,x)) {
|
|
Packit |
67cb25 |
gsl_sf_result ser;
|
|
Packit |
67cb25 |
const int stat_ser = hyperg_U_series(a, b, x, &ser;;
|
|
Packit |
67cb25 |
result->val = ser.val;
|
|
Packit |
67cb25 |
result->err = ser.err;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return stat_ser;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a < 0.0) {
|
|
Packit |
67cb25 |
/* Recurse backward on a and then upward on b.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
const double a0 = a - floor(a) - 1.0;
|
|
Packit |
67cb25 |
const double b0 = b - floor(b) + 1.0;
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
double lm_0, lm_1;
|
|
Packit |
67cb25 |
double lm_max;
|
|
Packit |
67cb25 |
gsl_sf_result r_Uap1;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ua;
|
|
Packit |
67cb25 |
int stat_0 = hyperg_U_small_a_bgt0(a0+1.0, b0, x, &r_Uap1, &lm_0);
|
|
Packit |
67cb25 |
int stat_1 = hyperg_U_small_a_bgt0(a0, b0, x, &r_Ua, &lm_1);
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
double Uap1 = r_Uap1.val;
|
|
Packit |
67cb25 |
double Ua = r_Ua.val;
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
double ap;
|
|
Packit |
67cb25 |
lm_max = GSL_MAX(lm_0, lm_1);
|
|
Packit |
67cb25 |
Uap1 *= exp(lm_0-lm_max);
|
|
Packit |
67cb25 |
Ua *= exp(lm_1-lm_max);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Downward recursion on a.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
for(ap=a0; ap>a+0.1; ap -= 1.0) {
|
|
Packit |
67cb25 |
Uam1 = ap*(b0-ap-1.0)*Uap1 + (x+2.0*ap-b0)*Ua;
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(b < 2.0) {
|
|
Packit |
67cb25 |
/* b == b0, so no recursion necessary
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
lnm.val = lm_max + scale_count * lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm_max) + scale_count * fabs(lnscale));
|
|
Packit |
67cb25 |
y.val = Ua;
|
|
Packit |
67cb25 |
y.err = fabs(r_Uap1.err/r_Uap1.val) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err += fabs(r_Ua.err/r_Ua.val) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err += 2.0 * GSL_DBL_EPSILON * (fabs(a-a0) + 1.0) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err *= fabs(lm_0-lm_max) + 1.0;
|
|
Packit |
67cb25 |
y.err *= fabs(lm_1-lm_max) + 1.0;
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Upward recursion on b.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double err_mult = fabs(b-b0) + fabs(a-a0) + 1.0;
|
|
Packit |
67cb25 |
const double lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double Ubm1 = Ua; /* U(a,b0) */
|
|
Packit |
67cb25 |
double Ub = (a*(b0-a-1.0)*Uap1 + (a+x)*Ua)/x; /* U(a,b0+1) */
|
|
Packit |
67cb25 |
double Ubp1;
|
|
Packit |
67cb25 |
double bp;
|
|
Packit |
67cb25 |
for(bp=b0+1.0; bp
|
|
Packit |
67cb25 |
Ubp1 = ((1.0+a-bp)*Ubm1 + (bp+x-1.0)*Ub)/x;
|
|
Packit |
67cb25 |
Ubm1 = Ub;
|
|
Packit |
67cb25 |
Ub = Ubp1;
|
|
Packit |
67cb25 |
RESCALE_2(Ub,Ubm1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnm.val = lm_max + scale_count * lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm_max) + fabs(scale_count * lnscale));
|
|
Packit |
67cb25 |
y.val = Ub;
|
|
Packit |
67cb25 |
y.err = 2.0 * err_mult * fabs(r_Uap1.err/r_Uap1.val) * fabs(Ub);
|
|
Packit |
67cb25 |
y.err += 2.0 * err_mult * fabs(r_Ua.err/r_Ua.val) * fabs(Ub);
|
|
Packit |
67cb25 |
y.err += 2.0 * GSL_DBL_EPSILON * err_mult * fabs(Ub);
|
|
Packit |
67cb25 |
y.err *= fabs(lm_0-lm_max) + 1.0;
|
|
Packit |
67cb25 |
y.err *= fabs(lm_1-lm_max) + 1.0;
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_3(stat_e, stat_0, stat_1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(b >= 2*a + x) {
|
|
Packit |
67cb25 |
/* Recurse forward from a near zero.
|
|
Packit |
67cb25 |
* Note that we cannot cross the singularity at
|
|
Packit |
67cb25 |
* the line b=a+1, because the only way we could
|
|
Packit |
67cb25 |
* be in that little wedge is if a < 1. But we
|
|
Packit |
67cb25 |
* have already dealt with the small a case.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
const double a0 = a - floor(a);
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
double lnscale;
|
|
Packit |
67cb25 |
double lm_0, lm_1, lm_max;
|
|
Packit |
67cb25 |
gsl_sf_result r_Uam1;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ua;
|
|
Packit |
67cb25 |
int stat_0 = hyperg_U_small_a_bgt0(a0-1.0, b, x, &r_Uam1, &lm_0);
|
|
Packit |
67cb25 |
int stat_1 = hyperg_U_small_a_bgt0(a0, b, x, &r_Ua, &lm_1);
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
double Uam1 = r_Uam1.val;
|
|
Packit |
67cb25 |
double Ua = r_Ua.val;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
double ap;
|
|
Packit |
67cb25 |
lm_max = GSL_MAX(lm_0, lm_1);
|
|
Packit |
67cb25 |
Uam1 *= exp(lm_0-lm_max);
|
|
Packit |
67cb25 |
Ua *= exp(lm_1-lm_max);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(ap=a0; ap
|
|
Packit |
67cb25 |
Uap1 = -(Uam1 + (b-2.0*ap-x)*Ua)/(ap*(1.0+ap-b));
|
|
Packit |
67cb25 |
Uam1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uap1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uam1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
lnm.val = lm_max + scale_count * lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm_max) + fabs(scale_count * lnscale));
|
|
Packit |
67cb25 |
y.val = Ua;
|
|
Packit |
67cb25 |
y.err = fabs(r_Uam1.err/r_Uam1.val) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err += fabs(r_Ua.err/r_Ua.val) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err += 2.0 * GSL_DBL_EPSILON * (fabs(a-a0) + 1.0) * fabs(Ua);
|
|
Packit |
67cb25 |
y.err *= fabs(lm_0-lm_max) + 1.0;
|
|
Packit |
67cb25 |
y.err *= fabs(lm_1-lm_max) + 1.0;
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_3(stat_e, stat_0, stat_1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
if(b <= x) {
|
|
Packit |
67cb25 |
/* Recurse backward to a near zero.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double a0 = a - floor(a);
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
int scale_count = 0;
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
double lnscale;
|
|
Packit |
67cb25 |
double lm_0;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
double Ua;
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
gsl_sf_result U0;
|
|
Packit |
67cb25 |
double ap;
|
|
Packit |
67cb25 |
double ru;
|
|
Packit |
67cb25 |
double r;
|
|
Packit |
67cb25 |
int CF1_count;
|
|
Packit |
67cb25 |
int stat_CF1 = hyperg_U_CF1(a, b, 0, x, &ru, &CF1_count);
|
|
Packit |
67cb25 |
int stat_U0;
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
r = ru/a;
|
|
Packit |
67cb25 |
Ua = GSL_SQRT_DBL_MIN;
|
|
Packit |
67cb25 |
Uap1 = r * Ua;
|
|
Packit |
67cb25 |
for(ap=a; ap>a0+0.1; ap -= 1.0) {
|
|
Packit |
67cb25 |
Uam1 = -((b-2.0*ap-x)*Ua + ap*(1.0+ap-b)*Uap1);
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
stat_U0 = hyperg_U_small_a_bgt0(a0, b, x, &U0, &lm_0);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
lnm.val = lm_0 - scale_count * lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm_0) + fabs(scale_count * lnscale));
|
|
Packit |
67cb25 |
y.val = GSL_SQRT_DBL_MIN*(U0.val/Ua);
|
|
Packit |
67cb25 |
y.err = GSL_SQRT_DBL_MIN*(U0.err/fabs(Ua));
|
|
Packit |
67cb25 |
y.err += 2.0 * GSL_DBL_EPSILON * (fabs(a0-a) + CF1_count + 1.0) * fabs(y.val);
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_3(stat_e, stat_U0, stat_CF1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Recurse backward to near the b=2a+x line, then
|
|
Packit |
67cb25 |
* forward from a near zero to get the normalization.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
int scale_count_for = 0;
|
|
Packit |
67cb25 |
int scale_count_bck = 0;
|
|
Packit |
67cb25 |
const double scale_factor = GSL_SQRT_DBL_MAX;
|
|
Packit |
67cb25 |
const double eps = a - floor(a);
|
|
Packit |
67cb25 |
const double a0 = ( eps == 0.0 ? 1.0 : eps );
|
|
Packit |
67cb25 |
const double a1 = a0 + ceil(0.5*(b-x) - a0);
|
|
Packit |
67cb25 |
gsl_sf_result lnm;
|
|
Packit |
67cb25 |
gsl_sf_result y;
|
|
Packit |
67cb25 |
double lm_for;
|
|
Packit |
67cb25 |
double lnscale;
|
|
Packit |
67cb25 |
double Ua1_bck;
|
|
Packit |
67cb25 |
double Ua1_for;
|
|
Packit |
67cb25 |
int stat_for;
|
|
Packit |
67cb25 |
int stat_bck;
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
int CF1_count;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Recurse back to determine U(a1,b), sans normalization.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
double Ua;
|
|
Packit |
67cb25 |
double Uam1;
|
|
Packit |
67cb25 |
double ap;
|
|
Packit |
67cb25 |
double ru;
|
|
Packit |
67cb25 |
double r;
|
|
Packit |
67cb25 |
int stat_CF1 = hyperg_U_CF1(a, b, 0, x, &ru, &CF1_count);
|
|
Packit |
67cb25 |
r = ru/a;
|
|
Packit |
67cb25 |
Ua = GSL_SQRT_DBL_MIN;
|
|
Packit |
67cb25 |
Uap1 = r * Ua;
|
|
Packit |
67cb25 |
for(ap=a; ap>a1+0.1; ap -= 1.0) {
|
|
Packit |
67cb25 |
Uam1 = -((b-2.0*ap-x)*Ua + ap*(1.0+ap-b)*Uap1);
|
|
Packit |
67cb25 |
Uap1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uam1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uap1,scale_factor,scale_count_bck);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
Ua1_bck = Ua;
|
|
Packit |
67cb25 |
stat_bck = stat_CF1;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Recurse forward to determine U(a1,b) with
|
|
Packit |
67cb25 |
* absolute normalization.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result r_Uam1;
|
|
Packit |
67cb25 |
gsl_sf_result r_Ua;
|
|
Packit |
67cb25 |
double lm_0, lm_1;
|
|
Packit |
67cb25 |
int stat_0 = hyperg_U_small_a_bgt0(a0-1.0, b, x, &r_Uam1, &lm_0);
|
|
Packit |
67cb25 |
int stat_1 = hyperg_U_small_a_bgt0(a0, b, x, &r_Ua, &lm_1);
|
|
Packit |
67cb25 |
double Uam1 = r_Uam1.val;
|
|
Packit |
67cb25 |
double Ua = r_Ua.val;
|
|
Packit |
67cb25 |
double Uap1;
|
|
Packit |
67cb25 |
double ap;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lm_for = GSL_MAX(lm_0, lm_1);
|
|
Packit |
67cb25 |
Uam1 *= exp(lm_0 - lm_for);
|
|
Packit |
67cb25 |
Ua *= exp(lm_1 - lm_for);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
for(ap=a0; ap
|
|
Packit |
67cb25 |
Uap1 = -(Uam1 + (b-2.0*ap-x)*Ua)/(ap*(1.0+ap-b));
|
|
Packit |
67cb25 |
Uam1 = Ua;
|
|
Packit |
67cb25 |
Ua = Uap1;
|
|
Packit |
67cb25 |
RESCALE_2(Ua,Uam1,scale_factor,scale_count_for);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
Ua1_for = Ua;
|
|
Packit |
67cb25 |
stat_for = GSL_ERROR_SELECT_2(stat_0, stat_1);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lnscale = log(scale_factor);
|
|
Packit |
67cb25 |
lnm.val = lm_for + (scale_count_for - scale_count_bck)*lnscale;
|
|
Packit |
67cb25 |
lnm.err = 2.0 * GSL_DBL_EPSILON * (fabs(lm_for) + fabs(scale_count_for - scale_count_bck)*fabs(lnscale));
|
|
Packit |
67cb25 |
y.val = GSL_SQRT_DBL_MIN*Ua1_for/Ua1_bck;
|
|
Packit |
67cb25 |
y.err = 2.0 * GSL_DBL_EPSILON * (fabs(a-a0) + CF1_count + 1.0) * fabs(y.val);
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(lnm.val, lnm.err, y.val, y.err, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_3(stat_e, stat_bck, stat_for);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Handle U(a,b,x) using AMS 13.1.3 when x = 0. This requires b<1 to
|
|
Packit |
67cb25 |
avoid a singularity from the term z^(1-b)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
U(a,b,z=0) = (pi/sin(pi*b)) * 1/(gamma(1+a-b)*gamma(b))
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
There are a lot of special limiting cases here
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
b = 0, positive integer, negative integer
|
|
Packit |
67cb25 |
1+a-b = 0, negative integer
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
I haven't implemented these yet - BJG
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
hyperg_U_origin (const double a, const double b, gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result r1, r2;
|
|
Packit |
67cb25 |
int stat_1 = gsl_sf_gammainv_e(1+a-b,&r1;;
|
|
Packit |
67cb25 |
int stat_2 = gsl_sf_gammainv_e(b,&r2;;
|
|
Packit |
67cb25 |
double factor = M_PI / sin(M_PI*b);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = factor * r1.val * r2.val;
|
|
Packit |
67cb25 |
result->err = fabs(factor) * (r1.err + r2.err);
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_1, stat_2);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
hyperg_U_int_origin (const int a, const int b, gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return hyperg_U_origin (a, b, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Calculate U(a,b,x) for x < 0
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Abramowitz and Stegun formula 13.1.3
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
U(a,b,x) = (gamma(1-b)/gamma(1+a-b)) M(a,b,x)
|
|
Packit |
67cb25 |
- z^(1-b) (gamma(1-b)/gamma(a)) M(1+a-b,2-b,x)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
can be transformed into
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
U(a,b,x) = poch(1+a-b,-a) M(a,b,x)
|
|
Packit |
67cb25 |
+ z^(1-b) poch(a,-(1+a-b)) M(1+a-b,2-b,x)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
using the reflection formula 6.1.17 and the definition of
|
|
Packit |
67cb25 |
Poch(a,b)=gamma(a+b)/gamma(a). Our poch function already handles
|
|
Packit |
67cb25 |
the special cases of ratios of gamma functions with negative
|
|
Packit |
67cb25 |
integer argument.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Note that U(a,b,x) is complex in general for x<0 due to the term
|
|
Packit |
67cb25 |
x^(1-b), but is real when
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
1) b is an integer
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
4) a is zero or a negative integer so x^(1-b)/gamma(a) is zero.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
For integer b U(a,b,x) is defined as the limit beta->b U(a,beta,x).
|
|
Packit |
67cb25 |
This makes the situation slightly more complicated.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
hyperg_U_negx (const double a, const double b, const double x, gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result r1, r2;
|
|
Packit |
67cb25 |
int stat_1, stat_2, status;
|
|
Packit |
67cb25 |
int a_int = (a == floor(a));
|
|
Packit |
67cb25 |
int b_int = (b == floor(b));
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double T1 = 0, T1_err = 0, T2 = 0, T2_err = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute the first term poch(1+a-b) M(a,b,x) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (b_int && b <= 0 && !(a_int && a <= 0 && a >= b))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Need to handle first term as
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
lim_{beta->b} poch(1+a-beta,-a) M(a,beta,x)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
due to pole in M(a,b,x) for b == 0 or -ve integer
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
We skip this case when a is zero or a negative integer and
|
|
Packit |
67cb25 |
a>=b because the hypergeometric series terminates before any
|
|
Packit |
67cb25 |
singular terms
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* FIXME: TO BE IMPLEMENTED ! */
|
|
Packit |
67cb25 |
result->val = GSL_NAN; result->err = GSL_NAN;
|
|
Packit |
67cb25 |
GSL_ERROR("limit case integer b <= 0 unimplemented", GSL_EUNIMPL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
stat_1 = gsl_sf_poch_e(1+a-b,-a,&r1;;
|
|
Packit |
67cb25 |
status = stat_1;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (r1.val != 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result Mr1;
|
|
Packit |
67cb25 |
int stat_Mr1 = gsl_sf_hyperg_1F1_e (a, b, x, &Mr1);
|
|
Packit |
67cb25 |
status = GSL_ERROR_SELECT_2(status, stat_Mr1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
T1 = Mr1.val * r1.val;
|
|
Packit |
67cb25 |
T1_err = 2.0 * GSL_DBL_EPSILON * fabs(T1)
|
|
Packit |
67cb25 |
+ fabs(Mr1.err * r1.val) + fabs(Mr1.val * r1.err) ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Compute the second term z^(1-b) poch(a,-(1+a-b)) M(1+a-b,2-b,x) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (b_int && b >= 2 && !(a_int && a <= (b - 2)))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Need to handle second term as a limit due to pole in
|
|
Packit |
67cb25 |
M(1+a-b,2-b,x).
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
We skip this case when a is integer and a <= b-2 because the
|
|
Packit |
67cb25 |
hypergeometric series terminates before any singular terms
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* FIXME: TO BE IMPLEMENTED ! */
|
|
Packit |
67cb25 |
result->val = GSL_NAN; result->err = GSL_NAN;
|
|
Packit |
67cb25 |
GSL_ERROR("limit case integer b >= 2 unimplemented", GSL_EUNIMPL);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (a_int && a <= 0 && (b >= 1))
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
r2.val = 0;
|
|
Packit |
67cb25 |
r2.err = 0;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
stat_2 = gsl_sf_poch_e(a,-(1+a-b),&r2;;
|
|
Packit |
67cb25 |
status = GSL_ERROR_SELECT_2(status, stat_2);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (r2.val != 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result Mr2;
|
|
Packit |
67cb25 |
int stat_Mr2 = gsl_sf_hyperg_1F1_e (1+a-b, 2-b, x, &Mr2);
|
|
Packit |
67cb25 |
T2 = Mr2.val * r2.val;
|
|
Packit |
67cb25 |
T2_err = 2.0 * GSL_DBL_EPSILON * fabs(T2)
|
|
Packit |
67cb25 |
+ fabs(Mr2.err * r2.val) + fabs(Mr2.val * r2.err);
|
|
Packit |
67cb25 |
status = GSL_ERROR_SELECT_2(status, stat_Mr2);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (T2 != 0.0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double x1mb = pow(x, 1-b);
|
|
Packit |
67cb25 |
T2 = x1mb * T2;
|
|
Packit |
67cb25 |
T2_err = fabs(x1mb) * T2_err;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
result->val = (T1 + T2);
|
|
Packit |
67cb25 |
result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val) + (T1_err + T2_err);
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
hyperg_U_int_negx (const int a, const int b, const double x, gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* Looking at the tests it seems that everything is handled correctly by hyperg_U_negx
|
|
Packit |
67cb25 |
except a
|
|
Packit |
67cb25 |
In order to do no (little) harm I fix up only a
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
if (a
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result_e10 r1;
|
|
Packit |
67cb25 |
double z21_z = pow(x, 1-b);
|
|
Packit |
67cb25 |
int status = hyperg_U_negx (1+a-b,2-b, x, &r1;;
|
|
Packit |
67cb25 |
double res_tem=z21_z*r1.val;
|
|
Packit |
67cb25 |
double res_tem_err = fabs(z21_z)*r1.err;
|
|
Packit |
67cb25 |
result->val = res_tem;
|
|
Packit |
67cb25 |
result->err = res_tem_err;
|
|
Packit |
67cb25 |
return status;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return hyperg_U_negx (a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_sf_hyperg_U_int_e10_e(const int a, const int b, const double x,
|
|
Packit |
67cb25 |
gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
/* CHECK_POINTER(result) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(x == 0.0 && b >= 1) {
|
|
Packit |
67cb25 |
DOMAIN_ERROR_E10(result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (x == 0.0) {
|
|
Packit |
67cb25 |
return hyperg_U_int_origin (a, b, result);
|
|
Packit |
67cb25 |
} else if (x < 0.0) {
|
|
Packit |
67cb25 |
return hyperg_U_int_negx (a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
if(b >= 1) {
|
|
Packit |
67cb25 |
return hyperg_U_int_bge1(a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Use the reflection formula
|
|
Packit |
67cb25 |
* U(a,b,x) = x^(1-b) U(1+a-b,2-b,x)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
gsl_sf_result_e10 U;
|
|
Packit |
67cb25 |
double ln_x = log(x);
|
|
Packit |
67cb25 |
int ap = 1 + a - b;
|
|
Packit |
67cb25 |
int bp = 2 - b;
|
|
Packit |
67cb25 |
int stat_e;
|
|
Packit |
67cb25 |
int stat_U = hyperg_U_int_bge1(ap, bp, x, &U);
|
|
Packit |
67cb25 |
double ln_pre_val = (1.0-b)*ln_x;
|
|
Packit |
67cb25 |
double ln_pre_err = 2.0 * GSL_DBL_EPSILON * (fabs(b)+1.0) * fabs(ln_x);
|
|
Packit |
67cb25 |
ln_pre_err += 2.0 * GSL_DBL_EPSILON * fabs(1.0-b); /* error in log(x) */
|
|
Packit |
67cb25 |
stat_e = gsl_sf_exp_mult_err_e10_e(ln_pre_val + U.e10*M_LN10, ln_pre_err,
|
|
Packit |
67cb25 |
U.val, U.err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_U);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_sf_hyperg_U_e10_e(const double a, const double b, const double x,
|
|
Packit |
67cb25 |
gsl_sf_result_e10 * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
const double rinta = floor(a + 0.5);
|
|
Packit |
67cb25 |
const double rintb = floor(b + 0.5);
|
|
Packit |
67cb25 |
const int a_integer = ( fabs(a - rinta) < INT_THRESHOLD );
|
|
Packit |
67cb25 |
const int b_integer = ( fabs(b - rintb) < INT_THRESHOLD );
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* CHECK_POINTER(result) */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if(x == 0.0 && b >= 1) {
|
|
Packit |
67cb25 |
DOMAIN_ERROR_E10(result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a == 0.0) {
|
|
Packit |
67cb25 |
result->val = 1.0;
|
|
Packit |
67cb25 |
result->err = 0.0;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (x == 0.0) {
|
|
Packit |
67cb25 |
return hyperg_U_origin (a, b, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a_integer && b == a + 1)
|
|
Packit |
67cb25 |
/* This is DLMF 13.6.4 */
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result powx1N_1;
|
|
Packit |
67cb25 |
gsl_sf_pow_int_e(x, -a, &powx1N_1);
|
|
Packit |
67cb25 |
result->val = powx1N_1.val;
|
|
Packit |
67cb25 |
result->err = powx1N_1.err;
|
|
Packit |
67cb25 |
result->e10 = 0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if(a_integer && b_integer) {
|
|
Packit |
67cb25 |
return gsl_sf_hyperg_U_int_e10_e(rinta, rintb, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (x < 0.0) {
|
|
Packit |
67cb25 |
return hyperg_U_negx (a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
if(b >= 1.0) {
|
|
Packit |
67cb25 |
/* Use b >= 1 function.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
return hyperg_U_bge1(a, b, x, result);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else {
|
|
Packit |
67cb25 |
/* Use the reflection formula
|
|
Packit |
67cb25 |
* U(a,b,x) = x^(1-b) U(1+a-b,2-b,x)
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
const double lnx = log(x);
|
|
Packit |
67cb25 |
const double ln_pre_val = (1.0-b)*lnx;
|
|
Packit |
67cb25 |
const double ln_pre_err = fabs(lnx) * 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(b));
|
|
Packit |
67cb25 |
const double ap = 1.0 + a - b;
|
|
Packit |
67cb25 |
const double bp = 2.0 - b;
|
|
Packit |
67cb25 |
gsl_sf_result_e10 U;
|
|
Packit |
67cb25 |
int stat_U = hyperg_U_bge1(ap, bp, x, &U);
|
|
Packit |
67cb25 |
int stat_e = gsl_sf_exp_mult_err_e10_e(ln_pre_val + U.e10*M_LN10, ln_pre_err,
|
|
Packit |
67cb25 |
U.val, U.err,
|
|
Packit |
67cb25 |
result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_e, stat_U);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_sf_hyperg_U_int_e(const int a, const int b, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result_e10 re = {0, 0, 0};
|
|
Packit |
67cb25 |
int stat_U = gsl_sf_hyperg_U_int_e10_e(a, b, x, &re);
|
|
Packit |
67cb25 |
int stat_c = gsl_sf_result_smash_e(&re, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_c, stat_U);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int
|
|
Packit |
67cb25 |
gsl_sf_hyperg_U_e(const double a, const double b, const double x, gsl_sf_result * result)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
gsl_sf_result_e10 re = {0, 0, 0};
|
|
Packit |
67cb25 |
int stat_U = gsl_sf_hyperg_U_e10_e(a, b, x, &re);
|
|
Packit |
67cb25 |
int stat_c = gsl_sf_result_smash_e(&re, result);
|
|
Packit |
67cb25 |
return GSL_ERROR_SELECT_2(stat_c, stat_U);
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include "eval.h"
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double gsl_sf_hyperg_U_int(const int a, const int b, const double x)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
EVAL_RESULT(gsl_sf_hyperg_U_int_e(a, b, x, &result));
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
double gsl_sf_hyperg_U(const double a, const double b, const double x)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
EVAL_RESULT(gsl_sf_hyperg_U_e(a, b, x, &result));
|
|
Packit |
67cb25 |
}
|