/*
 * Copyright (C) 2014 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.math;

import static com.google.common.math.Quantiles.median;
import static com.google.common.math.Quantiles.percentiles;
import static com.google.common.math.Quantiles.quartiles;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.NaN;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.math.RoundingMode.CEILING;
import static java.math.RoundingMode.FLOOR;
import static java.math.RoundingMode.UNNECESSARY;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Ordering;
import com.google.common.math.Quantiles.ScaleAndIndexes;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.truth.Correspondence;
import com.google.common.truth.Correspondence.BinaryPredicate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import junit.framework.TestCase;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Tests for {@link Quantiles}.
 *
 * @author Pete Gillin
 */
public class QuantilesTest extends TestCase {

  /*
   * Since Quantiles provides a fluent-style API, each test covers a chain of methods resulting in
   * the computation of one or more quantiles (or in an error) rather than individual methods. The
   * tests are divided into three sections:
   * 1. Tests on a hardcoded dataset for chains starting with median(), quartiles(), and scale(10);
   * 2. Tests on hardcoded datasets include non-finite values for chains starting with scale(10);
   * 3. Tests on a mechanically generated dataset for chains starting with percentiles();
   * 4. Tests of illegal usages of the API.
   */

  /*
   * Covering every combination would lead to an explosion in the number of tests. So we cover only:
   * - median with compute taking a double-collection and with computeInPlace;
   * - quartiles with index and with indexes taking int-varargs, and with compute taking a
   *   double-collection and with computeInPlace;
   * - scale with index and with indexes taking int-varargs, and with all overloads of compute
   *   taking a double-collection and with computeInPlace;
   * - scale with indexes taking integer-collection with compute taking a double-collection and with
   *   computeInPlace;
   * - (except that, for non-finite values, we don't do all combinations exhaustively);
   * - percentiles with index and with indexes taking int-varargs, and with compute taking a
   *   double-collection and with computeInPlace.
   */

  private static final double ALLOWED_ERROR = 1.0e-10;

  /**
   * A {@link Correspondence} which accepts finite values within {@link #ALLOWED_ERROR} of each
   * other.
   */
  private static final Correspondence<Number, Number> FINITE_QUANTILE_CORRESPONDENCE =
      Correspondence.tolerance(ALLOWED_ERROR);

  /**
   * A {@link Correspondence} which accepts either finite values within {@link #ALLOWED_ERROR} of
   * each other or identical non-finite values.
   */
  private static final Correspondence<Double, Double> QUANTILE_CORRESPONDENCE =
      Correspondence.from(
          new BinaryPredicate<Double, Double>() {
            @Override
            public boolean apply(@Nullable Double actual, @Nullable Double expected) {
              // Test for equality to allow non-finite values to match; otherwise, use the finite
              // test.
              return actual.equals(expected)
                  || FINITE_QUANTILE_CORRESPONDENCE.compare(actual, expected);
            }
          },
          "is identical to or " + FINITE_QUANTILE_CORRESPONDENCE);

  // 1. Tests on a hardcoded dataset for chains starting with median(), quartiles(), and scale(10):

  /** The squares of the 16 integers from 0 to 15, in an arbitrary order. */
  private static final ImmutableList<Double> SIXTEEN_SQUARES_DOUBLES =
      ImmutableList.of(
          25.0, 100.0, 0.0, 144.0, 9.0, 121.0, 4.0, 225.0, 169.0, 64.0, 49.0, 16.0, 36.0, 1.0, 81.0,
          196.0);

