1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.statistics.distribution;
19
20 import java.util.stream.Stream;
21 import org.apache.commons.math3.util.MathArrays;
22 import org.junit.jupiter.api.Assertions;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.params.ParameterizedTest;
25 import org.junit.jupiter.params.provider.Arguments;
26 import org.junit.jupiter.params.provider.CsvSource;
27 import org.junit.jupiter.params.provider.MethodSource;
28
29
30
31
32
33 class UniformDiscreteDistributionTest extends BaseDiscreteDistributionTest {
34 @Override
35 DiscreteDistribution makeDistribution(Object... parameters) {
36 final int lower = (Integer) parameters[0];
37 final int upper = (Integer) parameters[1];
38 return UniformDiscreteDistribution.of(lower, upper);
39 }
40
41
42 @Override
43 Object[][] makeInvalidParameters() {
44 return new Object[][] {
45
46 {1, 0},
47 {3, 2},
48 };
49 }
50
51 @Override
52 String[] getParameterNames() {
53 return new String[] {"SupportLowerBound", "SupportUpperBound"};
54 }
55
56 @Override
57 protected double getRelativeTolerance() {
58
59 return 2 * RELATIVE_EPS;
60 }
61
62
63
64 @ParameterizedTest
65 @MethodSource
66 void testAdditionalMoments(int lower, int upper, double mean, double variance) {
67 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
68 testMoments(dist, mean, variance, DoubleTolerances.equals());
69 }
70
71 static Stream<Arguments> testAdditionalMoments() {
72 return Stream.of(
73 Arguments.of(0, 5, 2.5, 35 / 12.0),
74 Arguments.of(0, 1, 0.5, 3 / 12.0)
75 );
76 }
77
78
79 @Test
80 void testLargeRangeSubtractionOverflow() {
81 final int hi = Integer.MAX_VALUE / 2 + 10;
82 final int lower = -hi;
83 final int upper = hi - 1;
84
85
86 Assertions.assertTrue(upper - lower < 0);
87
88 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
89
90 Assertions.assertEquals(0.5 / hi, dist.probability(123456));
91 Assertions.assertEquals(0.5, dist.cumulativeProbability(-1));
92
93 Assertions.assertEquals((Math.pow(2d * hi, 2) - 1) / 12, dist.getVariance());
94 }
95
96
97 @Test
98 void testLargeRangeAdditionOverflow() {
99 final int hi = Integer.MAX_VALUE / 2 + 10;
100 final int lower = hi - 1;
101 final int upper = hi + 1;
102
103
104 Assertions.assertTrue(lower + upper < 0);
105
106 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
107
108 Assertions.assertEquals(1d / 3d, dist.probability(hi));
109 Assertions.assertEquals(2d / 3d, dist.cumulativeProbability(hi));
110
111 Assertions.assertEquals(hi, dist.getMean());
112 }
113
114
115
116
117
118 @ParameterizedTest
119 @CsvSource(value = {
120
121 "-2147483648, -2147483648",
122 "-2147483648, -2147483647",
123 "-2147483648, -2147483646",
124 "-2147483648, -2147483638",
125 "2147483647, 2147483647",
126 "2147483646, 2147483647",
127 "2147483645, 2147483647",
128 "2147483637, 2147483647",
129
130 "3, 40",
131 "71, 201",
132 "223, 267",
133 "45, 125",
134 "53, 81",
135
136 "48, 247",
137 "141, 222",
138 "106, 223",
139 "156, 201",
140 "86, 265",
141 })
142 void testInverseCDF(int lower, int upper) {
143 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
144 final int[] x = MathArrays.sequence(upper - lower, lower, 1);
145 testCumulativeProbabilityInverseMapping(dist, x);
146 }
147
148
149
150
151
152 @ParameterizedTest
153 @CsvSource(value = {
154
155 "-2147483648, -2147483648",
156 "-2147483648, -2147483647",
157 "-2147483648, -2147483646",
158 "-2147483648, -2147483638",
159 "2147483647, 2147483647",
160 "2147483646, 2147483647",
161 "2147483645, 2147483647",
162 "2147483637, 2147483647",
163
164 "52, 91",
165 "81, 106",
166 "79, 268",
167 "54, 249",
168 "189, 267",
169
170 "105, 279",
171 "42, 261",
172 "37, 133",
173 "59, 214",
174 "33, 118",
175 })
176 void testInverseSF(int lower, int upper) {
177 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
178 final int[] x = MathArrays.sequence(upper - lower, lower, 1);
179 testSurvivalProbabilityInverseMapping(dist, x);
180 }
181
182
183
184
185
186
187
188 @ParameterizedTest
189 @CsvSource(value = {
190
191 "-2147483648, -2147483648",
192 "-2147483648, -2147483647",
193 "-2147483648, -2147483646",
194 "-2147483648, -2147483638",
195 "2147483647, 2147483647",
196 "2147483646, 2147483647",
197 "2147483645, 2147483647",
198 "2147483637, 2147483647",
199
200 "-10, 2",
201 "10, 16",
202 "-20, -10",
203
204 "-10, 3",
205 "10, 17",
206 "-20, -9",
207
208 "-2147483648, 2147483647",
209 "-2147483648, 1263781682",
210 "-2147483648, 1781682",
211 "-2147483648, -231781682",
212 "-1324234584, 2147483647",
213 "-324234584, 2147483647",
214 "6234584, 2147483647",
215 "-1256362376, 125637",
216 "-62378468, 1325657374",
217 })
218 void testProbabilityRange(int lower, int upper) {
219 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(lower, upper);
220 final double r = (double) upper - lower + 1;
221 final long stride = r < 20 ? 1 : (long) (r / 20);
222 for (long x0 = lower; x0 <= upper; x0 += stride) {
223 for (long x1 = x0; x1 <= upper; x1 += stride) {
224 final double p = (x1 - x0) / r;
225 Assertions.assertEquals(p, dist.probability((int) x0, (int) x1));
226 }
227 }
228 }
229
230 @Test
231 void testProbabilityRangeEdgeCases() {
232 final UniformDiscreteDistribution dist = UniformDiscreteDistribution.of(3, 5);
233
234 Assertions.assertThrows(DistributionException.class, () -> dist.probability(4, 3));
235
236
237 Assertions.assertEquals(0, dist.probability(5, 6));
238 Assertions.assertEquals(0, dist.probability(15, 16));
239
240 Assertions.assertEquals(0, dist.probability(-3, 1));
241
242
243 Assertions.assertEquals(0, dist.probability(3, 3));
244 Assertions.assertEquals(0, dist.probability(4, 4));
245 Assertions.assertEquals(0, dist.probability(5, 5));
246 Assertions.assertEquals(0, dist.probability(6, 6));
247
248
249 Assertions.assertEquals(1.0 / 3, dist.probability(3, 4));
250 Assertions.assertEquals(1.0 / 3, dist.probability(4, 5));
251
252
253 Assertions.assertEquals(1, dist.probability(2, 6));
254 Assertions.assertEquals(2.0 / 3, dist.probability(3, 6));
255 Assertions.assertEquals(1.0 / 3, dist.probability(4, 6));
256 Assertions.assertEquals(0, dist.probability(5, 6));
257
258
259 Assertions.assertEquals(0, dist.probability(-2, 2));
260 Assertions.assertEquals(1.0 / 3, dist.probability(-2, 3));
261 Assertions.assertEquals(2.0 / 3, dist.probability(-2, 4));
262 Assertions.assertEquals(1.0, dist.probability(-2, 5));
263
264
265 Assertions.assertEquals(1, dist.probability(-2, 6));
266 }
267 }