SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
Num.java
1/*
2 * Class: Num
3 * Description: Provides methods to compute some special functions
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.util;
26
27import cern.jet.math.Bessel;
28
35public class Num {
36 private static final double XBIG = 40.0;
37 private static final double SQPI_2 = 0.88622692545275801; // Sqrt(Pi)/2
38 private static final double RACPI = 1.77245385090551602729; // sqrt(Pi)
39 private static final double LOG_SQPI_2 = -0.1207822376352453; // Ln(Sqrt(Pi)/2)
40 private static final double LOG4 = 1.3862943611198906; // Ln(4)
41 private static final double LOG_PI = 1.14472988584940017413; // Ln(Pi)
42 private static final double PIsur2 = Math.PI / 2.0;
43
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;
51
52 private static final double[] AERF = {
53 // used in erf(x)
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 };
59
60 private static final double[] AERFC = {
61 // used in erfc(x)
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 };
68
69 private static final double[] AlnGamma = {
70 /*
71 * Chebyshev coefficients for lnGamma (x + 3), 0 <= x <= 1 In Yudell Luke: The
72 * special functions and their approximations, Vol. II, Academic Press, p. 301,
73 * 1969. There is an error in the additive constant in the formula: (Ln (2)).
74 */
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 };
79
80 private Num() {
81 }
82
86
90 public static final double DBL_EPSILON = 2.2204460492503131e-16;
91
96 public static final int DBL_MAX_EXP = 1024;
97
102 public static final int DBL_MIN_EXP = -1021;
103
108 public static final int DBL_MAX_10_EXP = 308;
109
113 public static final double DBL_MIN = 2.2250738585072014e-308;
114
118 public static final double LN_DBL_MIN = -708.3964185322641;
119
123 public static final int DBL_DIG = 15;
124
128 public static final double EBASE = 2.7182818284590452354;
129
133 public static final double EULER = 0.57721566490153286;
134
138 public static final double RAC2 = 1.41421356237309504880;
139
143 public static final double IRAC2 = 0.70710678118654752440;
144
148 public static final double LN2 = 0.69314718055994530941;
149
153 public static final double ILN2 = 1.44269504088896340737;
154
159 public static final double MAXINTDOUBLE = 9007199254740992.0;
160
164 public static final double MAXTWOEXP = 64;
165
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 };
181
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 };
188
192
200 public static int gcd(int x, int y) {
201 if (x < 0)
202 x = -x;
203 if (y < 0)
204 y = -y;
205 int r;
206 while (y != 0) {
207 r = x % y;
208 x = y;
209 y = r;
210 }
211 return x;
212 }
213
221 public static long gcd(long x, long y) {
222 if (x < 0)
223 x = -x;
224 if (y < 0)
225 y = -y;
226 long r;
227 while (y != 0) {
228 r = x % y;
229 x = y;
230 y = r;
231 }
232 return x;
233 }
234
243 public static double combination(int n, int s) {
244 final int NLIM = 100; // pour eviter les debordements
245 int i;
246 if (s == 0 || s == n)
247 return 1;
248 if (s < 0) {
249 System.err.println("combination: s < 0");
250 return 0;
251 }
252 if (s > n) {
253 System.err.println("combination: s > n");
254 return 0;
255 }
256 if (s > (n / 2))
257 s = n - s;
258 if (n <= NLIM) {
259 double Res = 1.0;
260 int Diff = n - s;
261 for (i = 1; i <= s; i++) {
262 Res *= (double) (Diff + i) / (double) i;
263 }
264 return Res;
265 } else {
266 double Res = (lnFactorial(n) - lnFactorial(s)) - lnFactorial(n - s);
267 return Math.exp(Res);
268 }
269 }
270
280 public static double lnCombination(int n, int s) {
281 if (s == 0 || s == n)
282 return 0;
283 if (s < 0 || s > n)
284 return Double.NEGATIVE_INFINITY;
285
286 double res = (lnFactorial(n) - lnFactorial(s)) - lnFactorial(n - s);
287 return res;
288 }
289
296 public static double factorial(int n) {
297 if (n < 0)
298 throw new IllegalArgumentException("factorial: n < 0");
299 double T = 1;
300 for (int j = 2; j <= n; j++)
301 T *= j;
302 return T;
303 }
304
313 public static double lnFactorial(int n) {
314 return lnFactorial((long) n);
315 }
316
325 public static double lnFactorial(long n) {
326 final int NLIM = 14;
327
328 if (n < 0)
329 throw new IllegalArgumentException("lnFactorial: n < 0");
330
331 if (n == 0 || n == 1)
332 return 0.0;
333 if (n <= NLIM) {
334 long z = 1;
335 long x = 1;
336 for (int i = 2; i <= n; i++) {
337 ++x;
338 z *= x;
339 }
340 return Math.log(z);
341 } else {
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;
346 return z;
347 }
348 }
349
356 public static double factoPow(int n) {
357 if (n < 0)
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;
362 }
363 return res;
364 }
365
377 public static double[][] calcMatStirling(int m, int n) {
378 int i, j, k;
379 double[][] M = new double[m + 1][n + 1];
380
381 for (i = 0; i <= m; i++)
382 for (j = 0; j <= n; j++)
383 M[i][j] = 0.0;
384
385 M[0][0] = 1.0;
386 for (j = 1; j <= n; j++) {
387 M[0][j] = 0.0;
388 if (j <= m) {
389 k = j - 1;
390 M[j][j] = 1.0;
391 } else
392 k = m;
393 for (i = 1; i <= k; i++)
394 M[i][j] = (double) i * M[i][j - 1] + M[i - 1][j - 1];
395 }
396 return M;
397 }
398
405 public static double log2(double x) {
406 return ILN2 * Math.log(x);
407 }
408
417 public static double lnGamma(double x) {
418 if (x <= 0.0)
419 throw new IllegalArgumentException("lnGamma: x <= 0");
420 if (Double.isNaN(x))
421 return Double.NaN;
422 final double XLIMBIG = 1.0 / DBL_EPSILON;
423 final double XLIM1 = 18.0;
424 final double DK2 = 0.91893853320467274177; // Ln (sqrt (2 Pi))
425 final double DK1 = 0.9574186990510627;
426 final int N = 15; // Degree of Chebyshev polynomial
427 double y, z;
428 int i, k;
429
430 /*
431 * if (x <= 0.0) { double f = (1.0 - x) - Math.floor (1.0 - x); return LOG_PI -
432 * lnGamma (1.0 - x) - Math.log (Math.sin (Math.PI * f)); }
433 */
434 if (x > XLIM1) {
435 if (x > XLIMBIG)
436 y = 0.0;
437 else
438 y = 1.0 / (x * x);
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;
441 return z;
442
443 } else if (x > 4.0) {
444 k = (int) x;
445 z = x - k;
446 y = 1.0;
447 for (i = 3; i < k; i++)
448 y *= z + i;
449 y = Math.log(y);
450
451 } else if (x <= 0.0)
452 return Double.MAX_VALUE;
453
454 else if (x < 3.0) {
455 k = (int) x;
456 z = x - k;
457 y = 1.0;
458 for (i = 2; i >= k; i--)
459 y *= z + i;
460 y = -Math.log(y);
461 } else { // 3 <= x <= 4
462 z = x - 3.0;
463 y = 0.0;
464 }
465 z = evalCheby(AlnGamma, N, 2.0 * z - 1.0);
466 return z + DK1 + y;
467 }
468
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;
480 return lnGamma(lam) + lnGamma(nu) - lnGamma(lam + nu);
481 }
482
487 public static double digamma(double x) {
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 } };
497
498 if (Double.isNaN(x))
499 return Double.NaN;
500 double prodPj = 0.0;
501 double prodQj = 0.0;
502 double digX = 0.0;
503
504 if (x >= 3.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];
509 }
510 digX = Math.log(x) - (0.5 / x) + (prodPj / prodQj);
511
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];
517 }
518 digX = (x - X0) * (prodPj / prodQj);
519
520 } else {
521 double f = (1.0 - x) - Math.floor(1.0 - x);
522 digX = digamma(1.0 - x) + Math.PI / Math.tan(Math.PI * f);
523 }
524
525 return digX;
526 }
527
532 public static double trigamma(double x) {
533 double y, sum;
534 if (Double.isNaN(x))
535 return Double.NaN;
536
537 if (x < 0.5) {
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);
541 }
542
543 if (x >= 40.0) {
544 // Asymptotic series
545 y = 1.0 / (x * 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)));
547 sum += 0.5 / x;
548 return sum / x;
549 }
550
551 int i;
552 int p = (int) x;
553 y = x - p;
554 sum = 0.0;
555
556 if (p > 3) {
557 for (i = 3; i < p; i++)
558 sum -= 1.0 / ((y + i) * (y + i));
559
560 } else if (p < 3) {
561 for (i = 2; i >= p; i--)
562 sum += 1.0 / ((y + i) * (y + i));
563 }
564
565 /*
566 * Chebyshev coefficients for trigamma (x + 3), 0 <= x <= 1. In Yudell Luke: The
567 * special functions and their approximations, Vol. II, Academic Press, p. 301,
568 * 1969.
569 */
570 final int N = 15;
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. };
575
576 return sum + evalChebyStar(A, N, y);
577 }
578
583 public static double tetragamma(double x) {
584 double y, sum;
585 if (Double.isNaN(x))
586 return Double.NaN;
587
588 if (x < 0.5) {
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);
592 }
593
594 if (x >= 20.0) {
595 // Asymptotic series
596 y = 1.0 / (x * 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;
599 return -sum * y;
600 }
601
602 int i;
603 int p = (int) x;
604 y = x - p;
605 sum = 0.0;
606
607 if (p > 3) {
608 for (i = 3; i < p; i++)
609 sum += 1.0 / ((y + i) * (y + i) * (y + i));
610
611 } else if (p < 3) {
612 for (i = 2; i >= p; i--)
613 sum -= 1.0 / ((y + i) * (y + i) * (y + i));
614 }
615
616 /*
617 * Chebyshev coefficients for tetragamma (x + 3), 0 <= x <= 1. In Yudell Luke:
618 * The special functions and their approximations, Vol. II, Academic Press, p.
619 * 301, 1969.
620 */
621 final int N = 16;
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 };
626
627 return 2.0 * sum + evalChebyStar(A, N, y);
628 }
629
635 public static double gammaRatioHalf(double x) {
636 if (x <= 0.0)
637 throw new IllegalArgumentException("gammaRatioHalf: x <= 0");
638 if (Double.isNaN(x))
639 return Double.NaN;
640
641 if (x <= 10.0) {
642 double y = lnGamma(x + 0.5) - lnGamma(x);
643 return Math.exp(y);
644 }
645
646 double sum;
647 if (x <= 300.0) {
648 // The sum converges very slowly for small x, but faster as x increases
649 final double EPSILON = 1.0e-15;
650 double term = 1.0;
651 sum = 1.0;
652 int i = 1;
653 while (term > EPSILON * sum) {
654 term *= (i - 1.5) * (i - 1.5) / (i * (x + i - 1.5));
655 sum += term;
656 i++;
657 }
658 return Math.sqrt((x - 0.5) * sum);
659 }
660
661 // Asymptotic series for Gamma(x + 0.5) / (Gamma(x) * Sqrt(x))
662 // Comparer la vitesse de l'asymptotique avec la somme ci-dessus !!!
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);
666 }
667
675 public static double sumKahan(double[] A, int n) {
676 if (A.length < n)
677 n = A.length;
678 double sum = 0;
679 double c = 0;
680 double y, t;
681
682 for (int i = 0; i < n; i++) {
683 y = A[i] - c;
684 t = sum + y;
685 c = (t - sum) - y;
686 sum = t;
687 }
688
689 return sum;
690 }
691
695 public static double harmonic(long n) {
696 if (n < 1)
697 throw new IllegalArgumentException("n < 1");
698 return digamma(n + 1) + EULER;
699 }
700
707 public static double harmonic2(long n) {
708 if (n <= 0)
709 throw new IllegalArgumentException("n <= 0");
710 if (1 == n)
711 return 0.0;
712 if (2 == n)
713 return 1.0;
714
715 long k = n / 2;
716 if ((n & 1) == 1)
717 return 2.0 * harmonic(k); // n odd
718 return 1.0 / k + 2.0 * harmonic(k - 1); // n even
719 }
720
733 public static double volumeSphere(double p, int t) {
734 final double EPS = 2.0 * DBL_EPSILON;
735 int pLR = (int) p;
736 double kLR = (double) t;
737 double Vol;
738 int s;
739
740 if (p < 0)
741 throw new IllegalArgumentException("volumeSphere: p < 0");
742
743 if (Math.abs(p - pLR) <= EPS) {
744 switch (pLR) {
745 case 0:
746 return TWOEXP[t];
747 case 1:
748 return TWOEXP[t] / (double) factorial(t);
749 case 2:
750 if ((t % 2) == 0)
751 return Math.pow(Math.PI, kLR / 2.0) / (double) factorial(t / 2);
752 else {
753 s = (t + 1) / 2;
754 return Math.pow(Math.PI, (double) s - 1.0) * factorial(s) * TWOEXP[2 * s] / (double) factorial(2 * s);
755 }
756 default:
757 }
758 }
759 Vol = kLR * (LN2 + lnGamma(1.0 + 1.0 / p)) - lnGamma(1.0 + kLR / p);
760 return Math.exp(Vol);
761 }
762
775 public static double bernoulliPoly(int n, double x) {
776 switch (n) {
777 case 0:
778 return 1.0;
779 case 1:
780 return x - 0.5;
781 case 2:
782 return x * (x - 1.0) + UNSIX;
783 case 3:
784 return ((2.0 * x - 3.0) * x + 1.0) * x * 0.5;
785 case 4:
786 return ((x - 2.0) * x + 1.0) * x * x - UNTRENTE;
787 case 5:
788 return (((x - 2.5) * x + CTIERS) * x * x - UNSIX) * x;
789 case 6:
790 return (((x - 3.0) * x + 2.5) * x * x - 0.5) * x * x + QUARAN;
791 case 7:
792 return ((((x - 3.5) * x + 3.5) * x * x - 7.0 / 6.0) * x * x + UNSIX) * x;
793 case 8:
794 return ((((x - 4.0) * x + QTIERS) * x * x - STIERS) * x * x + DTIERS) * x * x - UNTRENTE;
795 default:
796 throw new IllegalArgumentException("n must be <= 8");
797 }
798 // return 0;
799 }
800
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;
816 double b0 = 0.0;
817 double b1 = 0.0;
818 double b2 = 0.0;
819 for (int j = n; j >= 0; j--) {
820 b2 = b1;
821 b1 = b0;
822 b0 = (xx * b1 - b2) + a[j];
823 }
824 return (b0 - b2) / 2.0;
825 }
826
838 public static double evalChebyStar(double a[], int n, double x) {
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);
842 double b0 = 0.0;
843 double b1 = 0.0;
844 double b2 = 0.0;
845 for (int j = n; j >= 0; j--) {
846 b2 = b1;
847 b1 = b0;
848 b0 = xx * b1 - b2 + a[j];
849 }
850 return (b0 - b2) / 2.0;
851 }
852
863 public static double besselK025(double x) {
864 if (Double.isNaN(x))
865 return Double.NaN;
866 if (x < 1.E-300)
867 return Double.MIN_VALUE;
868
869 final int DEG = 6;
870 final double c[] = { 32177591145.0, 2099336339520.0, 16281990144000.0, 34611957596160.0, 26640289628160.0,
871 7901666082816.0, 755914244096.0 };
872
873 final double b[] = { 75293843625.0, 2891283595200.0, 18691126272000.0, 36807140966400.0, 27348959232000.0,
874 7972533043200.0, 755914244096.0 };
875
876 /*------------------------------------------------------------------
877 * x > 0.6 => approximation asymptotique rationnelle dans Luke:
878 * Yudell L.Luke "Mathematical functions and their approximations",
879 * Academic Press Inc. New York, 1975, p.371
880 *------------------------------------------------------------------*/
881 if (x >= 0.6) {
882 double B = b[DEG];
883 double C = c[DEG];
884 for (int j = DEG; j >= 1; j--) {
885 B = B * x + b[j - 1];
886 C = C * x + c[j - 1];
887 }
888 double Res1 = Math.sqrt(Math.PI / (2.0 * x)) * Math.exp(-x) * (C / B);
889 return Res1;
890 }
891
892 /*------------------------------------------------------------------
893 * x < 0.6 => la serie de K_{1/4} = Pi/Sqrt (2) [I_{-1/4} - I_{1/4}]
894 *------------------------------------------------------------------*/
895 double xx = x * x;
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;
900 return Res;
901 }
902
909 public static double expBesselK1(double x, double y) {
910 if (Double.isNaN(x) || Double.isNaN(y))
911 return Double.NaN;
912 if (y > 500.0) {
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));
918 } else {
919 return Math.exp(x) * Bessel.k1(y);
920 }
921 }
922
930 public static double erf(double x) {
931 if (Double.isNaN(x))
932 return Double.NaN;
933 if (x < 0.0)
934 return -erf(-x);
935 if (x >= 6.0)
936 return 1.0;
937 if (x >= 2.0)
938 return 1.0 - erfc(x);
939
940 double t = 0.5 * x * x - 1.0;
941 double y = Num.evalCheby(AERF, 16, t);
942 return x * y;
943 }
944
953 public static double erfc(double x) {
954 if (Double.isNaN(x))
955 return Double.NaN;
956 if (x < 0.0)
957 return 2.0 - erfc(-x);
958 if (x >= XBIG)
959 return 0.0;
960 double t = (x - 3.75) / (x + 3.75);
961 double y = Num.evalCheby(AERFC, 24, t);
962 y *= Math.exp(-x * x);
963 return y;
964 }
965
966 private static final double[] InvP1 = { 0.160304955844066229311e2, -0.90784959262960326650e2,
967 0.18644914861620987391e3, -0.16900142734642382420e3, 0.6545466284794487048e2, -0.864213011587247794e1,
968 0.1760587821390590 };
969
970 private static final double[] InvQ1 = { 0.147806470715138316110e2, -0.91374167024260313396e2,
971 0.21015790486205317714e3, -0.22210254121855132366e3, 0.10760453916055123830e3, -0.206010730328265443e2,
972 0.1e1 };
973
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 };
977
978 private static final double[] InvQ2 = { -0.108465169602059954e-1, 0.2610628885843078511, -0.24068318104393757995e1,
979 0.10695129973387014469e2, -0.23716715521596581025e2, 0.24640158943917284883e2, -0.10014376349783070835e2,
980 0.1e1 };
981
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 };
985
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 };
989
998 public static double erfInv(double u) {
999 if (Double.isNaN(u))
1000 return Double.NaN;
1001 if (u < 0.0)
1002 return -erfInv(-u);
1003
1004 if (u > 1.0)
1005 throw new IllegalArgumentException("u is not in [-1, 1]");
1006 if (u >= 1.0)
1007 return Double.POSITIVE_INFINITY;
1008
1009 double t, z, v, w;
1010
1011 if (u <= 0.75) {
1012 t = u * u - 0.5625;
1013 v = Misc.evalPoly(InvP1, 6, t);
1014 w = Misc.evalPoly(InvQ1, 6, t);
1015 z = (v / w) * u;
1016
1017 } else if (u <= 0.9375) {
1018 t = u * u - 0.87890625;
1019 v = Misc.evalPoly(InvP2, 7, t);
1020 w = Misc.evalPoly(InvQ2, 7, t);
1021 z = (v / w) * u;
1022
1023 } else {
1024 t = 1.0 / Math.sqrt(-Math.log(1.0 - u));
1025 v = Misc.evalPoly(InvP3, 10, t);
1026 w = Misc.evalPoly(InvQ3, 8, t);
1027 z = (v / w) / t;
1028 }
1029
1030 return z;
1031 }
1032
1042 public static double erfcInv(double u) {
1043 if (Double.isNaN(u))
1044 return Double.NaN;
1045 if (u < 0 || u > 2)
1046 throw new IllegalArgumentException("u is not in [0, 2]");
1047
1048 if (u > 0.005)
1049 return erfInv(1.0 - u);
1050
1051 if (u <= 0)
1052 return Double.POSITIVE_INFINITY;
1053
1054 double x, w;
1055
1056 // first term of asymptotic series
1057 x = Math.sqrt(-Math.log(RACPI * u));
1058 x = Math.sqrt(-Math.log(RACPI * u * x));
1059
1060 // Newton's method
1061 for (int i = 0; i < 3; ++i) {
1062 w = -2.0 * Math.exp(-x * x) / RACPI;
1063 x += (u - erfc(x)) / w;
1064 }
1065 return x;
1066 }
1067
1068}
This class provides miscellaneous functions that are hard to classify.
Definition Misc.java:33
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...
Definition Misc.java:248
static double sumKahan(double[] A, int n)
Implementation of the Kahan summation algorithm.
Definition Num.java:675
static final double RAC2
The value of .
Definition Num.java:138
static final int DBL_DIG
Number of decimal digits of precision in a double.
Definition Num.java:123
static double erfInv(double u)
Returns the value of erf , the inverse of the error function.
Definition Num.java:998
static final double DBL_MIN
Smallest normalized positive floating-point double.
Definition Num.java:113
static final double LN_DBL_MIN
Natural logarithm of DBL_MIN.
Definition Num.java:118
static final double EULER
The Euler-Mascheroni constant.
Definition Num.java:133
static double lnGamma(double x)
Returns the natural logarithm of the gamma function evaluated at x.
Definition Num.java:417
static double gammaRatioHalf(double x)
Returns the value of the ratio of two gamma functions.
Definition Num.java:635
static double[][] calcMatStirling(int m, int n)
Computes and returns the Stirling numbers of the second kind.
Definition Num.java:377
static double erf(double x)
Returns the value of erf( ), the error function.
Definition Num.java:930
static double harmonic(long n)
Computes the -th harmonic number .
Definition Num.java:695
static double lnFactorial(long n)
Returns the value of , the natural logarithm of factorial .
Definition Num.java:325
static double factoPow(int n)
Returns the value of .
Definition Num.java:356
static double volumeSphere(double p, int t)
Returns the volume of a sphere of radius 1 in dimensions using the norm .
Definition Num.java:733
static double log2(double x)
Returns x .
Definition Num.java:405
static final double DBL_EPSILON
Difference between 1.0 and the smallest double greater than 1.0.
Definition Num.java:90
static final double ILN2
The values of .
Definition Num.java:153
static final int DBL_MIN_EXP
Smallest int such that is representable (approximately) as a normalised double.
Definition Num.java:102
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...
Definition Num.java:812
static final int DBL_MAX_10_EXP
Largest int such that is representable (approximately) as a double.
Definition Num.java:108
static double bernoulliPoly(int n, double x)
Evaluates the Bernoulli polynomial of degree at.
Definition Num.java:775
static double trigamma(double x)
Returns the value of the trigamma function , the derivative of the digamma function,...
Definition Num.java:532
static double evalChebyStar(double a[], int n, double x)
Evaluates a series of shifted Chebyshev polynomials at.
Definition Num.java:838
static long gcd(long x, long y)
Returns the greatest common divisor (gcd) of and .
Definition Num.java:221
static final double IRAC2
The value of .
Definition Num.java:143
static double lnFactorial(int n)
Returns the value of , the natural logarithm of factorial .
Definition Num.java:313
static int gcd(int x, int y)
Returns the greatest common divisor (gcd) of and .
Definition Num.java:200
static final double TEN_NEG_POW[]
Contains the precomputed negative powers of 10.
Definition Num.java:186
static final double MAXTWOEXP
Powers of 2 up to MAXTWOEXP are stored exactly in the array TWOEXP.
Definition Num.java:164
static final int DBL_MAX_EXP
Largest int such that is representable (approximately) as a double.
Definition Num.java:96
static double factorial(int n)
Returns the value of .
Definition Num.java:296
static double erfc(double x)
Returns the value of erfc( ), the complementary error function.
Definition Num.java:953
static final double EBASE
The constant .
Definition Num.java:128
static double erfcInv(double u)
Returns the value of erfc , the inverse of the complementary error function.
Definition Num.java:1042
static double combination(int n, int s)
Returns the value of , the number of different combinations of objects amongst.
Definition Num.java:243
static double lnCombination(int n, int s)
Returns the natural logarithm of.
Definition Num.java:280
static double tetragamma(double x)
Returns the value of the tetragamma function , the second derivative of the digamma function,...
Definition Num.java:583
static final double TWOEXP[]
Contains the precomputed positive powers of 2.
Definition Num.java:170
static double expBesselK1(double x, double y)
Returns the value of , where is the modified Bessel function of the second kind of order 1.
Definition Num.java:909
static double besselK025(double x)
Returns the value of , where.
Definition Num.java:863
static double lnBeta(double lam, double nu)
Computes the natural logarithm of the Beta function .
Definition Num.java:475
static double digamma(double x)
Returns the value of the logarithmic derivative of the Gamma function .
Definition Num.java:487
static final double LN2
The values of .
Definition Num.java:148
static double harmonic2(long n)
Computes the sum.
Definition Num.java:707
static final double MAXINTDOUBLE
Largest integer such that any integer is represented exactly as a double.
Definition Num.java:159