  private static final ImmutableList<Long> SIXTEEN_SQUARES_LONGS =
      ImmutableList.of(
          25L, 100L, 0L, 144L, 9L, 121L, 4L, 225L, 169L, 64L, 49L, 16L, 36L, 1L, 81L, 196L);
  private static final ImmutableList<Integer> SIXTEEN_SQUARES_INTEGERS =
      ImmutableList.of(25, 100, 0, 144, 9, 121, 4, 225, 169, 64, 49, 16, 36, 1, 81, 196);
  private static final double SIXTEEN_SQUARES_MIN = 0.0;
  private static final double SIXTEEN_SQUARES_DECILE_1 = 0.5 * (1.0 + 4.0);
  private static final double SIXTEEN_SQUARES_QUARTILE_1 = 0.25 * 9.0 + 0.75 * 16.0;
  private static final double SIXTEEN_SQUARES_MEDIAN = 0.5 * (49.0 + 64.0);
  private static final double SIXTEEN_SQUARES_QUARTILE_3 = 0.75 * 121.0 + 0.25 * 144.0;
  private static final double SIXTEEN_SQUARES_DECILE_8 = 144.0;
  private static final double SIXTEEN_SQUARES_MAX = 225.0;

  public void testMedian_compute_doubleCollection() {
    assertThat(median().compute(SIXTEEN_SQUARES_DOUBLES))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_MEDIAN);
  }

  public void testMedian_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(median().computeInPlace(dataset)).isWithin(ALLOWED_ERROR).of(SIXTEEN_SQUARES_MEDIAN);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  public void testQuartiles_index_compute_doubleCollection() {
    assertThat(quartiles().index(1).compute(SIXTEEN_SQUARES_DOUBLES))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_QUARTILE_1);
  }

  public void testQuartiles_index_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(quartiles().index(1).computeInPlace(dataset))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_QUARTILE_1);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  public void testQuartiles_indexes_varargs_compute_doubleCollection() {
    assertThat(quartiles().indexes(1, 3).compute(SIXTEEN_SQUARES_DOUBLES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(1, SIXTEEN_SQUARES_QUARTILE_1, 3, SIXTEEN_SQUARES_QUARTILE_3);
  }

  public void testQuartiles_indexes_varargs_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(quartiles().indexes(1, 3).computeInPlace(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            1, SIXTEEN_SQUARES_QUARTILE_1,
            3, SIXTEEN_SQUARES_QUARTILE_3);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  public void testScale_index_compute_doubleCollection() {
    assertThat(Quantiles.scale(10).index(1).compute(SIXTEEN_SQUARES_DOUBLES))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
  }

  public void testScale_index_compute_longCollection() {
    assertThat(Quantiles.scale(10).index(1).compute(SIXTEEN_SQUARES_LONGS))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
  }

  public void testScale_index_compute_integerCollection() {
    assertThat(Quantiles.scale(10).index(1).compute(SIXTEEN_SQUARES_INTEGERS))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
  }

  public void testScale_index_compute_doubleVarargs() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(Quantiles.scale(10).index(1).compute(dataset))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
    assertThat(dataset)
        .usingExactEquality()
        .containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES)
        .inOrder();
  }

  public void testScale_index_compute_longVarargs() {
    long[] dataset = Longs.toArray(SIXTEEN_SQUARES_LONGS);
    assertThat(Quantiles.scale(10).index(1).compute(dataset))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
    assertThat(dataset).asList().isEqualTo(SIXTEEN_SQUARES_LONGS);
  }

  public void testScale_index_compute_intVarargs() {
    int[] dataset = Ints.toArray(SIXTEEN_SQUARES_INTEGERS);
    assertThat(Quantiles.scale(10).index(1).compute(dataset))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
    assertThat(dataset).asList().isEqualTo(SIXTEEN_SQUARES_INTEGERS);
  }

  public void testScale_index_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(Quantiles.scale(10).index(1).computeInPlace(dataset))
        .isWithin(ALLOWED_ERROR)
        .of(SIXTEEN_SQUARES_DECILE_1);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  public void testScale_index_computeInPlace_explicitVarargs() {
    assertThat(Quantiles.scale(10).index(5).computeInPlace(78.9, 12.3, 45.6))
        .isWithin(ALLOWED_ERROR)
        .of(45.6);
  }

  public void testScale_indexes_varargs_compute_doubleCollection() {
    // Note that we specify index 1 twice, which by the method contract should be ignored.
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_DOUBLES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
  }

  public void testScale_indexes_varargs_compute_doubleCollection_snapshotsIndexes() {
    // This test is the same as testScale_indexes_varargs_compute_doubleCollection except that the
    // array of indexes to be calculated is modified between the calls to indexes and compute: since
    // the contract is that it is snapshotted, this shouldn't make any difference to the result.
    int[] indexes = {0, 10, 5, 1, 8, 10};
    ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(indexes);
    indexes[0] = 3;
    assertThat(intermediate.compute(SIXTEEN_SQUARES_DOUBLES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
  }

  public void testScale_indexes_largeVarargs_compute_doubleCollection() {
    int scale = Integer.MAX_VALUE;
    int otherIndex = (Integer.MAX_VALUE - 1) / 3; // this divides exactly
    // For the otherIndex calculation, we have q=Integer.MAX_VALUE, k=(Integer.MAX_VALUE-1)/3, and
    // N=16. Therefore k*(N-1)/q = 5-5/Integer.MAX_VALUE, which has floor 4 and fractional part
    // (1-5/Integer.MAX_VALUE).
    double otherValue = 16.0 * 5.0 / Integer.MAX_VALUE + 25.0 * (1.0 - 5.0 / Integer.MAX_VALUE);
    assertThat(
            Quantiles.scale(scale).indexes(0, scale, otherIndex).compute(SIXTEEN_SQUARES_DOUBLES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN, scale, SIXTEEN_SQUARES_MAX, otherIndex, otherValue);
  }

  public void testScale_indexes_varargs_compute_longCollection() {
    // Note that we specify index 1 twice, which by the method contract should be ignored.
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_LONGS))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
  }

  public void testScale_indexes_varargs_compute_integerCollection() {
    // Note that we specify index 1 twice, which by the method contract should be ignored.
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
  }

  public void testScale_indexes_varargs_compute_indexOrderIsMaintained() {
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(SIXTEEN_SQUARES_INTEGERS))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8)
        .inOrder();
  }

  public void testScale_indexes_varargs_compute_doubleVarargs() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
    assertThat(dataset)
        .usingExactEquality()
        .containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES)
        .inOrder();
  }

  public void testScale_indexes_varargs_compute_longVarargs() {
    long[] dataset = Longs.toArray(SIXTEEN_SQUARES_LONGS);
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
    assertThat(dataset).asList().isEqualTo(SIXTEEN_SQUARES_LONGS);
  }

  public void testScale_indexes_varargs_compute_intVarargs() {
    int[] dataset = Ints.toArray(SIXTEEN_SQUARES_INTEGERS);
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).compute(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
    assertThat(dataset).asList().isEqualTo(SIXTEEN_SQUARES_INTEGERS);
  }

  public void testScale_indexes_varargs_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(Quantiles.scale(10).indexes(0, 10, 5, 1, 8, 1).computeInPlace(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  public void testScale_indexes_varargs_computeInPlace_explicitVarargs() {
    assertThat(Quantiles.scale(10).indexes(0, 10).computeInPlace(78.9, 12.3, 45.6))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, 12.3,
            10, 78.9);
  }

  public void testScale_indexes_collection_compute_doubleCollection() {
    // Note that we specify index 1 twice, which by the method contract should be ignored.
    assertThat(
            Quantiles.scale(10)
                .indexes(ImmutableList.of(0, 10, 5, 1, 8, 1))
                .compute(SIXTEEN_SQUARES_DOUBLES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
  }

  public void testScale_indexes_collection_computeInPlace() {
    double[] dataset = Doubles.toArray(SIXTEEN_SQUARES_DOUBLES);
    assertThat(
            Quantiles.scale(10)
                .indexes(ImmutableList.of(0, 10, 5, 1, 8, 1))
                .computeInPlace(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, SIXTEEN_SQUARES_MIN,
            10, SIXTEEN_SQUARES_MAX,
            5, SIXTEEN_SQUARES_MEDIAN,
            1, SIXTEEN_SQUARES_DECILE_1,
            8, SIXTEEN_SQUARES_DECILE_8);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(SIXTEEN_SQUARES_DOUBLES);
  }

  // 2. Tests on hardcoded datasets include non-finite values for chains starting with scale(10):

  private static final ImmutableList<Double> ONE_TO_FIVE_AND_POSITIVE_INFINITY =
      ImmutableList.of(3.0, 5.0, POSITIVE_INFINITY, 1.0, 4.0, 2.0);
  private static final ImmutableList<Double> ONE_TO_FIVE_AND_NEGATIVE_INFINITY =
      ImmutableList.of(3.0, 5.0, NEGATIVE_INFINITY, 1.0, 4.0, 2.0);
  private static final ImmutableList<Double> NEGATIVE_INFINITY_AND_FIVE_POSITIVE_INFINITIES =
      ImmutableList.of(
          POSITIVE_INFINITY,
          POSITIVE_INFINITY,
          NEGATIVE_INFINITY,
          POSITIVE_INFINITY,
          POSITIVE_INFINITY,
          POSITIVE_INFINITY);
  private static final ImmutableList<Double> ONE_TO_FIVE_AND_NAN =
      ImmutableList.of(3.0, 5.0, NaN, 1.0, 4.0, 2.0);

  public void testScale_indexes_varargs_compute_doubleCollection_positiveInfinity() {
    assertThat(
            Quantiles.scale(10)
                .indexes(0, 1, 2, 8, 9, 10)
                .compute(ONE_TO_FIVE_AND_POSITIVE_INFINITY))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, 1.0,
            1, 1.5,
            2, 2.0,
            8, 5.0,
            9, POSITIVE_INFINITY, // interpolating between 5.0 and POSITIVE_INFNINITY
            10, POSITIVE_INFINITY);
  }

  public void testScale_index_compute_doubleCollection_positiveInfinity() {
    // interpolating between 5.0 and POSITIVE_INFNINITY
    assertThat(Quantiles.scale(10).index(9).compute(ONE_TO_FIVE_AND_POSITIVE_INFINITY))
        .isPositiveInfinity();
  }

  public void testScale_indexes_varargs_compute_doubleCollection_negativeInfinity() {
    assertThat(
            Quantiles.scale(10)
                .indexes(0, 1, 2, 8, 9, 10)
                .compute(ONE_TO_FIVE_AND_NEGATIVE_INFINITY))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, NEGATIVE_INFINITY,
            1, NEGATIVE_INFINITY, // interpolating between NEGATIVE_INFNINITY and 1.0
            2, 1.0,
            8, 4.0,
            9, 4.5,
            10, 5.0);
  }

  public void testScale_index_compute_doubleCollection_negativeInfinity() {
    // interpolating between NEGATIVE_INFNINITY and 1.0
    assertThat(Quantiles.scale(10).index(1).compute(ONE_TO_FIVE_AND_NEGATIVE_INFINITY))
        .isNegativeInfinity();
  }

  public void testScale_indexes_varargs_compute_doubleCollection_bothInfinities() {
    assertThat(
            Quantiles.scale(10)
                .indexes(0, 1, 2, 8, 9, 10)
                .compute(NEGATIVE_INFINITY_AND_FIVE_POSITIVE_INFINITIES))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, NEGATIVE_INFINITY,
            1, NaN, // interpolating between NEGATIVE_ and POSITIVE_INFINITY values
            2, POSITIVE_INFINITY,
            8, POSITIVE_INFINITY,
            9, POSITIVE_INFINITY, // interpolating between two POSITIVE_INFINITY values
            10, POSITIVE_INFINITY);
  }

  public void testScale_indexes_varargs_compute_doubleCollection_nan() {
    assertThat(Quantiles.scale(10).indexes(0, 1, 2, 8, 9, 10).compute(ONE_TO_FIVE_AND_NAN))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactly(
            0, NaN,
            1, NaN,
            2, NaN,
            8, NaN,
            9, NaN,
            10, NaN);
  }

  public void testScale_index_compute_doubleCollection_nan() {
    assertThat(Quantiles.scale(10).index(5).compute(ONE_TO_FIVE_AND_NAN)).isNaN();
  }

  // 3. Tests on a mechanically generated dataset for chains starting with percentiles():

  private static final int PSEUDORANDOM_DATASET_SIZE = 9951;
  private static final ImmutableList<Double> PSEUDORANDOM_DATASET = generatePseudorandomDataset();
  private static final ImmutableList<Double> PSEUDORANDOM_DATASET_SORTED =
      Ordering.natural().immutableSortedCopy(PSEUDORANDOM_DATASET);

  private static ImmutableList<Double> generatePseudorandomDataset() {
    Random random = new Random(2211275185798966364L);
    ImmutableList.Builder<Double> largeDatasetBuilder = ImmutableList.builder();
    for (int i = 0; i < PSEUDORANDOM_DATASET_SIZE; i++) {
      largeDatasetBuilder.add(random.nextGaussian());
    }
    return largeDatasetBuilder.build();
  }

  private static double expectedLargeDatasetPercentile(int index) {
    // We have q=100, k=index, and N=9951. Therefore k*(N-1)/q is 99.5*index. If index is even, that
    // is an integer 199*index/2. If index is odd, that is halfway between floor(199*index/2) and
    // ceil(199*index/2).
    if (index % 2 == 0) {
      int position = IntMath.divide(199 * index, 2, UNNECESSARY);
      return PSEUDORANDOM_DATASET_SORTED.get(position);
    } else {
      int positionFloor = IntMath.divide(199 * index, 2, FLOOR);
      int positionCeil = IntMath.divide(199 * index, 2, CEILING);
      double lowerValue = PSEUDORANDOM_DATASET_SORTED.get(positionFloor);
      double upperValue = PSEUDORANDOM_DATASET_SORTED.get(positionCeil);
      return (lowerValue + upperValue) / 2.0;
    }
  }

  public void testPercentiles_index_compute_doubleCollection() {
    for (int index = 0; index <= 100; index++) {
      assertWithMessage("quantile at index " + index)
          .that(percentiles().index(index).compute(PSEUDORANDOM_DATASET))
          .isWithin(ALLOWED_ERROR)
          .of(expectedLargeDatasetPercentile(index));
    }
  }

  @AndroidIncompatible // slow
  public void testPercentiles_index_computeInPlace() {
    // Assert that the computation gives the correct result for all possible percentiles.
    for (int index = 0; index <= 100; index++) {
      double[] dataset = Doubles.toArray(PSEUDORANDOM_DATASET);
      assertWithMessage("quantile at index " + index)
          .that(percentiles().index(index).computeInPlace(dataset))
          .isWithin(ALLOWED_ERROR)
          .of(expectedLargeDatasetPercentile(index));
    }

    // Assert that the dataset contains the same elements after the in-place computation (although
    // they may be reordered). We only do this for one index rather than for all indexes, as it is
    // quite expensives (quadratic in the size of PSEUDORANDOM_DATASET).
    double[] dataset = Doubles.toArray(PSEUDORANDOM_DATASET);
    @SuppressWarnings("unused")
    double actual = percentiles().index(33).computeInPlace(dataset);
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(PSEUDORANDOM_DATASET);
  }

  public void testPercentiles_indexes_varargsPairs_compute_doubleCollection() {
    for (int index1 = 0; index1 <= 100; index1++) {
      for (int index2 = 0; index2 <= 100; index2++) {
        ImmutableMap.Builder<Integer, Double> expectedBuilder = ImmutableMap.builder();
        expectedBuilder.put(index1, expectedLargeDatasetPercentile(index1));
        if (index2 != index1) {
          expectedBuilder.put(index2, expectedLargeDatasetPercentile(index2));
        }
        assertThat(percentiles().indexes(index1, index2).compute(PSEUDORANDOM_DATASET))
            .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
            .containsExactlyEntriesIn(expectedBuilder.build());
      }
    }
  }

  public void testPercentiles_indexes_varargsAll_compute_doubleCollection() {
    ArrayList<Integer> indexes = new ArrayList<>();
    ImmutableMap.Builder<Integer, Double> expectedBuilder = ImmutableMap.builder();
    for (int index = 0; index <= 100; index++) {
      indexes.add(index);
      expectedBuilder.put(index, expectedLargeDatasetPercentile(index));
    }
    Random random = new Random(770683168895677741L);
    Collections.shuffle(indexes, random);
    assertThat(percentiles().indexes(Ints.toArray(indexes)).compute(PSEUDORANDOM_DATASET))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactlyEntriesIn(expectedBuilder.build());
  }

  @AndroidIncompatible // slow
  public void testPercentiles_indexes_varargsAll_computeInPlace() {
    double[] dataset = Doubles.toArray(PSEUDORANDOM_DATASET);
    List<Integer> indexes = new ArrayList<>();
    ImmutableMap.Builder<Integer, Double> expectedBuilder = ImmutableMap.builder();
    for (int index = 0; index <= 100; index++) {
      indexes.add(index);
      expectedBuilder.put(index, expectedLargeDatasetPercentile(index));
    }
    Random random = new Random(770683168895677741L);
    Collections.shuffle(indexes, random);
    assertThat(percentiles().indexes(Ints.toArray(indexes)).computeInPlace(dataset))
        .comparingValuesUsing(QUANTILE_CORRESPONDENCE)
        .containsExactlyEntriesIn(expectedBuilder.build());
    assertThat(dataset).usingExactEquality().containsExactlyElementsIn(PSEUDORANDOM_DATASET);
  }

  // 4. Tests of illegal usages of the API:

  private static final ImmutableList<Double> EMPTY_DATASET = ImmutableList.of();

  public void testScale_zero() {
    try {
      Quantiles.scale(0);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_negative() {
    try {
      Quantiles.scale(-4);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_negative() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.index(-1);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_tooHigh() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.index(11);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_negative() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.indexes(1, -1, 3);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_tooHigh() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.indexes(1, 11, 3);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_collection_negative() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.indexes(ImmutableList.of(1, -1, 3));
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_collection_tooHigh() {
    Quantiles.Scale intermediate = Quantiles.scale(10);
    try {
      intermediate.indexes(ImmutableList.of(1, 11, 3));
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_compute_doubleCollection_empty() {
    Quantiles.ScaleAndIndex intermediate = Quantiles.scale(10).index(3);
    try {
      intermediate.compute(EMPTY_DATASET);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_compute_doubleVarargs_empty() {
    Quantiles.ScaleAndIndex intermediate = Quantiles.scale(10).index(3);
    try {
      intermediate.compute(new double[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_compute_longVarargs_empty() {
    Quantiles.ScaleAndIndex intermediate = Quantiles.scale(10).index(3);
    try {
      intermediate.compute(new long[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_compute_intVarargs_empty() {
    Quantiles.ScaleAndIndex intermediate = Quantiles.scale(10).index(3);
    try {
      intermediate.compute(new int[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_index_computeInPlace_empty() {
    Quantiles.ScaleAndIndex intermediate = Quantiles.scale(10).index(3);
    try {
      intermediate.computeInPlace(new double[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_compute_doubleCollection_empty() {
    Quantiles.ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(1, 3, 5);
    try {
      intermediate.compute(EMPTY_DATASET);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_compute_doubleVarargs_empty() {
    Quantiles.ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(1, 3, 5);
    try {
      intermediate.compute(new double[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_compute_longVarargs_empty() {
    Quantiles.ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(1, 3, 5);
    try {
      intermediate.compute(new long[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_compute_intVarargs_empty() {
    Quantiles.ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(1, 3, 5);
    try {
      intermediate.compute(new int[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_varargs_computeInPlace_empty() {
    Quantiles.ScaleAndIndexes intermediate = Quantiles.scale(10).indexes(1, 3, 5);
    try {
      intermediate.computeInPlace(new double[] {});
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testScale_indexes_indexes_computeInPlace_empty() {
    int[] emptyIndexes = {};
    try {
      Quantiles.ScaleAndIndexes unused = Quantiles.scale(10).indexes(emptyIndexes);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }
}
