25package umontreal.ssj.util;
27import cern.jet.math.Bessel;
36 private static final double XBIG = 40.0;
37 private static final double SQPI_2 = 0.88622692545275801;
38 private static final double RACPI = 1.77245385090551602729;
39 private static final double LOG_SQPI_2 = -0.1207822376352453;
40 private static final double LOG4 = 1.3862943611198906;
41 private static final double LOG_PI = 1.14472988584940017413;
42 private static final double PIsur2 = Math.PI / 2.0;
44 private static final double UNSIX = 1.0 / 6.0;
45 private static final double QUARAN = 1.0 / 42.0;
46 private static final double UNTRENTE = 1.0 / 30.0;
47 private static final double DTIERS = 2.0 / 3.0;
48 private static final double CTIERS = 5.0 / 3.0;
49 private static final double STIERS = 7.0 / 3.0;
50 private static final double QTIERS = 14.0 / 3.0;
52 private static final double[] AERF = {
54 1.4831105640848036E0, -3.0107107338659494E-1, 6.8994830689831566E-2, -1.3916271264722188E-2,
55 2.4207995224334637E-3, -3.6586396858480864E-4, 4.8620984432319048E-5, -5.7492565580356848E-6,
56 6.1132435784347647E-7, -5.8991015312958434E-8, 5.2070090920686482E-9, -4.2329758799655433E-10,
57 3.188113506649174974E-11, -2.2361550188326843E-12, 1.46732984799108492E-13, -9.044001985381747E-15,
58 5.25481371547092E-16 };
60 private static final double[] AERFC = {
62 6.10143081923200418E-1, -4.34841272712577472E-1, 1.76351193643605501E-1, -6.07107956092494149E-2,
63 1.77120689956941145E-2, -4.32111938556729382E-3, 8.54216676887098679E-4, -1.27155090609162743E-4,
64 1.12481672436711895E-5, 3.13063885421820973E-7, -2.70988068537762022E-7, 3.07376227014076884E-8,
65 2.51562038481762294E-9, -1.02892992132031913E-9, 2.99440521199499394E-11, 2.60517896872669363E-11,
66 -2.63483992417196939E-12, -6.43404509890636443E-13, 1.12457401801663447E-13, 1.7281533389986098E-14,
67 -4.2641016949424E-15, -5.4537197788E-16, 1.5869760776E-16, 2.08998378E-17, -0.5900E-17 };
69 private static final double[] AlnGamma = {
75 0.52854303698223459887, 0.54987644612141411418, 0.02073980061613665136, -0.00056916770421543842,
76 0.00002324587210400169, -0.00000113060758570393, 0.00000006065653098948, -0.00000000346284357770,
77 0.00000000020624998806, -0.00000000001266351116, 0.00000000000079531007, -0.00000000000005082077,
78 0.00000000000000329187, -0.00000000000000021556, 0.00000000000000001424, -0.00000000000000000095 };
90 public static final double DBL_EPSILON = 2.2204460492503131e-16;
113 public static final double DBL_MIN = 2.2250738585072014e-308;
128 public static final double EBASE = 2.7182818284590452354;
133 public static final double EULER = 0.57721566490153286;
138 public static final double RAC2 = 1.41421356237309504880;
143 public static final double IRAC2 = 0.70710678118654752440;
148 public static final double LN2 = 0.69314718055994530941;
153 public static final double ILN2 = 1.44269504088896340737;
170 public static final double TWOEXP[] = { 1.0, 2.0, 4.0, 8.0, 1.6e1, 3.2e1, 6.4e1, 1.28e2, 2.56e2, 5.12e2, 1.024e3,
171 2.048e3, 4.096e3, 8.192e3, 1.6384e4, 3.2768e4, 6.5536e4, 1.31072e5, 2.62144e5, 5.24288e5, 1.048576e6,
172 2.097152e6, 4.194304e6, 8.388608e6, 1.6777216e7, 3.3554432e7, 6.7108864e7, 1.34217728e8, 2.68435456e8,
173 5.36870912e8, 1.073741824e9, 2.147483648e9, 4.294967296e9, 8.589934592e9, 1.7179869184e10, 3.4359738368e10,
174 6.8719476736e10, 1.37438953472e11, 2.74877906944e11, 5.49755813888e11, 1.099511627776e12, 2.199023255552e12,
175 4.398046511104e12, 8.796093022208e12, 1.7592186044416e13, 3.5184372088832e13, 7.0368744177664e13,
176 1.40737488355328e14, 2.81474976710656e14, 5.62949953421312e14, 1.125899906842624e15, 2.251799813685248e15,
177 4.503599627370496e15, 9.007199254740992e15, 1.8014398509481984e16, 3.6028797018963968e16,
178 7.2057594037927936e16, 1.44115188075855872e17, 2.88230376151711744e17, 5.76460752303423488e17,
179 1.152921504606846976e18, 2.305843009213693952e18, 4.611686018427387904e18, 9.223372036854775808e18,
180 1.8446744073709551616e19 };
186 public static final double TEN_NEG_POW[] = { 1.0, 1.0e-1, 1.0e-2, 1.0e-3, 1.0e-4, 1.0e-5, 1.0e-6, 1.0e-7, 1.0e-8,
187 1.0e-9, 1.0e-10, 1.0e-11, 1.0e-12, 1.0e-13, 1.0e-14, 1.0e-15, 1.0e-16 };
200 public static int gcd(
int x,
int y) {
221 public static long gcd(
long x,
long y) {
244 final int NLIM = 100;
246 if (s == 0 || s == n)
249 System.err.println(
"combination: s < 0");
253 System.err.println(
"combination: s > n");
261 for (i = 1; i <= s; i++) {
262 Res *= (double) (Diff + i) / (double) i;
267 return Math.exp(Res);
281 if (s == 0 || s == n)
284 return Double.NEGATIVE_INFINITY;
298 throw new IllegalArgumentException(
"factorial: n < 0");
300 for (
int j = 2; j <= n; j++)
329 throw new IllegalArgumentException(
"lnFactorial: n < 0");
331 if (n == 0 || n == 1)
336 for (
int i = 2; i <= n; i++) {
342 double x = (double) (n + 1);
343 double y = 1.0 / (x * x);
344 double z = ((-(5.95238095238E-4 * y) + 7.936500793651E-4) * y - 2.7777777777778E-3) * y + 8.3333333333333E-2;
345 z = ((x - 0.5) * Math.log(x) - x) + 9.1893853320467E-1 + z / x;
358 throw new IllegalArgumentException(
"factoPow : n < 0");
359 double res = 1.0 / n;
360 for (
int i = 2; i <= n; i++) {
361 res *= (double) i / n;
379 double[][] M =
new double[m + 1][n + 1];
381 for (i = 0; i <= m; i++)
382 for (j = 0; j <= n; j++)
386 for (j = 1; j <= n; j++) {
393 for (i = 1; i <= k; i++)
394 M[i][j] = (
double) i * M[i][j - 1] + M[i - 1][j - 1];
405 public static double log2(
double x) {
406 return ILN2 * Math.log(x);
419 throw new IllegalArgumentException(
"lnGamma: x <= 0");
423 final double XLIM1 = 18.0;
424 final double DK2 = 0.91893853320467274177;
425 final double DK1 = 0.9574186990510627;
439 z = ((-(5.95238095238E-4 * y) + 7.936500793651E-4) * y - 2.7777777777778E-3) * y + 8.3333333333333E-2;
440 z = ((x - 0.5) * Math.log(x) - x) + DK2 + z / x;
443 }
else if (x > 4.0) {
447 for (i = 3; i < k; i++)
452 return Double.MAX_VALUE;
458 for (i = 2; i >= k; i--)
465 z =
evalCheby(AlnGamma, N, 2.0 * z - 1.0);
475 public static double lnBeta(
double lam,
double nu) {
476 if (0. == lam || 0. == nu)
477 return Double.POSITIVE_INFINITY;
478 if (Double.isInfinite(lam) || Double.isInfinite(nu))
479 return Double.NEGATIVE_INFINITY;
488 final double C7[][] = {
489 { 1.3524999667726346383e4, 4.5285601699547289655e4, 4.5135168469736662555e4, 1.8529011818582610168e4,
490 3.3291525149406935532e3, 2.4068032474357201831e2, 5.1577892000139084710, 6.2283506918984745826e-3 },
491 { 6.9389111753763444376e-7, 1.9768574263046736421e4, 4.1255160835353832333e4, 2.9390287119932681918e4,
492 9.0819666074855170271e3, 1.2447477785670856039e3, 6.7429129516378593773e1, 1.0 } };
493 final double C4[][] = {
494 { -2.728175751315296783e-15, -6.481571237661965099e-1, -4.486165439180193579, -7.016772277667586642,
495 -2.129404451310105168 },
496 { 7.777885485229616042, 5.461177381032150702e1, 8.929207004818613702e1, 3.227034937911433614e1, 1.0 } };
505 double x2 = 1.0 / (x * x);
506 for (
int j = 4; j >= 0; j--) {
507 prodPj = prodPj * x2 + C4[0][j];
508 prodQj = prodQj * x2 + C4[1][j];
510 digX = Math.log(x) - (0.5 / x) + (prodPj / prodQj);
512 }
else if (x >= 0.5) {
513 final double X0 = 1.46163214496836234126;
514 for (
int j = 7; j >= 0; j--) {
515 prodPj = x * prodPj + C7[0][j];
516 prodQj = x * prodQj + C7[1][j];
518 digX = (x - X0) * (prodPj / prodQj);
521 double f = (1.0 - x) - Math.floor(1.0 - x);
522 digX =
digamma(1.0 - x) + Math.PI / Math.tan(Math.PI * f);
538 y = (1.0 - x) - Math.floor(1.0 - x);
539 sum = Math.PI / Math.sin(Math.PI * y);
540 return sum * sum -
trigamma(1.0 - x);
546 sum = 1.0 + y * (1.0 / 6.0 - y * (1.0 / 30.0 - y * (1.0 / 42.0 - 1.0 / 30.0 * y)));
557 for (i = 3; i < p; i++)
558 sum -= 1.0 / ((y + i) * (y + i));
561 for (i = 2; i >= p; i--)
562 sum += 1.0 / ((y + i) * (y + i));
571 final double A[] = { 2.0 * 0.33483869791094938576, -0.05518748204873009463, 0.00451019073601150186,
572 -0.00036570588830372083, 2.943462746822336e-5, -2.35277681515061e-6, 1.8685317663281e-7, -1.475072018379e-8,
573 1.15799333714e-9, -9.043917904e-11, 7.029627e-12, -5.4398873e-13, 0.4192525e-13, -3.21903e-15, 0.2463e-15,
574 -1.878e-17, 0., 0. };
589 y = (1.0 - x) - Math.floor(1.0 - x);
590 sum = Math.PI / Math.sin(Math.PI * y);
591 return 2.0 * Math.cos(Math.PI * y) * sum * sum * sum +
tetragamma(1.0 - x);
597 sum = y * (0.5 - y * (1.0 / 6.0 - y * (1.0 / 6.0 - y * (0.3 - 5.0 / 6.0 * y))));
598 sum += 1.0 + 1.0 / x;
608 for (i = 3; i < p; i++)
609 sum += 1.0 / ((y + i) * (y + i) * (y + i));
612 for (i = 2; i >= p; i--)
613 sum -= 1.0 / ((y + i) * (y + i) * (y + i));
622 final double A[] = { -0.11259293534547383037 * 2.0, 0.03655700174282094137, -0.00443594249602728223,
623 0.00047547585472892648, -4.747183638263232e-5, 4.52181523735268e-6, -4.1630007962011e-7, 3.733899816535e-8,
624 -3.27991447410e-9, 2.8321137682e-10, -2.410402848e-11, 2.02629690e-12, -1.6852418e-13, 1.388481e-14,
625 -1.13451e-15, 9.201e-17, -7.41e-18, 5.9e-19, -5.0e-20 };
637 throw new IllegalArgumentException(
"gammaRatioHalf: x <= 0");
649 final double EPSILON = 1.0e-15;
653 while (term > EPSILON * sum) {
654 term *= (i - 1.5) * (i - 1.5) / (i * (x + i - 1.5));
658 return Math.sqrt((x - 0.5) * sum);
663 double y = 1.0 / (8.0 * x);
664 sum = 1.0 + y * (-1.0 + y * (0.5 + y * (2.5 - y * (2.625 + 49.875 * y))));
665 return sum * Math.sqrt(x);
682 for (
int i = 0; i < n; i++) {
697 throw new IllegalArgumentException(
"n < 1");
709 throw new IllegalArgumentException(
"n <= 0");
718 return 1.0 / k + 2.0 *
harmonic(k - 1);
736 double kLR = (double) t;
741 throw new IllegalArgumentException(
"volumeSphere: p < 0");
743 if (Math.abs(p - pLR) <= EPS) {
751 return Math.pow(Math.PI, kLR / 2.0) / (double)
factorial(t / 2);
760 return Math.exp(Vol);
782 return x * (x - 1.0) + UNSIX;
784 return ((2.0 * x - 3.0) * x + 1.0) * x * 0.5;
786 return ((x - 2.0) * x + 1.0) * x * x - UNTRENTE;
788 return (((x - 2.5) * x + CTIERS) * x * x - UNSIX) * x;
790 return (((x - 3.0) * x + 2.5) * x * x - 0.5) * x * x + QUARAN;
792 return ((((x - 3.5) * x + 3.5) * x * x - 7.0 / 6.0) * x * x + UNSIX) * x;
794 return ((((x - 4.0) * x + QTIERS) * x * x - STIERS) * x * x + DTIERS) * x * x - UNTRENTE;
796 throw new IllegalArgumentException(
"n must be <= 8");
812 public static double evalCheby(
double a[],
int n,
double x) {
813 if (Math.abs(x) > 1.0)
814 System.err.println(
"Chebychev polynomial evaluated " +
"at x outside [-1, 1]");
815 final double xx = 2.0 * x;
819 for (
int j = n; j >= 0; j--) {
822 b0 = (xx * b1 - b2) + a[j];
824 return (b0 - b2) / 2.0;
839 if (x > 1.0 || x < 0.0)
840 System.err.println(
"Shifted Chebychev polynomial evaluated " +
"at x outside [0, 1]");
841 final double xx = 2.0 * (2.0 * x - 1.0);
845 for (
int j = n; j >= 0; j--) {
848 b0 = xx * b1 - b2 + a[j];
850 return (b0 - b2) / 2.0;
867 return Double.MIN_VALUE;
870 final double c[] = { 32177591145.0, 2099336339520.0, 16281990144000.0, 34611957596160.0, 26640289628160.0,
871 7901666082816.0, 755914244096.0 };
873 final double b[] = { 75293843625.0, 2891283595200.0, 18691126272000.0, 36807140966400.0, 27348959232000.0,
874 7972533043200.0, 755914244096.0 };
884 for (
int j = DEG; j >= 1; j--) {
885 B = B * x + b[j - 1];
886 C = C * x + c[j - 1];
888 double Res1 = Math.sqrt(Math.PI / (2.0 * x)) * Math.exp(-x) * (C / B);
896 double rac = Math.pow(x / 2.0, 0.25);
897 double Res = (((xx / 1386.0 + 1.0 / 42.0) * xx + 1.0 / 3.0) * xx + 1.0) / (1.225416702465177 * rac);
898 double temp = (((xx / 3510.0 + 1.0 / 90.0) * xx + 0.2) * xx + 1.0) * rac / 0.906402477055477;
899 Res = Math.PI * (Res - temp) /
RAC2;
910 if (Double.isNaN(x) || Double.isNaN(y))
913 double sum = 1 + 3.0 / (8.0 * y) - 15.0 / (128.0 * y * y) + 105.0 / (1024.0 * y * y * y);
914 return Math.sqrt(PIsur2 / y) * sum * Math.exp(x - y);
915 }
else if (Math.abs(x) > 500.0) {
916 double b = Bessel.k1(y);
917 return Math.exp(x + Math.log(b));
919 return Math.exp(x) * Bessel.k1(y);
930 public static double erf(
double x) {
938 return 1.0 -
erfc(x);
940 double t = 0.5 * x * x - 1.0;
941 double y = Num.evalCheby(AERF, 16, t);
953 public static double erfc(
double x) {
957 return 2.0 -
erfc(-x);
960 double t = (x - 3.75) / (x + 3.75);
961 double y = Num.evalCheby(AERFC, 24, t);
962 y *= Math.exp(-x * x);
966 private static final double[] InvP1 = { 0.160304955844066229311e2, -0.90784959262960326650e2,
967 0.18644914861620987391e3, -0.16900142734642382420e3, 0.6545466284794487048e2, -0.864213011587247794e1,
968 0.1760587821390590 };
970 private static final double[] InvQ1 = { 0.147806470715138316110e2, -0.91374167024260313396e2,
971 0.21015790486205317714e3, -0.22210254121855132366e3, 0.10760453916055123830e3, -0.206010730328265443e2,
974 private static final double[] InvP2 = { -0.152389263440726128e-1, 0.3444556924136125216, -0.29344398672542478687e1,
975 0.11763505705217827302e2, -0.22655292823101104193e2, 0.19121334396580330163e2, -0.5478927619598318769e1,
976 0.237516689024448000 };
978 private static final double[] InvQ2 = { -0.108465169602059954e-1, 0.2610628885843078511, -0.24068318104393757995e1,
979 0.10695129973387014469e2, -0.23716715521596581025e2, 0.24640158943917284883e2, -0.10014376349783070835e2,
982 private static final double[] InvP3 = { 0.56451977709864482298e-4, 0.53504147487893013765e-2, 0.12969550099727352403,
983 0.10426158549298266122e1, 0.28302677901754489974e1, 0.26255672879448072726e1, 0.20789742630174917228e1,
984 0.72718806231556811306, 0.66816807711804989575e-1, -0.17791004575111759979e-1, 0.22419563223346345828e-2 };
986 private static final double[] InvQ3 = { 0.56451699862760651514e-4, 0.53505587067930653953e-2, 0.12986615416911646934,
987 0.10542932232626491195e1, 0.30379331173522206237e1, 0.37631168536405028901e1, 0.38782858277042011263e1,
988 0.20372431817412177929e1, 0.1e1 };
1005 throw new IllegalArgumentException(
"u is not in [-1, 1]");
1007 return Double.POSITIVE_INFINITY;
1017 }
else if (u <= 0.9375) {
1018 t = u * u - 0.87890625;
1024 t = 1.0 / Math.sqrt(-Math.log(1.0 - u));
1043 if (Double.isNaN(u))
1046 throw new IllegalArgumentException(
"u is not in [0, 2]");
1052 return Double.POSITIVE_INFINITY;
1057 x = Math.sqrt(-Math.log(RACPI * u));
1058 x = Math.sqrt(-Math.log(RACPI * u * x));
1061 for (
int i = 0; i < 3; ++i) {
1062 w = -2.0 * Math.exp(-x * x) / RACPI;
1063 x += (u -
erfc(x)) / w;
This class provides miscellaneous functions that are hard to classify.
static double evalPoly(int n, double[] X, double[] C, double z)
Given , and as described in interpol(n, X, Y, C), this function returns the value of the interpolat...
static double sumKahan(double[] A, int n)
Implementation of the Kahan summation algorithm.
static final double RAC2
The value of .
static final int DBL_DIG
Number of decimal digits of precision in a double.
static double erfInv(double u)
Returns the value of erf , the inverse of the error function.
static final double DBL_MIN
Smallest normalized positive floating-point double.
static final double LN_DBL_MIN
Natural logarithm of DBL_MIN.
static final double EULER
The Euler-Mascheroni constant.
static double lnGamma(double x)
Returns the natural logarithm of the gamma function evaluated at x.
static double gammaRatioHalf(double x)
Returns the value of the ratio of two gamma functions.
static double[][] calcMatStirling(int m, int n)
Computes and returns the Stirling numbers of the second kind.
static double erf(double x)
Returns the value of erf( ), the error function.
static double harmonic(long n)
Computes the -th harmonic number .
static double lnFactorial(long n)
Returns the value of , the natural logarithm of factorial .
static double factoPow(int n)
Returns the value of .
static double volumeSphere(double p, int t)
Returns the volume of a sphere of radius 1 in dimensions using the norm .
static double log2(double x)
Returns x .
static final double DBL_EPSILON
Difference between 1.0 and the smallest double greater than 1.0.
static final double ILN2
The values of .
static final int DBL_MIN_EXP
Smallest int such that is representable (approximately) as a normalised double.
static double evalCheby(double a[], int n, double x)
Evaluates a series of Chebyshev polynomials at over the basic interval , using the method of Clensh...
static final int DBL_MAX_10_EXP
Largest int such that is representable (approximately) as a double.
static double bernoulliPoly(int n, double x)
Evaluates the Bernoulli polynomial of degree at.
static double trigamma(double x)
Returns the value of the trigamma function , the derivative of the digamma function,...
static double evalChebyStar(double a[], int n, double x)
Evaluates a series of shifted Chebyshev polynomials at.
static long gcd(long x, long y)
Returns the greatest common divisor (gcd) of and .
static final double IRAC2
The value of .
static double lnFactorial(int n)
Returns the value of , the natural logarithm of factorial .
static int gcd(int x, int y)
Returns the greatest common divisor (gcd) of and .
static final double TEN_NEG_POW[]
Contains the precomputed negative powers of 10.
static final double MAXTWOEXP
Powers of 2 up to MAXTWOEXP are stored exactly in the array TWOEXP.
static final int DBL_MAX_EXP
Largest int such that is representable (approximately) as a double.
static double factorial(int n)
Returns the value of .
static double erfc(double x)
Returns the value of erfc( ), the complementary error function.
static final double EBASE
The constant .
static double erfcInv(double u)
Returns the value of erfc , the inverse of the complementary error function.
static double combination(int n, int s)
Returns the value of , the number of different combinations of objects amongst.
static double lnCombination(int n, int s)
Returns the natural logarithm of.
static double tetragamma(double x)
Returns the value of the tetragamma function , the second derivative of the digamma function,...
static final double TWOEXP[]
Contains the precomputed positive powers of 2.
static double expBesselK1(double x, double y)
Returns the value of , where is the modified Bessel function of the second kind of order 1.
static double besselK025(double x)
Returns the value of , where.
static double lnBeta(double lam, double nu)
Computes the natural logarithm of the Beta function .
static double digamma(double x)
Returns the value of the logarithmic derivative of the Gamma function .
static final double LN2
The values of .
static double harmonic2(long n)
Computes the sum.
static final double MAXINTDOUBLE
Largest integer such that any integer is represented exactly as a double.