/// Beta function. Beta(x,y)=Beta(y,x)=integral(0 to 1) {t^(x-1)*(1-t)^(y-1) dt}. /// Also, Beta(x,y) = gamma(x)*gamma(y)/gamma(x+y). /// @param x first argument /// @param y second argument /// @return beta(x,y) /// @throw if either input argument is <= 0 double beta(const double& x, const double& y) throw(Exception) { try { return ::exp(lnGamma(x) + lnGamma(y) - lnGamma(x+y)); } catch(Exception& e) { GPSTK_RETHROW(e); } }
/// Incomplete beta function I_x(a,b), 0<=x<=1, a,b>0 /// I sub x (a,b) = (1/beta(a,b)) integral (0 to x) { t^(a-1)*(1-t)^(b-1)dt } /// @param double x input value, 0 <= x <= 1 /// @param double a input value, a > 0 /// @param double b input value, b > 0 /// @return Incomplete beta function I_x(a,b) double incompleteBeta(const double& x, const double& a, const double& b) throw(Exception) { if(x < 0 || x > 1) { Exception e("Invalid x argument in incompleteBeta()"); GPSTK_THROW(e); } if(a <= 0 || b <= 0) { Exception e("Non-positive argument in incompleteBeta()"); GPSTK_THROW(e); } if(x == 0) return 0.0; if(x == 1) return 1.0; try { double factor = ::exp(lnGamma(a+b) - lnGamma(a) - lnGamma(b) + a * ::log(x) + b * ::log(1.0-x)); if(x < (a+1.0)/(a+b+2.0)) return factor*cfIBeta(x,a,b)/a; else return 1.0-factor*cfIBeta(1.0-x,b,a)/b; } catch(Exception& e) { e.addText("Called by incompleteBeta()"); GPSTK_RETHROW(e); } }
/// Beta function. Beta(x,y)=Beta(y,x)=integral(0 to 1) {t^(x-1)*(1-t)^(y-1) dt}. /// Also, Beta(x,y) = gamma(x)*gamma(y)/gamma(x+y). /// @param double x first argument /// @param double y second argument /// @return beta(x,y) /// @throw if either input argument is <= 0 double beta(const double& x, const double& y) throw(Exception) { try { return ::exp(lnGamma(x) + lnGamma(y) - lnGamma(x+y)); } catch(Exception& e) { e.addText("Called by beta(x,y)"); GPSTK_RETHROW(e); } }
/// Gamma(x) the gamma function for positive argument. /// Gamma(x) = integral(0 to inf) { t^(x-1) exp(-t) dt } /// @param x argument, x must be > 0 /// @return double Gamma(x), the gamma function of x. /// @throw if the input argument is <= 0 double Gamma(const double& x) throw(Exception) { try { return ::exp(lnGamma(double(x))); } catch(Exception& e) { GPSTK_RETHROW(e); } }
double lnFactorial(const int x) { static const int maxTableSize = 128; static double lut[maxTableSize]; // static arrays are automatically // initialized with zero if (x < 0) { return NaN; } if (x <= 1) { return 0.0; } if (x < maxTableSize) { return (lut[static_cast<int>(x)] != 0) ? lut[static_cast<int>(x)] : (lut[static_cast<int>(x)] = lnGamma(double(static_cast<int>(x)+1))); } return lnGamma(double(static_cast<int>(x)+1)); }
/// ln of Factorial of an integer, returned as a double. /// @param n argument, n must be >= 0 /// @return ln(n!) or natural log of factorial(n), as a double /// @throw if the input argument is < 0 double lnFactorial(const int& n) throw(Exception) { try { if(n < 0) GPSTK_THROW(Exception("Negative argument")); if(n <= 1) return 0.0; return lnGamma(double(n+1)); } catch(Exception& e) { GPSTK_RETHROW(e); } }
/// ln of Factorial of an integer, returned as a double. /// @param n int argument, n must be >= 0 /// @return ln(n!) or natural log of factorial(n), as a double /// @throw if the input argument is < 0 double lnFactorial(const int& n) throw(Exception) { if(n < 0) { Exception e("Negative argument in lnFactorial()"); GPSTK_THROW(e); } if(n <= 1) return 0.0; return lnGamma(double(n+1)); }
double factorial(const int x) { static const int maxLut = 34; static const double lut[] = {1.0, // 0! 1.0, // 1! 2.0, // 2! 6.0, // 3! 24.0, // 4! 120.0, // 5! 720.0, // 6! 5040.0, // 7! 40320.0, // 8! 362880.0, // 9! 3628800.0, // 10! 39916800.0, // 11! 479001600.0, // 12! 6227020800.0, // 13! 87178291200.0, // 14! 1307674368000.0, // 15! 20922789888000.0, // 16! 355687428096000.0, // 17! 6402373705728000.0, // 18! 121645100408832000.0, // 19! 2432902008176640000.0, // 20! 51090942171709440000.0, // 21! 1124000727777607680000.0, // 22! 25852016738884976640000.0, // 23! 620448401733239439360000.0, // 24! 15511210043330985984000000.0, // 25! 403291461126605635584000000.0, // 26! 10888869450418352160768000000.0, // 27! 304888344611713860501504000000.0, // 28! 8841761993739701954543616000000.0, // 29! 265252859812191058636308480000000.0, // 30! 8222838654177922817725562880000000.0, // 31! 263130836933693530167218012160000000.0, // 32! 8683317618811886495518194401280000000.0 // 33! }; if (x < 0) { return NaN; } if (x>=maxLut) { return exp(lnGamma(static_cast<double>(x+1))); } return lut[static_cast<int>(x)]; }
/// Factorial of an integer, returned as a double. /// @param n int argument, n must be >= 0 /// @return n! or factorial(n), as a double /// @throw if the input argument is < 0 double factorial(const int& n) throw(Exception) { if(n < 0) { Exception e("Negative argument in factorial()"); GPSTK_THROW(e); } if(n > 32) return ::exp(lnGamma(double(n+1))); static double store[33] = { 1.0, 1.0, 2.0, 6.0, 24.0, 120.0 }; static int nstore=5; while(nstore < n) { int i = nstore++; store[nstore] = store[i] * nstore; } return store[n]; }