1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.distribution.continuous;
23
24 import java.io.Serializable;
25
26 import org.hipparchus.analysis.UnivariateFunction;
27 import org.hipparchus.analysis.solvers.UnivariateSolverUtils;
28 import org.hipparchus.distribution.RealDistribution;
29 import org.hipparchus.exception.LocalizedCoreFormats;
30 import org.hipparchus.exception.MathIllegalArgumentException;
31 import org.hipparchus.util.FastMath;
32 import org.hipparchus.util.MathUtils;
33
34
35
36
37
38
39
40 public abstract class AbstractRealDistribution
41 implements RealDistribution, Serializable {
42
43
44 protected static final double DEFAULT_SOLVER_ABSOLUTE_ACCURACY = 1e-9;
45
46 private static final long serialVersionUID = 20160320L;
47
48
49 private final double solverAbsoluteAccuracy;
50
51
52
53
54
55 protected AbstractRealDistribution(double solverAbsoluteAccuracy) {
56 this.solverAbsoluteAccuracy = solverAbsoluteAccuracy;
57 }
58
59
60
61
62 protected AbstractRealDistribution() {
63 this.solverAbsoluteAccuracy = DEFAULT_SOLVER_ABSOLUTE_ACCURACY;
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 @Override
80 public double probability(double x0,
81 double x1) throws MathIllegalArgumentException {
82 if (x0 > x1) {
83 throw new MathIllegalArgumentException(LocalizedCoreFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT,
84 x0, x1, true);
85 }
86 return cumulativeProbability(x1) - cumulativeProbability(x0);
87 }
88
89
90
91
92
93
94
95
96
97
98 @Override
99 public double inverseCumulativeProbability(final double p) throws MathIllegalArgumentException {
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 MathUtils.checkRangeInclusive(p, 0, 1);
130
131 double lowerBound = getSupportLowerBound();
132 if (p == 0.0) {
133 return lowerBound;
134 }
135
136 double upperBound = getSupportUpperBound();
137 if (p == 1.0) {
138 return upperBound;
139 }
140
141 final double mu = getNumericalMean();
142 final double sig = FastMath.sqrt(getNumericalVariance());
143 final boolean chebyshevApplies;
144 chebyshevApplies = !(Double.isInfinite(mu) || Double.isNaN(mu) ||
145 Double.isInfinite(sig) || Double.isNaN(sig));
146
147 if (lowerBound == Double.NEGATIVE_INFINITY) {
148 if (chebyshevApplies) {
149 lowerBound = mu - sig * FastMath.sqrt((1. - p) / p);
150 } else {
151 lowerBound = -1.0;
152 while (cumulativeProbability(lowerBound) >= p) {
153 lowerBound *= 2.0;
154 }
155 }
156 }
157
158 if (upperBound == Double.POSITIVE_INFINITY) {
159 if (chebyshevApplies) {
160 upperBound = mu + sig * FastMath.sqrt(p / (1. - p));
161 } else {
162 upperBound = 1.0;
163 while (cumulativeProbability(upperBound) < p) {
164 upperBound *= 2.0;
165 }
166 }
167 }
168
169 final UnivariateFunction toSolve = new UnivariateFunction() {
170
171 @Override
172 public double value(final double x) {
173 return cumulativeProbability(x) - p;
174 }
175 };
176
177 double x = UnivariateSolverUtils.solve(toSolve,
178 lowerBound,
179 upperBound,
180 getSolverAbsoluteAccuracy());
181
182 if (!isSupportConnected()) {
183
184 final double dx = getSolverAbsoluteAccuracy();
185 if (x - dx >= getSupportLowerBound()) {
186 double px = cumulativeProbability(x);
187 if (cumulativeProbability(x - dx) == px) {
188 upperBound = x;
189 while (upperBound - lowerBound > dx) {
190 final double midPoint = 0.5 * (lowerBound + upperBound);
191 if (cumulativeProbability(midPoint) < px) {
192 lowerBound = midPoint;
193 } else {
194 upperBound = midPoint;
195 }
196 }
197 return upperBound;
198 }
199 }
200 }
201 return x;
202 }
203
204
205
206
207
208
209
210
211 protected double getSolverAbsoluteAccuracy() {
212 return solverAbsoluteAccuracy;
213 }
214
215
216
217
218
219
220 @Override
221 public double logDensity(double x) {
222 return FastMath.log(density(x));
223 }
224 }
225