1 /* 2 * Copyright (C) 2014 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.math; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import com.google.common.collect.ImmutableSet; 23 import com.google.common.collect.Sets; 24 import java.util.Map; 25 import java.util.Random; 26 import java.util.Set; 27 import junit.framework.TestCase; 28 29 /** 30 * Tests that the different algorithms benchmarked in {@link QuantilesBenchmark} are actually all 31 * returning more-or-less the same answers. 32 */ 33 public class QuantilesAlgorithmTest extends TestCase { 34 35 private static final Random RNG = new Random(82674067L); 36 private static final int DATASET_SIZE = 1000; 37 private static final double ALLOWED_ERROR = 1.0e-10; 38 private static final QuantilesAlgorithm REFERENCE_ALGORITHM = QuantilesAlgorithm.SORTING; 39 private static final Set<QuantilesAlgorithm> NON_REFERENCE_ALGORITHMS = 40 Sets.difference( 41 ImmutableSet.copyOf(QuantilesAlgorithm.values()), ImmutableSet.of(REFERENCE_ALGORITHM)); 42 43 private double[] dataset; 44 45 @Override setUp()46 protected void setUp() { 47 dataset = new double[DATASET_SIZE]; 48 for (int i = 0; i < DATASET_SIZE; i++) { 49 dataset[i] = RNG.nextDouble(); 50 } 51 } 52 testSingleQuantile_median()53 public void testSingleQuantile_median() { 54 double referenceValue = REFERENCE_ALGORITHM.singleQuantile(1, 2, dataset.clone()); 55 for (QuantilesAlgorithm algorithm : NON_REFERENCE_ALGORITHMS) { 56 assertWithMessage("Mismatch between %s and %s", algorithm, REFERENCE_ALGORITHM) 57 .that(algorithm.singleQuantile(1, 2, dataset.clone())) 58 .isWithin(ALLOWED_ERROR) 59 .of(referenceValue); 60 } 61 } 62 testSingleQuantile_percentile99()63 public void testSingleQuantile_percentile99() { 64 double referenceValue = REFERENCE_ALGORITHM.singleQuantile(99, 100, dataset.clone()); 65 for (QuantilesAlgorithm algorithm : NON_REFERENCE_ALGORITHMS) { 66 assertWithMessage("Mismatch between %s and %s", algorithm, REFERENCE_ALGORITHM) 67 .that(algorithm.singleQuantile(99, 100, dataset.clone())) 68 .isWithin(ALLOWED_ERROR) 69 .of(referenceValue); 70 } 71 } 72 testMultipleQuantile()73 public void testMultipleQuantile() { 74 ImmutableSet<Integer> indexes = ImmutableSet.of(50, 90, 99); 75 Map<Integer, Double> referenceQuantiles = 76 REFERENCE_ALGORITHM.multipleQuantiles(indexes, 100, dataset.clone()); 77 assertThat(referenceQuantiles.keySet()).isEqualTo(indexes); 78 for (QuantilesAlgorithm algorithm : NON_REFERENCE_ALGORITHMS) { 79 Map<Integer, Double> quantiles = algorithm.multipleQuantiles(indexes, 100, dataset.clone()); 80 assertWithMessage("Wrong keys from " + algorithm).that(quantiles.keySet()).isEqualTo(indexes); 81 for (int i : indexes) { 82 assertWithMessage("Mismatch between %s and %s at %s", algorithm, REFERENCE_ALGORITHM, i) 83 .that(quantiles.get(i)) 84 .isWithin(ALLOWED_ERROR) 85 .of(referenceQuantiles.get(i)); 86 } 87 } 88 } 89 } 90