1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.statistics.distribution;
18
19
20
21
22
23
24
25
26
27 final class SaddlePointExpansionUtils {
28
29 private static final double TWO_PI = 2 * Math.PI;
30
31 private static final double ONE_TENTH = 0.1;
32
33 private static final int STIRLING_ERROR_THRESHOLD = 15;
34
35
36 private static final double[] EXACT_STIRLING_ERRORS = {
37 0.0,
38 0.1534264097200273452913848,
39 0.0810614667953272582196702,
40 0.0548141210519176538961390,
41 0.0413406959554092940938221,
42 0.03316287351993628748511048,
43 0.02767792568499833914878929,
44 0.02374616365629749597132920,
45 0.02079067210376509311152277,
46 0.01848845053267318523077934,
47 0.01664469118982119216319487,
48 0.01513497322191737887351255,
49 0.01387612882307074799874573,
50 0.01281046524292022692424986,
51 0.01189670994589177009505572,
52 0.01110455975820691732662991,
53 0.010411265261972096497478567,
54 0.009799416126158803298389475,
55 0.009255462182712732917728637,
56 0.008768700134139385462952823,
57 0.008330563433362871256469318,
58 0.007934114564314020547248100,
59 0.007573675487951840794972024,
60 0.007244554301320383179543912,
61 0.006942840107209529865664152,
62 0.006665247032707682442354394,
63 0.006408994188004207068439631,
64 0.006171712263039457647532867,
65 0.005951370112758847735624416,
66 0.005746216513010115682023589,
67 0.005554733551962801371038690
68 };
69
70
71
72
73 private SaddlePointExpansionUtils() {}
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 static double getStirlingError(int z) {
93 if (z <= STIRLING_ERROR_THRESHOLD) {
94 return EXACT_STIRLING_ERRORS[2 * z];
95 }
96 final double z2 = (double) z * z;
97 return (0.083333333333333333333 -
98 (0.00277777777777777777778 -
99 (0.00079365079365079365079365 -
100 (0.000595238095238095238095238 -
101 0.0008417508417508417508417508 /
102 z2) / z2) / z2) / z2) / z;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 static double getDeviancePart(int x, double mu) {
124 if (Math.abs(x - mu) < 0.1 * (x + mu)) {
125 final double d = x - mu;
126 double v = d / (x + mu);
127 double s1 = v * d;
128 double s = Double.NaN;
129 double ej = 2.0 * x * v;
130 v *= v;
131 int j = 1;
132 while (s1 != s) {
133 s = s1;
134 ej *= v;
135 s1 = s + ej / ((j * 2) + 1);
136 ++j;
137 }
138 return s1;
139 } else if (x == 0) {
140 return mu;
141 }
142 return x * Math.log(x / mu) + mu - x;
143 }
144
145
146
147
148
149
150
151
152
153
154
155 static double logBinomialProbability(int x, int n, double p, double q) {
156 if (x == 0) {
157 if (p < ONE_TENTH) {
158
159 return 0.0 - getDeviancePart(n, n * q) - n * p;
160 } else if (n == 0) {
161 return 0;
162 }
163 return n * Math.log(q);
164 } else if (x == n) {
165 if (q < ONE_TENTH) {
166
167 return 0.0 - getDeviancePart(n, n * p) - n * q;
168 }
169 return n * Math.log(p);
170 }
171 final int nMx = n - x;
172 final double ret = getStirlingError(n) - getStirlingError(x) -
173 getStirlingError(nMx) - getDeviancePart(x, n * p) -
174 getDeviancePart(nMx, n * q);
175 final double f = (TWO_PI * x * nMx) / n;
176 return -0.5 * Math.log(f) + ret;
177 }
178 }