1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.distribution.continuous;
24
25 import org.hipparchus.exception.LocalizedCoreFormats;
26 import org.hipparchus.exception.MathIllegalArgumentException;
27 import org.hipparchus.special.Beta;
28 import org.hipparchus.util.FastMath;
29
30
31
32
33
34
35
36 public class FDistribution extends AbstractRealDistribution {
37
38 private static final long serialVersionUID = 20160320L;
39
40 private final double numeratorDegreesOfFreedom;
41
42 private final double denominatorDegreesOfFreedom;
43
44 private final double numericalVariance;
45
46
47
48
49
50
51
52
53
54
55 public FDistribution(double numeratorDegreesOfFreedom,
56 double denominatorDegreesOfFreedom)
57 throws MathIllegalArgumentException {
58 this(numeratorDegreesOfFreedom, denominatorDegreesOfFreedom,
59 DEFAULT_SOLVER_ABSOLUTE_ACCURACY);
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73 public FDistribution(double numeratorDegreesOfFreedom,
74 double denominatorDegreesOfFreedom,
75 double inverseCumAccuracy)
76 throws MathIllegalArgumentException {
77 super(inverseCumAccuracy);
78
79 if (numeratorDegreesOfFreedom <= 0) {
80 throw new MathIllegalArgumentException(LocalizedCoreFormats.DEGREES_OF_FREEDOM,
81 numeratorDegreesOfFreedom);
82 }
83 if (denominatorDegreesOfFreedom <= 0) {
84 throw new MathIllegalArgumentException(LocalizedCoreFormats.DEGREES_OF_FREEDOM,
85 denominatorDegreesOfFreedom);
86 }
87 this.numeratorDegreesOfFreedom = numeratorDegreesOfFreedom;
88 this.denominatorDegreesOfFreedom = denominatorDegreesOfFreedom;
89 this.numericalVariance = calculateNumericalVariance();
90 }
91
92
93
94
95 @Override
96 public double density(double x) {
97 return FastMath.exp(logDensity(x));
98 }
99
100
101 @Override
102 public double logDensity(double x) {
103 final double nhalf = numeratorDegreesOfFreedom / 2;
104 final double mhalf = denominatorDegreesOfFreedom / 2;
105 final double logx = FastMath.log(x);
106 final double logn = FastMath.log(numeratorDegreesOfFreedom);
107 final double logm = FastMath.log(denominatorDegreesOfFreedom);
108 final double lognxm = FastMath.log(numeratorDegreesOfFreedom * x +
109 denominatorDegreesOfFreedom);
110 return nhalf * logn + nhalf * logx - logx +
111 mhalf * logm - nhalf * lognxm - mhalf * lognxm -
112 Beta.logBeta(nhalf, mhalf);
113 }
114
115
116
117
118
119
120
121
122
123
124
125
126 @Override
127 public double cumulativeProbability(double x) {
128 double ret;
129 if (x <= 0) {
130 ret = 0;
131 } else {
132 double n = numeratorDegreesOfFreedom;
133 double m = denominatorDegreesOfFreedom;
134
135 ret = Beta.regularizedBeta((n * x) / (m + n * x),
136 0.5 * n,
137 0.5 * m);
138 }
139 return ret;
140 }
141
142
143
144
145
146
147 public double getNumeratorDegreesOfFreedom() {
148 return numeratorDegreesOfFreedom;
149 }
150
151
152
153
154
155
156 public double getDenominatorDegreesOfFreedom() {
157 return denominatorDegreesOfFreedom;
158 }
159
160
161
162
163
164
165
166
167
168
169 @Override
170 public double getNumericalMean() {
171 final double denominatorDF = getDenominatorDegreesOfFreedom();
172
173 if (denominatorDF > 2) {
174 return denominatorDF / (denominatorDF - 2);
175 }
176
177 return Double.NaN;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 @Override
194 public double getNumericalVariance() {
195 return numericalVariance;
196 }
197
198
199
200
201
202
203 private double calculateNumericalVariance() {
204 final double denominatorDF = getDenominatorDegreesOfFreedom();
205
206 if (denominatorDF > 4) {
207 final double numeratorDF = getNumeratorDegreesOfFreedom();
208 final double denomDFMinusTwo = denominatorDF - 2;
209
210 return ( 2 * (denominatorDF * denominatorDF) * (numeratorDF + denominatorDF - 2) ) /
211 ( (numeratorDF * (denomDFMinusTwo * denomDFMinusTwo) * (denominatorDF - 4)) );
212 }
213
214 return Double.NaN;
215 }
216
217
218
219
220
221
222
223
224 @Override
225 public double getSupportLowerBound() {
226 return 0;
227 }
228
229
230
231
232
233
234
235
236
237 @Override
238 public double getSupportUpperBound() {
239 return Double.POSITIVE_INFINITY;
240 }
241
242
243
244
245
246
247
248
249 @Override
250 public boolean isSupportConnected() {
251 return true;
252 }
253 }