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.stat;
23
24 import org.hipparchus.UnitTestUtils;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.exception.NullArgumentException;
27 import org.hipparchus.stat.descriptive.DescriptiveStatistics;
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.Precision;
30 import org.junit.jupiter.api.Test;
31
32 import static org.junit.jupiter.api.Assertions.assertEquals;
33 import static org.junit.jupiter.api.Assertions.assertTrue;
34 import static org.junit.jupiter.api.Assertions.fail;
35
36
37
38
39 final class StatUtilsTest {
40
41 private static final double ONE = 1;
42 private static final float TWO = 2;
43 private static final int THREE = 3;
44 private static final double MEAN = 2;
45 private static final double SUMSQ = 18;
46 private static final double SUM = 8;
47 private static final double VAR = 0.666666666666666666667;
48 private static final double MIN = 1;
49 private static final double MAX = 3;
50 private static final double TOLERANCE = 10E-15;
51 private static final double NAN = Double.NaN;
52
53
54 @Test
55 void testStats() {
56 double[] values = new double[] { ONE, TWO, TWO, THREE };
57 assertEquals(SUM, StatUtils.sum(values), TOLERANCE, "sum");
58 assertEquals(SUMSQ, StatUtils.sumSq(values), TOLERANCE, "sumsq");
59 assertEquals(VAR, StatUtils.variance(values), TOLERANCE, "var");
60 assertEquals(VAR, StatUtils.variance(values, MEAN), TOLERANCE, "var with mean");
61 assertEquals(MEAN, StatUtils.mean(values), TOLERANCE, "mean");
62 assertEquals(MIN, StatUtils.min(values), TOLERANCE, "min");
63 assertEquals(MAX, StatUtils.max(values), TOLERANCE, "max");
64 }
65
66 @Test
67 void testN0andN1Conditions() {
68 double[] values = new double[0];
69
70 assertTrue(Double.isNaN(StatUtils.mean(values)),
71 "Mean of n = 0 set should be NaN");
72 assertTrue(Double.isNaN(StatUtils.variance(values)),
73 "Variance of n = 0 set should be NaN");
74
75 values = new double[] { ONE };
76
77 assertEquals(ONE,
78 StatUtils.mean(values), 0.0, "Mean of n = 1 set should be value of single item n1");
79 assertEquals(0,
80 StatUtils.variance(values), 0.0, "Variance of n = 1 set should be zero");
81 }
82
83 @Test
84 void testArrayIndexConditions() {
85 double[] values = { 1.0, 2.0, 3.0, 4.0 };
86
87 assertEquals(5.0, StatUtils.sum(values, 1, 2), Double.MIN_VALUE, "Sum not expected");
88 assertEquals(3.0, StatUtils.sum(values, 0, 2), Double.MIN_VALUE, "Sum not expected");
89 assertEquals(7.0, StatUtils.sum(values, 2, 2), Double.MIN_VALUE, "Sum not expected");
90
91 try {
92 StatUtils.sum(values, 2, 3);
93 fail("Expected RuntimeException");
94 } catch (RuntimeException e) {
95
96 }
97
98 try {
99 StatUtils.sum(values, -1, 2);
100 fail("Expected RuntimeException");
101 } catch (RuntimeException e) {
102
103 }
104 }
105
106 @Test
107 void testSumSq() {
108 double[] x = null;
109
110
111 try {
112 StatUtils.sumSq(x);
113 fail("null is not a valid data array.");
114 } catch (NullArgumentException ex) {
115
116 }
117
118 try {
119 StatUtils.sumSq(x, 0, 4);
120 fail("null is not a valid data array.");
121 } catch (NullArgumentException ex) {
122
123 }
124
125
126 x = new double[] {};
127 UnitTestUtils.customAssertEquals(0, StatUtils.sumSq(x), TOLERANCE);
128 UnitTestUtils.customAssertEquals(0, StatUtils.sumSq(x, 0, 0), TOLERANCE);
129
130
131 x = new double[] {TWO};
132 UnitTestUtils.customAssertEquals(4, StatUtils.sumSq(x), TOLERANCE);
133 UnitTestUtils.customAssertEquals(4, StatUtils.sumSq(x, 0, 1), TOLERANCE);
134
135
136 x = new double[] {ONE, TWO, TWO, THREE};
137 UnitTestUtils.customAssertEquals(18, StatUtils.sumSq(x), TOLERANCE);
138 UnitTestUtils.customAssertEquals(8, StatUtils.sumSq(x, 1, 2), TOLERANCE);
139 }
140
141 @Test
142 void testProduct() {
143 double[] x = null;
144
145
146 try {
147 StatUtils.product(x);
148 fail("null is not a valid data array.");
149 } catch (NullArgumentException ex) {
150
151 }
152
153 try {
154 StatUtils.product(x, 0, 4);
155 fail("null is not a valid data array.");
156 } catch (NullArgumentException ex) {
157
158 }
159
160
161 x = new double[] {};
162 UnitTestUtils.customAssertEquals(1, StatUtils.product(x), TOLERANCE);
163 UnitTestUtils.customAssertEquals(1, StatUtils.product(x, 0, 0), TOLERANCE);
164
165
166 x = new double[] {TWO};
167 UnitTestUtils.customAssertEquals(TWO, StatUtils.product(x), TOLERANCE);
168 UnitTestUtils.customAssertEquals(TWO, StatUtils.product(x, 0, 1), TOLERANCE);
169
170
171 x = new double[] {ONE, TWO, TWO, THREE};
172 UnitTestUtils.customAssertEquals(12, StatUtils.product(x), TOLERANCE);
173 UnitTestUtils.customAssertEquals(4, StatUtils.product(x, 1, 2), TOLERANCE);
174 }
175
176 @Test
177 void testSumLog() {
178 double[] x = null;
179
180
181 try {
182 StatUtils.sumLog(x);
183 fail("null is not a valid data array.");
184 } catch (NullArgumentException ex) {
185
186 }
187
188 try {
189 StatUtils.sumLog(x, 0, 4);
190 fail("null is not a valid data array.");
191 } catch (NullArgumentException ex) {
192
193 }
194
195
196 x = new double[] {};
197 UnitTestUtils.customAssertEquals(0, StatUtils.sumLog(x), TOLERANCE);
198 UnitTestUtils.customAssertEquals(0, StatUtils.sumLog(x, 0, 0), TOLERANCE);
199
200
201 x = new double[] {TWO};
202 UnitTestUtils.customAssertEquals(FastMath.log(TWO), StatUtils.sumLog(x), TOLERANCE);
203 UnitTestUtils.customAssertEquals(FastMath.log(TWO), StatUtils.sumLog(x, 0, 1), TOLERANCE);
204
205
206 x = new double[] {ONE, TWO, TWO, THREE};
207 UnitTestUtils.customAssertEquals(FastMath.log(ONE) + 2.0 * FastMath.log(TWO) + FastMath.log(THREE), StatUtils.sumLog(x), TOLERANCE);
208 UnitTestUtils.customAssertEquals(2.0 * FastMath.log(TWO), StatUtils.sumLog(x, 1, 2), TOLERANCE);
209 }
210
211 @Test
212 void testMean() {
213 double[] x = null;
214
215 try {
216 StatUtils.mean(x, 0, 4);
217 fail("null is not a valid data array.");
218 } catch (NullArgumentException ex) {
219
220 }
221
222
223 x = new double[] {};
224 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.mean(x, 0, 0), TOLERANCE);
225
226
227 x = new double[] {TWO};
228 UnitTestUtils.customAssertEquals(TWO, StatUtils.mean(x, 0, 1), TOLERANCE);
229
230
231 x = new double[] {ONE, TWO, TWO, THREE};
232 UnitTestUtils.customAssertEquals(2.5, StatUtils.mean(x, 2, 2), TOLERANCE);
233 }
234
235 @Test
236 void testVariance() {
237 double[] x = null;
238
239 try {
240 StatUtils.variance(x, 0, 4);
241 fail("null is not a valid data array.");
242 } catch (NullArgumentException ex) {
243
244 }
245
246
247 x = new double[] {};
248 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.variance(x, 0, 0), TOLERANCE);
249
250
251 x = new double[] {TWO};
252 UnitTestUtils.customAssertEquals(0.0, StatUtils.variance(x, 0, 1), TOLERANCE);
253
254
255 x = new double[] {ONE, TWO, TWO, THREE};
256 UnitTestUtils.customAssertEquals(0.5, StatUtils.variance(x, 2, 2), TOLERANCE);
257
258
259 x = new double[] {ONE, TWO, TWO, THREE};
260 UnitTestUtils.customAssertEquals(0.5, StatUtils.variance(x, 2.5, 2, 2), TOLERANCE);
261 }
262
263 @Test
264 void testPopulationVariance() {
265 double[] x = null;
266
267 try {
268 StatUtils.variance(x, 0, 4);
269 fail("null is not a valid data array.");
270 } catch (NullArgumentException ex) {
271
272 }
273
274
275 x = new double[] {};
276 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.populationVariance(x, 0, 0), TOLERANCE);
277
278
279 x = new double[] {TWO};
280 UnitTestUtils.customAssertEquals(0.0, StatUtils.populationVariance(x, 0, 1), TOLERANCE);
281
282
283 x = new double[] {ONE, TWO, TWO, THREE};
284 UnitTestUtils.customAssertEquals(0.25, StatUtils.populationVariance(x, 0, 2), TOLERANCE);
285
286
287 x = new double[] {ONE, TWO, TWO, THREE};
288 UnitTestUtils.customAssertEquals(0.25, StatUtils.populationVariance(x, 2.5, 2, 2), TOLERANCE);
289 }
290
291 @Test
292 void testMax() {
293 double[] x = null;
294
295 try {
296 StatUtils.max(x, 0, 4);
297 fail("null is not a valid data array.");
298 } catch (NullArgumentException ex) {
299
300 }
301
302
303 x = new double[] {};
304 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.max(x, 0, 0), TOLERANCE);
305
306
307 x = new double[] {TWO};
308 UnitTestUtils.customAssertEquals(TWO, StatUtils.max(x, 0, 1), TOLERANCE);
309
310
311 x = new double[] {ONE, TWO, TWO, THREE};
312 UnitTestUtils.customAssertEquals(THREE, StatUtils.max(x, 1, 3), TOLERANCE);
313
314
315 x = new double[] {NAN, TWO, THREE};
316 UnitTestUtils.customAssertEquals(THREE, StatUtils.max(x), TOLERANCE);
317
318
319 x = new double[] {ONE, NAN, THREE};
320 UnitTestUtils.customAssertEquals(THREE, StatUtils.max(x), TOLERANCE);
321
322
323 x = new double[] {ONE, TWO, NAN};
324 UnitTestUtils.customAssertEquals(TWO, StatUtils.max(x), TOLERANCE);
325
326
327 x = new double[] {NAN, NAN, NAN};
328 UnitTestUtils.customAssertEquals(NAN, StatUtils.max(x), TOLERANCE);
329 }
330
331 @Test
332 void testMin() {
333 double[] x = null;
334
335 try {
336 StatUtils.min(x, 0, 4);
337 fail("null is not a valid data array.");
338 } catch (NullArgumentException ex) {
339
340 }
341
342
343 x = new double[] {};
344 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.min(x, 0, 0), TOLERANCE);
345
346
347 x = new double[] {TWO};
348 UnitTestUtils.customAssertEquals(TWO, StatUtils.min(x, 0, 1), TOLERANCE);
349
350
351 x = new double[] {ONE, TWO, TWO, THREE};
352 UnitTestUtils.customAssertEquals(TWO, StatUtils.min(x, 1, 3), TOLERANCE);
353
354
355 x = new double[] {NAN, TWO, THREE};
356 UnitTestUtils.customAssertEquals(TWO, StatUtils.min(x), TOLERANCE);
357
358
359 x = new double[] {ONE, NAN, THREE};
360 UnitTestUtils.customAssertEquals(ONE, StatUtils.min(x), TOLERANCE);
361
362
363 x = new double[] {ONE, TWO, NAN};
364 UnitTestUtils.customAssertEquals(ONE, StatUtils.min(x), TOLERANCE);
365
366
367 x = new double[] {NAN, NAN, NAN};
368 UnitTestUtils.customAssertEquals(NAN, StatUtils.min(x), TOLERANCE);
369 }
370
371 @Test
372 void testPercentile() {
373 double[] x = null;
374
375
376 try {
377 StatUtils.percentile(x, .25);
378 fail("null is not a valid data array.");
379 } catch (NullArgumentException ex) {
380
381 }
382
383 try {
384 StatUtils.percentile(x, 0, 4, 0.25);
385 fail("null is not a valid data array.");
386 } catch (NullArgumentException ex) {
387
388 }
389
390
391 x = new double[] {};
392 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.percentile(x, 25), TOLERANCE);
393 UnitTestUtils.customAssertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), TOLERANCE);
394
395
396 x = new double[] {TWO};
397 UnitTestUtils.customAssertEquals(TWO, StatUtils.percentile(x, 25), TOLERANCE);
398 UnitTestUtils.customAssertEquals(TWO, StatUtils.percentile(x, 0, 1, 25), TOLERANCE);
399
400
401 x = new double[] {ONE, TWO, TWO, THREE};
402 UnitTestUtils.customAssertEquals(2.5, StatUtils.percentile(x, 70), TOLERANCE);
403 UnitTestUtils.customAssertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), TOLERANCE);
404 }
405
406 @Test
407 void testDifferenceStats() {
408 double[] sample1 = {1d, 2d, 3d, 4d};
409 double[] sample2 = {1d, 3d, 4d, 2d};
410 double[] diff = {0d, -1d, -1d, 2d};
411 double[] small = {1d, 4d};
412 double meanDifference = StatUtils.meanDifference(sample1, sample2);
413 assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), TOLERANCE);
414 assertEquals(meanDifference, StatUtils.mean(diff), TOLERANCE);
415 assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference),
416 StatUtils.variance(diff), TOLERANCE);
417 try {
418 StatUtils.meanDifference(sample1, small);
419 fail("Expecting MathIllegalArgumentException");
420 } catch (MathIllegalArgumentException ex) {
421
422 }
423 try {
424 StatUtils.varianceDifference(sample1, small, meanDifference);
425 fail("Expecting MathIllegalArgumentException");
426 } catch (MathIllegalArgumentException ex) {
427
428 }
429 try {
430 double[] single = {1.0};
431 StatUtils.varianceDifference(single, single, meanDifference);
432 fail("Expecting MathIllegalArgumentException");
433 } catch (MathIllegalArgumentException ex) {
434
435 }
436 }
437
438 @Test
439 void testGeometricMean() {
440 double[] test = null;
441 try {
442 StatUtils.geometricMean(test);
443 fail("Expecting NullArgumentException");
444 } catch (NullArgumentException ex) {
445
446 }
447 test = new double[] {2, 4, 6, 8};
448 assertEquals(FastMath.exp(0.25d * StatUtils.sumLog(test)),
449 StatUtils.geometricMean(test), Double.MIN_VALUE);
450 assertEquals(FastMath.exp(0.5 * StatUtils.sumLog(test, 0, 2)),
451 StatUtils.geometricMean(test, 0, 2), Double.MIN_VALUE);
452 }
453
454
455
456
457 @Test
458 void testNormalize1() {
459 double[] sample = { 50, 100 };
460 double[]
461 expectedSample = { -25 / FastMath.sqrt(1250), 25 / FastMath.sqrt(1250) };
462 double[] out = StatUtils.normalize(sample);
463 for (int i = 0; i < out.length; i++) {
464 assertTrue(Precision.equals(out[i], expectedSample[i], 1));
465 }
466 }
467
468
469
470
471
472 @Test
473 void testNormalize2() {
474
475 int length = 77;
476 double[] sample = new double[length];
477 for (int i = 0; i < length; i++) {
478 sample[i] = FastMath.random();
479 }
480
481 double[] standardizedSample = StatUtils.normalize(sample);
482
483 DescriptiveStatistics stats = new DescriptiveStatistics();
484
485 for (int i = 0; i < length; i++) {
486 stats.addValue(standardizedSample[i]);
487 }
488
489 double distance = 1E-10;
490
491 assertEquals(0.0, stats.getMean(), distance);
492 assertEquals(1.0, stats.getStandardDeviation(), distance);
493 }
494
495 @Test
496 void testMode() {
497 final double[] singleMode = {0, 1, 0, 2, 7, 11, 12};
498 final double[] modeSingle = StatUtils.mode(singleMode);
499 assertEquals(0, modeSingle[0], Double.MIN_VALUE);
500 assertEquals(1, modeSingle.length);
501
502 final double[] twoMode = {0, 1, 2, 0, 2, 3, 7, 11};
503 final double[] modeDouble = StatUtils.mode(twoMode);
504 assertEquals(0, modeDouble[0], Double.MIN_VALUE);
505 assertEquals(2, modeDouble[1], Double.MIN_VALUE);
506 assertEquals(2, modeDouble.length);
507
508 final double[] nanInfested = {0, 0, 0, Double.NaN, Double.NaN, Double.NaN, Double.NaN, 2, 2, 2, 3, 5};
509 final double[] modeNan = StatUtils.mode(nanInfested);
510 assertEquals(0, modeNan[0], Double.MIN_VALUE);
511 assertEquals(2, modeNan[1], Double.MIN_VALUE);
512 assertEquals(2, modeNan.length);
513
514 final double[] infInfested = {0, 0, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
515 Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 2, 2, 3, 5};
516 final double[] modeInf = StatUtils.mode(infInfested);
517 assertEquals(Double.NEGATIVE_INFINITY, modeInf[0], Double.MIN_VALUE);
518 assertEquals(0, modeInf[1], Double.MIN_VALUE);
519 assertEquals(2, modeInf[2], Double.MIN_VALUE);
520 assertEquals(Double.POSITIVE_INFINITY, modeInf[3], Double.MIN_VALUE);
521 assertEquals(4, modeInf.length);
522
523 final double[] noData = {};
524 final double[] modeNodata = StatUtils.mode(noData);
525 assertEquals(0, modeNodata.length);
526
527 final double[] nansOnly = {Double.NaN, Double.NaN};
528 final double[] modeNansOnly = StatUtils.mode(nansOnly);
529 assertEquals(0, modeNansOnly.length);
530
531 final double[] nullArray = null;
532 try {
533 StatUtils.mode(nullArray);
534 fail("Expecting NullArgumentException");
535 } catch (NullArgumentException ex) {
536
537 }
538 }
539
540 }