Blame specfunc/hyperg_U.c

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
}