001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.stat; 018 019 import junit.framework.Test; 020 import junit.framework.TestCase; 021 import junit.framework.TestSuite; 022 023 import org.apache.commons.math.TestUtils; 024 025 /** 026 * Test cases for the {@link StatUtils} class. 027 * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $ 028 */ 029 030 public final class StatUtilsTest extends TestCase { 031 032 private double one = 1; 033 private float two = 2; 034 private int three = 3; 035 private double mean = 2; 036 private double sumSq = 18; 037 private double sum = 8; 038 private double var = 0.666666666666666666667; 039 private double min = 1; 040 private double max = 3; 041 private double tolerance = 10E-15; 042 private double nan = Double.NaN; 043 044 public StatUtilsTest(String name) { 045 super(name); 046 } 047 048 public static Test suite() { 049 TestSuite suite = new TestSuite(StatUtilsTest.class); 050 suite.setName("StatUtil Tests"); 051 return suite; 052 } 053 054 /** test stats */ 055 public void testStats() { 056 double[] values = new double[] { one, two, two, three }; 057 assertEquals("sum", sum, StatUtils.sum(values), tolerance); 058 assertEquals("sumsq", sumSq, StatUtils.sumSq(values), tolerance); 059 assertEquals("var", var, StatUtils.variance(values), tolerance); 060 assertEquals("var with mean", var, StatUtils.variance(values, mean), tolerance); 061 assertEquals("mean", mean, StatUtils.mean(values), tolerance); 062 assertEquals("min", min, StatUtils.min(values), tolerance); 063 assertEquals("max", max, StatUtils.max(values), tolerance); 064 } 065 066 public void testN0andN1Conditions() throws Exception { 067 double[] values = new double[0]; 068 069 assertTrue( 070 "Mean of n = 0 set should be NaN", 071 Double.isNaN(StatUtils.mean(values))); 072 assertTrue( 073 "Variance of n = 0 set should be NaN", 074 Double.isNaN(StatUtils.variance(values))); 075 076 values = new double[] { one }; 077 078 assertTrue( 079 "Mean of n = 1 set should be value of single item n1", 080 StatUtils.mean(values) == one); 081 assertTrue( 082 "Variance of n = 1 set should be zero", 083 StatUtils.variance(values) == 0); 084 } 085 086 public void testArrayIndexConditions() throws Exception { 087 double[] values = { 1.0, 2.0, 3.0, 4.0 }; 088 089 assertEquals( 090 "Sum not expected", 091 5.0, 092 StatUtils.sum(values, 1, 2), 093 Double.MIN_VALUE); 094 assertEquals( 095 "Sum not expected", 096 3.0, 097 StatUtils.sum(values, 0, 2), 098 Double.MIN_VALUE); 099 assertEquals( 100 "Sum not expected", 101 7.0, 102 StatUtils.sum(values, 2, 2), 103 Double.MIN_VALUE); 104 105 try { 106 StatUtils.sum(values, 2, 3); 107 assertTrue("Didn't throw exception", false); 108 } catch (Exception e) { 109 assertTrue(true); 110 } 111 112 try { 113 StatUtils.sum(values, -1, 2); 114 assertTrue("Didn't throw exception", false); 115 } catch (Exception e) { 116 assertTrue(true); 117 } 118 119 } 120 121 public void testSumSq() { 122 double[] x = null; 123 124 // test null 125 try { 126 StatUtils.sumSq(x); 127 fail("null is not a valid data array."); 128 } catch (IllegalArgumentException ex) { 129 // success 130 } 131 132 try { 133 StatUtils.sumSq(x, 0, 4); 134 fail("null is not a valid data array."); 135 } catch (IllegalArgumentException ex) { 136 // success 137 } 138 139 // test empty 140 x = new double[] {}; 141 TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance); 142 TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance); 143 144 // test one 145 x = new double[] {two}; 146 TestUtils.assertEquals(4, StatUtils.sumSq(x), tolerance); 147 TestUtils.assertEquals(4, StatUtils.sumSq(x, 0, 1), tolerance); 148 149 // test many 150 x = new double[] {one, two, two, three}; 151 TestUtils.assertEquals(18, StatUtils.sumSq(x), tolerance); 152 TestUtils.assertEquals(8, StatUtils.sumSq(x, 1, 2), tolerance); 153 } 154 155 public void testProduct() { 156 double[] x = null; 157 158 // test null 159 try { 160 StatUtils.product(x); 161 fail("null is not a valid data array."); 162 } catch (IllegalArgumentException ex) { 163 // success 164 } 165 166 try { 167 StatUtils.product(x, 0, 4); 168 fail("null is not a valid data array."); 169 } catch (IllegalArgumentException ex) { 170 // success 171 } 172 173 // test empty 174 x = new double[] {}; 175 TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance); 176 TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance); 177 178 // test one 179 x = new double[] {two}; 180 TestUtils.assertEquals(two, StatUtils.product(x), tolerance); 181 TestUtils.assertEquals(two, StatUtils.product(x, 0, 1), tolerance); 182 183 // test many 184 x = new double[] {one, two, two, three}; 185 TestUtils.assertEquals(12, StatUtils.product(x), tolerance); 186 TestUtils.assertEquals(4, StatUtils.product(x, 1, 2), tolerance); 187 } 188 189 public void testSumLog() { 190 double[] x = null; 191 192 // test null 193 try { 194 StatUtils.sumLog(x); 195 fail("null is not a valid data array."); 196 } catch (IllegalArgumentException ex) { 197 // success 198 } 199 200 try { 201 StatUtils.sumLog(x, 0, 4); 202 fail("null is not a valid data array."); 203 } catch (IllegalArgumentException ex) { 204 // success 205 } 206 207 // test empty 208 x = new double[] {}; 209 TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance); 210 TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance); 211 212 // test one 213 x = new double[] {two}; 214 TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x), tolerance); 215 TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x, 0, 1), tolerance); 216 217 // test many 218 x = new double[] {one, two, two, three}; 219 TestUtils.assertEquals(Math.log(one) + 2.0 * Math.log(two) + Math.log(three), StatUtils.sumLog(x), tolerance); 220 TestUtils.assertEquals(2.0 * Math.log(two), StatUtils.sumLog(x, 1, 2), tolerance); 221 } 222 223 public void testMean() { 224 double[] x = null; 225 226 try { 227 StatUtils.mean(x, 0, 4); 228 fail("null is not a valid data array."); 229 } catch (IllegalArgumentException ex) { 230 // success 231 } 232 233 // test empty 234 x = new double[] {}; 235 TestUtils.assertEquals(Double.NaN, StatUtils.mean(x, 0, 0), tolerance); 236 237 // test one 238 x = new double[] {two}; 239 TestUtils.assertEquals(two, StatUtils.mean(x, 0, 1), tolerance); 240 241 // test many 242 x = new double[] {one, two, two, three}; 243 TestUtils.assertEquals(2.5, StatUtils.mean(x, 2, 2), tolerance); 244 } 245 246 public void testVariance() { 247 double[] x = null; 248 249 try { 250 StatUtils.variance(x, 0, 4); 251 fail("null is not a valid data array."); 252 } catch (IllegalArgumentException ex) { 253 // success 254 } 255 256 // test empty 257 x = new double[] {}; 258 TestUtils.assertEquals(Double.NaN, StatUtils.variance(x, 0, 0), tolerance); 259 260 // test one 261 x = new double[] {two}; 262 TestUtils.assertEquals(0.0, StatUtils.variance(x, 0, 1), tolerance); 263 264 // test many 265 x = new double[] {one, two, two, three}; 266 TestUtils.assertEquals(0.5, StatUtils.variance(x, 2, 2), tolerance); 267 268 // test precomputed mean 269 x = new double[] {one, two, two, three}; 270 TestUtils.assertEquals(0.5, StatUtils.variance(x,2.5, 2, 2), tolerance); 271 } 272 273 public void testMax() { 274 double[] x = null; 275 276 try { 277 StatUtils.max(x, 0, 4); 278 fail("null is not a valid data array."); 279 } catch (IllegalArgumentException ex) { 280 // success 281 } 282 283 // test empty 284 x = new double[] {}; 285 TestUtils.assertEquals(Double.NaN, StatUtils.max(x, 0, 0), tolerance); 286 287 // test one 288 x = new double[] {two}; 289 TestUtils.assertEquals(two, StatUtils.max(x, 0, 1), tolerance); 290 291 // test many 292 x = new double[] {one, two, two, three}; 293 TestUtils.assertEquals(three, StatUtils.max(x, 1, 3), tolerance); 294 295 // test first nan is ignored 296 x = new double[] {nan, two, three}; 297 TestUtils.assertEquals(three, StatUtils.max(x), tolerance); 298 299 // test middle nan is ignored 300 x = new double[] {one, nan, three}; 301 TestUtils.assertEquals(three, StatUtils.max(x), tolerance); 302 303 // test last nan is ignored 304 x = new double[] {one, two, nan}; 305 TestUtils.assertEquals(two, StatUtils.max(x), tolerance); 306 307 // test all nan returns nan 308 x = new double[] {nan, nan, nan}; 309 TestUtils.assertEquals(nan, StatUtils.max(x), tolerance); 310 } 311 312 public void testMin() { 313 double[] x = null; 314 315 try { 316 StatUtils.min(x, 0, 4); 317 fail("null is not a valid data array."); 318 } catch (IllegalArgumentException ex) { 319 // success 320 } 321 322 // test empty 323 x = new double[] {}; 324 TestUtils.assertEquals(Double.NaN, StatUtils.min(x, 0, 0), tolerance); 325 326 // test one 327 x = new double[] {two}; 328 TestUtils.assertEquals(two, StatUtils.min(x, 0, 1), tolerance); 329 330 // test many 331 x = new double[] {one, two, two, three}; 332 TestUtils.assertEquals(two, StatUtils.min(x, 1, 3), tolerance); 333 334 // test first nan is ignored 335 x = new double[] {nan, two, three}; 336 TestUtils.assertEquals(two, StatUtils.min(x), tolerance); 337 338 // test middle nan is ignored 339 x = new double[] {one, nan, three}; 340 TestUtils.assertEquals(one, StatUtils.min(x), tolerance); 341 342 // test last nan is ignored 343 x = new double[] {one, two, nan}; 344 TestUtils.assertEquals(one, StatUtils.min(x), tolerance); 345 346 // test all nan returns nan 347 x = new double[] {nan, nan, nan}; 348 TestUtils.assertEquals(nan, StatUtils.min(x), tolerance); 349 } 350 351 public void testPercentile() { 352 double[] x = null; 353 354 // test null 355 try { 356 StatUtils.percentile(x, .25); 357 fail("null is not a valid data array."); 358 } catch (IllegalArgumentException ex) { 359 // success 360 } 361 362 try { 363 StatUtils.percentile(x, 0, 4, 0.25); 364 fail("null is not a valid data array."); 365 } catch (IllegalArgumentException ex) { 366 // success 367 } 368 369 // test empty 370 x = new double[] {}; 371 TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 25), tolerance); 372 TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), tolerance); 373 374 // test one 375 x = new double[] {two}; 376 TestUtils.assertEquals(two, StatUtils.percentile(x, 25), tolerance); 377 TestUtils.assertEquals(two, StatUtils.percentile(x, 0, 1, 25), tolerance); 378 379 // test many 380 x = new double[] {one, two, two, three}; 381 TestUtils.assertEquals(2.5, StatUtils.percentile(x, 70), tolerance); 382 TestUtils.assertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), tolerance); 383 } 384 385 public void testDifferenceStats() throws Exception { 386 double sample1[] = {1d, 2d, 3d, 4d}; 387 double sample2[] = {1d, 3d, 4d, 2d}; 388 double diff[] = {0d, -1d, -1d, 2d}; 389 double small[] = {1d, 4d}; 390 double meanDifference = StatUtils.meanDifference(sample1, sample2); 391 assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), tolerance); 392 assertEquals(meanDifference, StatUtils.mean(diff), tolerance); 393 assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference), 394 StatUtils.variance(diff), tolerance); 395 try { 396 StatUtils.meanDifference(sample1, small); 397 fail("Expecting IllegalArgumentException"); 398 } catch (IllegalArgumentException ex) { 399 // expected 400 } 401 try { 402 StatUtils.varianceDifference(sample1, small, meanDifference); 403 fail("Expecting IllegalArgumentException"); 404 } catch (IllegalArgumentException ex) { 405 // expected 406 } 407 try { 408 double[] single = {1.0}; 409 StatUtils.varianceDifference(single, single, meanDifference); 410 fail("Expecting IllegalArgumentException"); 411 } catch (IllegalArgumentException ex) { 412 // expected 413 } 414 } 415 416 public void testGeometricMean() throws Exception { 417 double[] test = null; 418 try { 419 StatUtils.geometricMean(test); 420 fail("Expecting IllegalArgumentException"); 421 } catch (IllegalArgumentException ex) { 422 // expected 423 } 424 test = new double[] {2, 4, 6, 8}; 425 assertEquals(Math.exp(0.25d * StatUtils.sumLog(test)), 426 StatUtils.geometricMean(test), Double.MIN_VALUE); 427 assertEquals(Math.exp(0.5 * StatUtils.sumLog(test, 0, 2)), 428 StatUtils.geometricMean(test, 0, 2), Double.MIN_VALUE); 429 } 430 }