/*
 * Copyright (C) 2017 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.primitives;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Preconditions;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.Immutable;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.LongConsumer;
import java.util.stream.LongStream;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * An immutable array of {@code long} values, with an API resembling {@link List}.
 *
 *
Advantages compared to {@code long[]}:
 *
 *

 *
All the many well-known advantages of immutability (read Effective Java, third
 *       edition, Item 17).
 *
Has the value-based (not identity-based) {@link #equals}, {@link #hashCode}, and {@link
 *       #toString} behavior you expect.
 *
Offers useful operations beyond just {@code get} and {@code length}, so you don't have to
 *       hunt through classes like {@link Arrays} and {@link Longs} for them.
 *
Supports a copy-free {@link #subArray} view, so methods that accept this type don't need to
 *       add overloads that accept start and end indexes.
 *
Can be streamed without "breaking the chain": {@code foo.getBarLongs().stream()...}.
 *
Access to all collection-based utilities via {@link #asList} (though at the cost of
 *       allocating garbage).
 *

 *
 *
Disadvantages compared to {@code long[]}:
 *
 *

 *
Memory footprint has a fixed overhead (about 24 bytes per instance).
 *
Some construction use cases force the data to be copied (though several construction
 *       APIs are offered that don't).
 *
Can't be passed directly to methods that expect {@code long[]} (though the most common
 *       utilities do have replacements here).
 *
Dependency on {@code com.google.common} / Guava.
 *

 *
 *
Advantages compared to {@link com.google.common.collect.ImmutableList ImmutableList}{@code
 * <Long>}:
 *
 *

 *
Improved memory compactness and locality.
 *
Can be queried without allocating garbage.
 *
Access to {@code LongStream} features (like {@link LongStream#sum}) using {@code stream()}
 *       instead of the awkward {@code stream().mapToLong(v -> v)}.
 *

 *
 *
Disadvantages compared to {@code ImmutableList<Long>}:
 *
 *

 *
Can't be passed directly to methods that expect {@code Iterable}, {@code Collection}, or
 *       {@code List} (though the most common utilities do have replacements here, and there is a
 *       lazy {@link #asList} view).
 *

 *
 * @since 22.0
 */
@Beta
@GwtCompatible
@Immutable
public final class ImmutableLongArray implements Serializable {
  private static final ImmutableLongArray EMPTY = new ImmutableLongArray(new long[0]);

  /** Returns the empty array. */
  public static ImmutableLongArray of() {
    return EMPTY;
  }

  /** Returns an immutable array containing a single value. */
  public static ImmutableLongArray of(long e0) {
    return new ImmutableLongArray(new long[] {e0});
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray of(long e0, long e1) {
    return new ImmutableLongArray(new long[] {e0, e1});
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray of(long e0, long e1, long e2) {
    return new ImmutableLongArray(new long[] {e0, e1, e2});
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray of(long e0, long e1, long e2, long e3) {
    return new ImmutableLongArray(new long[] {e0, e1, e2, e3});
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray of(long e0, long e1, long e2, long e3, long e4) {
    return new ImmutableLongArray(new long[] {e0, e1, e2, e3, e4});
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray of(long e0, long e1, long e2, long e3, long e4, long e5) {
    return new ImmutableLongArray(new long[] {e0, e1, e2, e3, e4, e5});
  }

  // TODO(kevinb): go up to 11?

  /**
   * Returns an immutable array containing the given values, in order.
   *
   *
The array {@code rest} must not be longer than {@code Integer.MAX_VALUE - 1}.
   */
  // Use (first, rest) so that `of(someLongArray)` won't compile (they should use copyOf), which is
  // okay since we have to copy the just-created array anyway.
  public static ImmutableLongArray of(long first, long... rest) {
    checkArgument(
        rest.length <= Integer.MAX_VALUE - 1, "the total number of elements must fit in an int");
    long[] array = new long[rest.length + 1];
    array[0] = first;
    System.arraycopy(rest, 0, array, 1, rest.length);
    return new ImmutableLongArray(array);
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray copyOf(long[] values) {
    return values.length == 0
        ? EMPTY
        : new ImmutableLongArray(Arrays.copyOf(values, values.length));
  }

  /** Returns an immutable array containing the given values, in order. */
  public static ImmutableLongArray copyOf(Collection<Long> values) {
    return values.isEmpty() ? EMPTY : new ImmutableLongArray(Longs.toArray(values));
  }

  /**
   * Returns an immutable array containing the given values, in order.
   *
   *
Performance note: this method delegates to {@link #copyOf(Collection)} if {@code
   * values} is a {@link Collection}. Otherwise it creates a {@link #builder} and uses {@link
   * Builder#addAll(Iterable)}, with all the performance implications associated with that.
   */
  public static ImmutableLongArray copyOf(Iterable<Long> values) {
    if (values instanceof Collection) {
      return copyOf((Collection<Long>) values);
    }
    return builder().addAll(values).build();
  }

  /** Returns an immutable array containing all the values from {@code stream}, in order. */
  public static ImmutableLongArray copyOf(LongStream stream) {
    // Note this uses very different growth behavior from copyOf(Iterable) and the builder.
    long[] array = stream.toArray();
    return (array.length == 0) ? EMPTY : new ImmutableLongArray(array);
  }

  /**
   * Returns a new, empty builder for {@link ImmutableLongArray} instances, sized to hold up to
   * {@code initialCapacity} values without resizing. The returned builder is not thread-safe.
   *
   *
Performance note: When feasible, {@code initialCapacity} should be the exact number
   * of values that will be added, if that knowledge is readily available. It is better to guess a
   * value slightly too high than slightly too low. If the value is not exact, the {@link
   * ImmutableLongArray} that is built will very likely occupy more memory than strictly necessary;
   * to trim memory usage, build using {@code builder.build().trimmed()}.
   */
  public static Builder builder(int initialCapacity) {
    checkArgument(initialCapacity >= 0, "Invalid initialCapacity: %s", initialCapacity);
    return new Builder(initialCapacity);
  }

  /**
   * Returns a new, empty builder for {@link ImmutableLongArray} instances, with a default initial
   * capacity. The returned builder is not thread-safe.
   *
   *
Performance note: The {@link ImmutableLongArray} that is built will very likely
   * occupy more memory than necessary; to trim memory usage, build using {@code
   * builder.build().trimmed()}.
   */
  public static Builder builder() {
    return new Builder(10);
  }

  /**
   * A builder for {@link ImmutableLongArray} instances; obtained using {@link
   * ImmutableLongArray#builder}.
   */
  @CanIgnoreReturnValue
  public static final class Builder {
    private long[] array;
    private int count = 0; // <= array.length

    Builder(int initialCapacity) {
      array = new long[initialCapacity];
    }

    /**
     * Appends {@code value} to the end of the values the built {@link ImmutableLongArray} will
     * contain.
     */
    public Builder add(long value) {
      ensureRoomFor(1);
      array[count] = value;
      count += 1;
      return this;
    }

    /**
     * Appends {@code values}, in order, to the end of the values the built {@link
     * ImmutableLongArray} will contain.
     */
    public Builder addAll(long[] values) {
      ensureRoomFor(values.length);
      System.arraycopy(values, 0, array, count, values.length);
      count += values.length;
      return this;
    }

    /**
     * Appends {@code values}, in order, to the end of the values the built {@link
     * ImmutableLongArray} will contain.
     */
    public Builder addAll(Iterable<Long> values) {
      if (values instanceof Collection) {
        return addAll((Collection<Long>) values);
      }
      for (Long value : values) {
        add(value);
      }
      return this;
    }

    /**
     * Appends {@code values}, in order, to the end of the values the built {@link
     * ImmutableLongArray} will contain.
     */
    public Builder addAll(Collection<Long> values) {
      ensureRoomFor(values.size());
      for (Long value : values) {
        array[count++] = value;
      }
      return this;
    }

    /**
     * Appends all values from {@code stream}, in order, to the end of the values the built {@link
     * ImmutableLongArray} will contain.
     */
    public Builder addAll(LongStream stream) {
      Spliterator.OfLong spliterator = stream.spliterator();
      long size = spliterator.getExactSizeIfKnown();
      if (size > 0) { // known *and* nonempty
        ensureRoomFor(Ints.saturatedCast(size));
      }
      spliterator.forEachRemaining((LongConsumer) this::add);
      return this;
    }

    /**
     * Appends {@code values}, in order, to the end of the values the built {@link
     * ImmutableLongArray} will contain.
     */
    public Builder addAll(ImmutableLongArray values) {
      ensureRoomFor(values.length());
      System.arraycopy(values.array, values.start, array, count, values.length());
      count += values.length();
      return this;
    }

    private void ensureRoomFor(int numberToAdd) {
      int newCount = count + numberToAdd; // TODO(kevinb): check overflow now?
      if (newCount > array.length) {
        long[] newArray = new long[expandedCapacity(array.length, newCount)];
        System.arraycopy(array, 0, newArray, 0, count);
        this.array = newArray;
      }
    }

    // Unfortunately this is pasted from ImmutableCollection.Builder.
    private static int expandedCapacity(int oldCapacity, int minCapacity) {
      if (minCapacity < 0) {
        throw new AssertionError("cannot store more than MAX_VALUE elements");
      }
      // careful of overflow!
      int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
      if (newCapacity < minCapacity) {
        newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;
      }
      if (newCapacity < 0) {
        newCapacity = Integer.MAX_VALUE; // guaranteed to be >= newCapacity
      }
      return newCapacity;
    }

    /**
     * Returns a new immutable array. The builder can continue to be used after this call, to append
     * more values and build again.
     *
     *
Performance note: the returned array is backed by the same array as the builder, so
     * no data is copied as part of this step, but this may occupy more memory than strictly
     * necessary. To copy the data to a right-sized backing array, use {@code .build().trimmed()}.
     */
    @CheckReturnValue
    public ImmutableLongArray build() {
      return count == 0 ? EMPTY : new ImmutableLongArray(array, 0, count);
    }
  }

  // Instance stuff here

  // The array is never mutated after storing in this field and the construction strategies ensure
  // it doesn't escape this class
  @SuppressWarnings("Immutable")
  private final long[] array;

  /*
   * TODO(kevinb): evaluate the trade-offs of going bimorphic to save these two fields from most
   * instances. Note that the instances that would get smaller are the right set to care about
   * optimizing, because the rest have the option of calling `trimmed`.
   */

  private final transient int start; // it happens that we only serialize instances where this is 0
  private final int end; // exclusive

  private ImmutableLongArray(long[] array) {
    this(array, 0, array.length);
  }

  private ImmutableLongArray(long[] array, int start, int end) {
    this.array = array;
    this.start = start;
    this.end = end;
  }

  /** Returns the number of values in this array. */
  public int length() {
    return end - start;
  }

  /** Returns {@code true} if there are no values in this array ({@link #length} is zero). */
  public boolean isEmpty() {
    return end == start;
  }

  /**
   * Returns the {@code long} value present at the given index.
   *
   * @throws IndexOutOfBoundsException if {@code index} is negative, or greater than or equal to
   *     {@link #length}
   */
  public long get(int index) {
    Preconditions.checkElementIndex(index, length());
    return array[start + index];
  }

  /**
   * Returns the smallest index for which {@link #get} returns {@code target}, or {@code -1} if no
   * such index exists. Equivalent to {@code asList().indexOf(target)}.
   */
  public int indexOf(long target) {
    for (int i = start; i < end; i++) {
      if (array[i] == target) {
        return i - start;
      }
    }
    return -1;
  }

  /**
   * Returns the largest index for which {@link #get} returns {@code target}, or {@code -1} if no
   * such index exists. Equivalent to {@code asList().lastIndexOf(target)}.
   */
  public int lastIndexOf(long target) {
    for (int i = end - 1; i >= start; i--) {
      if (array[i] == target) {
        return i - start;
      }
    }
    return -1;
  }

  /**
   * Returns {@code true} if {@code target} is present at any index in this array. Equivalent to
   * {@code asList().contains(target)}.
   */
  public boolean contains(long target) {
    return indexOf(target) >= 0;
  }

  /** Invokes {@code consumer} for each value contained in this array, in order. */
  public void forEach(LongConsumer consumer) {
    checkNotNull(consumer);
    for (int i = start; i < end; i++) {
      consumer.accept(array[i]);
    }
  }

  /** Returns a stream over the values in this array, in order. */
  public LongStream stream() {
    return Arrays.stream(array, start, end);
  }

  /** Returns a new, mutable copy of this array's values, as a primitive {@code long[]}. */
  public long[] toArray() {
    return Arrays.copyOfRange(array, start, end);
  }

  /**
   * Returns a new immutable array containing the values in the specified range.
   *
   *
Performance note: The returned array has the same full memory footprint as this one
   * does (no actual copying is performed). To reduce memory usage, use {@code subArray(start,
   * end).trimmed()}.
   */
  public ImmutableLongArray subArray(int startIndex, int endIndex) {
    Preconditions.checkPositionIndexes(startIndex, endIndex, length());
    return startIndex == endIndex
        ? EMPTY
        : new ImmutableLongArray(array, start + startIndex, start + endIndex);
  }

  private Spliterator.OfLong spliterator() {
    return Spliterators.spliterator(array, start, end, Spliterator.IMMUTABLE | Spliterator.ORDERED);
  }

  /**
   * Returns an immutable view of this array's values as a {@code List}; note that {@code
   * long} values are boxed into {@link Long} instances on demand, which can be very expensive. The
   * returned list should be used once and discarded. For any usages beyond that, pass the returned
   * list to {@link com.google.common.collect.ImmutableList#copyOf(Collection) ImmutableList.copyOf}
   * and use that list instead.
   */
  public List<Long> asList() {
    /*
     * Typically we cache this kind of thing, but much repeated use of this view is a performance
     * anti-pattern anyway. If we cache, then everyone pays a price in memory footprint even if
     * they never use this method.
     */
    return new AsList(this);
  }

  static class AsList extends AbstractList<Long> implements RandomAccess, Serializable {
    private final ImmutableLongArray parent;

    private AsList(ImmutableLongArray parent) {
      this.parent = parent;
    }

    // inherit: isEmpty, containsAll, toArray x2, iterator, listIterator, stream, forEach, mutations

    @Override
    public int size() {
      return parent.length();
    }

    @Override
    public Long get(int index) {
      return parent.get(index);
    }

    @Override
    public boolean contains(Object target) {
      return indexOf(target) >= 0;
    }

    @Override
    public int indexOf(Object target) {
      return target instanceof Long ? parent.indexOf((Long) target) : -1;
    }

    @Override
    public int lastIndexOf(Object target) {
      return target instanceof Long ? parent.lastIndexOf((Long) target) : -1;
    }

    @Override
    public List<Long> subList(int fromIndex, int toIndex) {
      return parent.subArray(fromIndex, toIndex).asList();
    }

    // The default List spliterator is not efficiently splittable
    @Override
    public Spliterator<Long> spliterator() {
      return parent.spliterator();
    }

    @Override
    public boolean equals(@Nullable Object object) {
      if (object instanceof AsList) {
        AsList that = (AsList) object;
        return this.parent.equals(that.parent);
      }
      // We could delegate to super now but it would still box too much
      if (!(object instanceof List)) {
        return false;
      }
      List<?> that = (List<?>) object;
      if (this.size() != that.size()) {
        return false;
      }
      int i = parent.start;
      // Since `that` is very likely RandomAccess we could avoid allocating this iterator...
      for (Object element : that) {
        if (!(element instanceof Long) || parent.array[i++] != (Long) element) {
          return false;
        }
      }
      return true;
    }

    // Because we happen to use the same formula. If that changes, just don't override this.
    @Override
    public int hashCode() {
      return parent.hashCode();
    }

    @Override
    public String toString() {
      return parent.toString();
    }
  }

  /**
   * Returns {@code true} if {@code object} is an {@code ImmutableLongArray} containing the same
   * values as this one, in the same order.
   */
  @Override
  public boolean equals(@Nullable Object object) {
    if (object == this) {
      return true;
    }
    if (!(object instanceof ImmutableLongArray)) {
      return false;
    }
    ImmutableLongArray that = (ImmutableLongArray) object;
    if (this.length() != that.length()) {
      return false;
    }
    for (int i = 0; i < length(); i++) {
      if (this.get(i) != that.get(i)) {
        return false;
      }
    }
    return true;
  }

  /** Returns an unspecified hash code for the contents of this immutable array. */
  @Override
  public int hashCode() {
    int hash = 1;
    for (int i = start; i < end; i++) {
      hash *= 31;
      hash += Longs.hashCode(array[i]);
    }
    return hash;
  }

  /**
   * Returns a string representation of this array in the same form as {@link
   * Arrays#toString(long[])}, for example {@code "[1, 2, 3]"}.
   */
  @Override
  public String toString() {
    if (isEmpty()) {
      return "[]";
    }
    StringBuilder builder = new StringBuilder(length() * 5); // rough estimate is fine
    builder.append('[').append(array[start]);

    for (int i = start + 1; i < end; i++) {
      builder.append(", ").append(array[i]);
    }
    builder.append(']');
    return builder.toString();
  }

  /**
   * Returns an immutable array containing the same values as {@code this} array. This is logically
   * a no-op, and in some circumstances {@code this} itself is returned. However, if this instance
   * is a {@link #subArray} view of a larger array, this method will copy only the appropriate range
   * of values, resulting in an equivalent array with a smaller memory footprint.
   */
  public ImmutableLongArray trimmed() {
    return isPartialView() ? new ImmutableLongArray(toArray()) : this;
  }

  private boolean isPartialView() {
    return start > 0 || end < array.length;
  }

  Object writeReplace() {
    return trimmed();
  }

  Object readResolve() {
    return isEmpty() ? EMPTY : this;
  }
}


/*
 * 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.base.Preconditions.checkArgument;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.NaN;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.util.Arrays.sort;
import static java.util.Collections.unmodifiableMap;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Provides a fluent API for calculating quantiles.
 *
 *
Examples

 *
 *
To compute the median:
 *
 *
{@code
 * double myMedian = median().compute(myDataset);
 * }

 *
 * where {@link #median()} has been statically imported.
 *
 *
To compute the 99th percentile:
 *
 *
{@code
 * double myPercentile99 = percentiles().index(99).compute(myDataset);
 * }

 *
 * where {@link #percentiles()} has been statically imported.
 *
 *
To compute median and the 90th and 99th percentiles:
 *
 *
{@code
 * Map<Integer, Double> myPercentiles =
 *     percentiles().indexes(50, 90, 99).compute(myDataset);
 * }

 *
 * where {@link #percentiles()} has been statically imported: {@code myPercentiles} maps the keys
 * 50, 90, and 99, to their corresponding quantile values.
 *
 *
To compute quartiles, use {@link #quartiles()} instead of {@link #percentiles()}. To compute
 * arbitrary q-quantiles, use {@link #scale scale(q)}.
 *
 *
These examples all take a copy of your dataset. If you have a double array, you are okay with
 * it being arbitrarily reordered, and you want to avoid that copy, you can use {@code
 * computeInPlace} instead of {@code compute}.
 *
 *
Definition and notes on interpolation

 *
 *
The definition of the kth q-quantile of N values is as follows: define x = k * (N - 1) / q; if
 * x is an integer, the result is the value which would appear at index x in the sorted dataset
 * (unless there are {@link Double#NaN NaN} values, see below); otherwise, the result is the average
 * of the values which would appear at the indexes floor(x) and ceil(x) weighted by (1-frac(x)) and
 * frac(x) respectively. This is the same definition as used by Excel and by S, it is the Type 7
 * definition in R, and it is
 * described by
 * wikipedia as providing "Linear interpolation of the modes for the order statistics for the
 * uniform distribution on [0,1]."
 *
 *
Handling of non-finite values

 *
 *
If any values in the input are {@link Double#NaN NaN} then all values returned are {@link
 * Double#NaN NaN}. (This is the one occasion when the behaviour is not the same as you'd get from
 * sorting with {@link java.util.Arrays#sort(double[]) Arrays.sort(double[])} or {@link
 * java.util.Collections#sort(java.util.List) Collections.sort(List<Double>)} and selecting
 * the required value(s). Those methods would sort {@link Double#NaN NaN} as if it is greater than
 * any other value and place them at the end of the dataset, even after {@link
 * Double#POSITIVE_INFINITY POSITIVE_INFINITY}.)
 *
 *
Otherwise, {@link Double#NEGATIVE_INFINITY NEGATIVE_INFINITY} and {@link
 * Double#POSITIVE_INFINITY POSITIVE_INFINITY} sort to the beginning and the end of the dataset, as
 * you would expect.
 *
 *
If required to do a weighted average between an infinity and a finite value, or between an
 * infinite value and itself, the infinite value is returned. If required to do a weighted average
 * between {@link Double#NEGATIVE_INFINITY NEGATIVE_INFINITY} and {@link Double#POSITIVE_INFINITY
 * POSITIVE_INFINITY}, {@link Double#NaN NaN} is returned (note that this will only happen if the
 * dataset contains no finite values).
 *
 *
Performance

 *
 *
The average time complexity of the computation is O(N) in the size of the dataset. There is a
 * worst case time complexity of O(N^2). You are extremely unlikely to hit this quadratic case on
 * randomly ordered data (the probability decreases faster than exponentially in N), but if you are
 * passing in unsanitized user data then a malicious user could force it. A light shuffle of the
 * data using an unpredictable seed should normally be enough to thwart this attack.
 *
 *
The time taken to compute multiple quantiles on the same dataset using {@link Scale#indexes
 * indexes} is generally less than the total time taken to compute each of them separately, and
 * sometimes much less. For example, on a large enough dataset, computing the 90th and 99th
 * percentiles together takes about 55% as long as computing them separately.
 *
 *
When calling {@link ScaleAndIndex#compute} (in {@linkplain ScaleAndIndexes#compute either
 * form}), the memory requirement is 8*N bytes for the copy of the dataset plus an overhead which is
 * independent of N (but depends on the quantiles being computed). When calling {@link
 * ScaleAndIndex#computeInPlace computeInPlace} (in {@linkplain ScaleAndIndexes#computeInPlace
 * either form}), only the overhead is required. The number of object allocations is independent of
 * N in both cases.
 *
 * @author Pete Gillin
 * @since 20.0
 */
@Beta
@GwtIncompatible
public final class Quantiles {

  /** Specifies the computation of a median (i.e. the 1st 2-quantile). */
  public static ScaleAndIndex median() {
    return scale(2).index(1);
  }

  /** Specifies the computation of quartiles (i.e. 4-quantiles). */
  public static Scale quartiles() {
    return scale(4);
  }

  /** Specifies the computation of percentiles (i.e. 100-quantiles). */
  public static Scale percentiles() {
    return scale(100);
  }

  /**
   * Specifies the computation of q-quantiles.
   *
   * @param scale the scale for the quantiles to be calculated, i.e. the q of the q-quantiles, which
   *     must be positive
   */
  public static Scale scale(int scale) {
    return new Scale(scale);
  }

  /**
   * Describes the point in a fluent API chain where only the scale (i.e. the q in q-quantiles) has
   * been specified.
   *
   * @since 20.0
   */
  public static final class Scale {

    private final int scale;

    private Scale(int scale) {
      checkArgument(scale > 0, "Quantile scale must be positive");
      this.scale = scale;
    }

    /**
     * Specifies a single quantile index to be calculated, i.e. the k in the kth q-quantile.
     *
     * @param index the quantile index, which must be in the inclusive range [0, q] for q-quantiles
     */
    public ScaleAndIndex index(int index) {
      return new ScaleAndIndex(scale, index);
    }

    /**
     * Specifies multiple quantile indexes to be calculated, each index being the k in the kth
     * q-quantile.
     *
     * @param indexes the quantile indexes, each of which must be in the inclusive range [0, q] for
     *     q-quantiles; the order of the indexes is unimportant, duplicates will be ignored, and the
     *     set will be snapshotted when this method is called
     */
    public ScaleAndIndexes indexes(int... indexes) {
      return new ScaleAndIndexes(scale, indexes.clone());
    }

    /**
     * Specifies multiple quantile indexes to be calculated, each index being the k in the kth
     * q-quantile.
     *
     * @param indexes the quantile indexes, each of which must be in the inclusive range [0, q] for
     *     q-quantiles; the order of the indexes is unimportant, duplicates will be ignored, and the
     *     set will be snapshotted when this method is called
     */
    public ScaleAndIndexes indexes(Collection<Integer> indexes) {
      return new ScaleAndIndexes(scale, Ints.toArray(indexes));
    }
  }

  /**
   * Describes the point in a fluent API chain where the scale and a single quantile index (i.e. the
   * q and the k in the kth q-quantile) have been specified.
   *
   * @since 20.0
   */
  public static final class ScaleAndIndex {

    private final int scale;
    private final int index;

    private ScaleAndIndex(int scale, int index) {
      checkIndex(index, scale);
      this.scale = scale;
      this.index = index;
    }

    /**
     * Computes the quantile value of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles (with any associated lost of precision), and which will not be mutated by
     *     this call (it is copied instead)
     * @return the quantile value
     */
    public double compute(Collection<? extends Number> dataset) {
      return computeInPlace(Doubles.toArray(dataset));
    }

    /**
     * Computes the quantile value of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will not
     *     be mutated by this call (it is copied instead)
     * @return the quantile value
     */
    public double compute(double... dataset) {
      return computeInPlace(dataset.clone());
    }

    /**
     * Computes the quantile value of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles (with any associated lost of precision), and which will not be mutated by
     *     this call (it is copied instead)
     * @return the quantile value
     */
    public double compute(long... dataset) {
      return computeInPlace(longsToDoubles(dataset));
    }

    /**
     * Computes the quantile value of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles, and which will not be mutated by this call (it is copied instead)
     * @return the quantile value
     */
    public double compute(int... dataset) {
      return computeInPlace(intsToDoubles(dataset));
    }

    /**
     * Computes the quantile value of the given dataset, performing the computation in-place.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, and which will
     *     be arbitrarily reordered by this method call
     * @return the quantile value
     */
    public double computeInPlace(double... dataset) {
      checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
      if (containsNaN(dataset)) {
        return NaN;
      }

      // Calculate the quotient and remainder in the integer division x = k * (N-1) / q, i.e.
      // index * (dataset.length - 1) / scale. If there is no remainder, we can just find the value
      // whose index in the sorted dataset equals the quotient; if there is a remainder, we
      // interpolate between that and the next value.

      // Since index and (dataset.length - 1) are non-negative ints, their product can be expressed
      // as a long, without risk of overflow:
      long numerator = (long) index * (dataset.length - 1);
      // Since scale is a positive int, index is in [0, scale], and (dataset.length - 1) is a
      // non-negative int, we can do long-arithmetic on index * (dataset.length - 1) / scale to get
      // a rounded ratio and a remainder which can be expressed as ints, without risk of overflow:
      int quotient = (int) LongMath.divide(numerator, scale, RoundingMode.DOWN);
      int remainder = (int) (numerator - (long) quotient * scale);
      selectInPlace(quotient, dataset, 0, dataset.length - 1);
      if (remainder == 0) {
        return dataset[quotient];
      } else {
        selectInPlace(quotient + 1, dataset, quotient + 1, dataset.length - 1);
        return interpolate(dataset[quotient], dataset[quotient + 1], remainder, scale);
      }
    }
  }

  /**
   * Describes the point in a fluent API chain where the scale and a multiple quantile indexes (i.e.
   * the q and a set of values for the k in the kth q-quantile) have been specified.
   *
   * @since 20.0
   */
  public static final class ScaleAndIndexes {

    private final int scale;
    private final int[] indexes;

    private ScaleAndIndexes(int scale, int[] indexes) {
      for (int index : indexes) {
        checkIndex(index, scale);
      }
      this.scale = scale;
      this.indexes = indexes;
    }

    /**
     * Computes the quantile values of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles (with any associated lost of precision), and which will not be mutated by
     *     this call (it is copied instead)
     * @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
     *     the values the corresponding quantile values
     */
    public Map<Integer, Double> compute(Collection<? extends Number> dataset) {
      return computeInPlace(Doubles.toArray(dataset));
    }

    /**
     * Computes the quantile values of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will not
     *     be mutated by this call (it is copied instead)
     * @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
     *     the values the corresponding quantile values
     */
    public Map<Integer, Double> compute(double... dataset) {
      return computeInPlace(dataset.clone());
    }

    /**
     * Computes the quantile values of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles (with any associated lost of precision), and which will not be mutated by
     *     this call (it is copied instead)
     * @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
     *     the values the corresponding quantile values
     */
    public Map<Integer, Double> compute(long... dataset) {
      return computeInPlace(longsToDoubles(dataset));
    }

    /**
     * Computes the quantile values of the given dataset.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, which will be
     *     cast to doubles, and which will not be mutated by this call (it is copied instead)
     * @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
     *     the values the corresponding quantile values
     */
    public Map<Integer, Double> compute(int... dataset) {
      return computeInPlace(intsToDoubles(dataset));
    }

    /**
     * Computes the quantile values of the given dataset, performing the computation in-place.
     *
     * @param dataset the dataset to do the calculation on, which must be non-empty, and which will
     *     be arbitrarily reordered by this method call
     * @return an unmodifiable map of results: the keys will be the specified quantile indexes, and
     *     the values the corresponding quantile values
     */
    public Map<Integer, Double> computeInPlace(double... dataset) {
      checkArgument(dataset.length > 0, "Cannot calculate quantiles of an empty dataset");
      if (containsNaN(dataset)) {
        Map<Integer, Double> nanMap = new HashMap<>();
        for (int index : indexes) {
          nanMap.put(index, NaN);
        }
        return unmodifiableMap(nanMap);
      }

      // Calculate the quotients and remainders in the integer division x = k * (N - 1) / q, i.e.
      // index * (dataset.length - 1) / scale for each index in indexes. For each, if there is no
      // remainder, we can just select the value whose index in the sorted dataset equals the
      // quotient; if there is a remainder, we interpolate between that and the next value.

      int[] quotients = new int[indexes.length];
      int[] remainders = new int[indexes.length];
      // The indexes to select. In the worst case, we'll need one each side of each quantile.
      int[] requiredSelections = new int[indexes.length * 2];
      int requiredSelectionsCount = 0;
      for (int i = 0; i < indexes.length; i++) {
        // Since index and (dataset.length - 1) are non-negative ints, their product can be
        // expressed as a long, without risk of overflow:
        long numerator = (long) indexes[i] * (dataset.length - 1);
        // Since scale is a positive int, index is in [0, scale], and (dataset.length - 1) is a
        // non-negative int, we can do long-arithmetic on index * (dataset.length - 1) / scale to
        // get a rounded ratio and a remainder which can be expressed as ints, without risk of
        // overflow:
        int quotient = (int) LongMath.divide(numerator, scale, RoundingMode.DOWN);
        int remainder = (int) (numerator - (long) quotient * scale);
        quotients[i] = quotient;
        remainders[i] = remainder;
        requiredSelections[requiredSelectionsCount] = quotient;
        requiredSelectionsCount++;
        if (remainder != 0) {
          requiredSelections[requiredSelectionsCount] = quotient + 1;
          requiredSelectionsCount++;
        }
      }
      sort(requiredSelections, 0, requiredSelectionsCount);
      selectAllInPlace(
          requiredSelections, 0, requiredSelectionsCount - 1, dataset, 0, dataset.length - 1);
      Map<Integer, Double> ret = new HashMap<>();
      for (int i = 0; i < indexes.length; i++) {
        int quotient = quotients[i];
        int remainder = remainders[i];
        if (remainder == 0) {
          ret.put(indexes[i], dataset[quotient]);
        } else {
          ret.put(
              indexes[i], interpolate(dataset[quotient], dataset[quotient + 1], remainder, scale));
        }
      }
      return unmodifiableMap(ret);
    }
  }

  /** Returns whether any of the values in {@code dataset} are {@code NaN}. */
  private static boolean containsNaN(double... dataset) {
    for (double value : dataset) {
      if (Double.isNaN(value)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns a value a fraction {@code (remainder / scale)} of the way between {@code lower} and
   * {@code upper}. Assumes that {@code lower <= upper}. Correctly handles infinities (but not
   * {@code NaN}).
   */
  private static double interpolate(double lower, double upper, double remainder, double scale) {
    if (lower == NEGATIVE_INFINITY) {
      if (upper == POSITIVE_INFINITY) {
        // Return NaN when lower == NEGATIVE_INFINITY and upper == POSITIVE_INFINITY:
        return NaN;
      }
      // Return NEGATIVE_INFINITY when NEGATIVE_INFINITY == lower <= upper < POSITIVE_INFINITY:
      return NEGATIVE_INFINITY;
    }
    if (upper == POSITIVE_INFINITY) {
      // Return POSITIVE_INFINITY when NEGATIVE_INFINITY < lower <= upper == POSITIVE_INFINITY:
      return POSITIVE_INFINITY;
    }
    return lower + (upper - lower) * remainder / scale;
  }

  private static void checkIndex(int index, int scale) {
    if (index < 0 || index > scale) {
      throw new IllegalArgumentException(
          "Quantile indexes must be between 0 and the scale, which is " + scale);
    }
  }

  private static double[] longsToDoubles(long[] longs) {
    int len = longs.length;
    double[] doubles = new double[len];
    for (int i = 0; i < len; i++) {
      doubles[i] = longs[i];
    }
    return doubles;
  }

  private static double[] intsToDoubles(int[] ints) {
    int len = ints.length;
    double[] doubles = new double[len];
    for (int i = 0; i < len; i++) {
      doubles[i] = ints[i];
    }
    return doubles;
  }

  /**
   * Performs an in-place selection to find the element which would appear at a given index in a
   * dataset if it were sorted. The following preconditions should hold:
   *
   *

   *
{@code required}, {@code from}, and {@code to} should all be indexes into {@code array};
   *
{@code required} should be in the range [{@code from}, {@code to}];
   *
all the values with indexes in the range [0, {@code from}) should be less than or equal
   *       to all the values with indexes in the range [{@code from}, {@code to}];
   *
all the values with indexes in the range ({@code to}, {@code array.length - 1}] should be
   *       greater than or equal to all the values with indexes in the range [{@code from}, {@code
   *       to}].
   *

   *
   * This method will reorder the values with indexes in the range [{@code from}, {@code to}] such
   * that all the values with indexes in the range [{@code from}, {@code required}) are less than or
   * equal to the value with index {@code required}, and all the values with indexes in the range
   * ({@code required}, {@code to}] are greater than or equal to that value. Therefore, the value at
   * {@code required} is the value which would appear at that index in the sorted dataset.
   */
  private static void selectInPlace(int required, double[] array, int from, int to) {
    // If we are looking for the least element in the range, we can just do a linear search for it.
    // (We will hit this whenever we are doing quantile interpolation: our first selection finds
    // the lower value, our second one finds the upper value by looking for the next least element.)
    if (required == from) {
      int min = from;
      for (int index = from + 1; index <= to; index++) {
        if (array[min] > array[index]) {
          min = index;
        }
      }
      if (min != from) {
        swap(array, min, from);
      }
      return;
    }

    // Let's play quickselect! We'll repeatedly partition the range [from, to] containing the
    // required element, as long as it has more than one element.
    while (to > from) {
      int partitionPoint = partition(array, from, to);
      if (partitionPoint >= required) {
        to = partitionPoint - 1;
      }
      if (partitionPoint <= required) {
        from = partitionPoint + 1;
      }
    }
  }

  /**
   * Performs a partition operation on the slice of {@code array} with elements in the range [{@code
   * from}, {@code to}]. Uses the median of {@code from}, {@code to}, and the midpoint between them
   * as a pivot. Returns the index which the slice is partitioned around, i.e. if it returns {@code
   * ret} then we know that the values with indexes in [{@code from}, {@code ret}) are less than or
   * equal to the value at {@code ret} and the values with indexes in ({@code ret}, {@code to}] are
   * greater than or equal to that.
   */
  private static int partition(double[] array, int from, int to) {
    // Select a pivot, and move it to the start of the slice i.e. to index from.
    movePivotToStartOfSlice(array, from, to);
    double pivot = array[from];

    // Move all elements with indexes in (from, to] which are greater than the pivot to the end of
    // the array. Keep track of where those elements begin.
    int partitionPoint = to;
    for (int i = to; i > from; i--) {
      if (array[i] > pivot) {
        swap(array, partitionPoint, i);
        partitionPoint--;
      }
    }

    // We now know that all elements with indexes in (from, partitionPoint] are less than or equal
    // to the pivot at from, and all elements with indexes in (partitionPoint, to] are greater than
    // it. We swap the pivot into partitionPoint and we know the array is partitioned around that.
    swap(array, from, partitionPoint);
    return partitionPoint;
  }

  /**
   * Selects the pivot to use, namely the median of the values at {@code from}, {@code to}, and
   * halfway between the two (rounded down), from {@code array}, and ensure (by swapping elements if
   * necessary) that that pivot value appears at the start of the slice i.e. at {@code from}.
   * Expects that {@code from} is strictly less than {@code to}.
   */
  private static void movePivotToStartOfSlice(double[] array, int from, int to) {
    int mid = (from + to) >>> 1;
    // We want to make a swap such that either array[to] <= array[from] <= array[mid], or
    // array[mid] <= array[from] <= array[to]. We know that from < to, so we know mid < to
    // (although it's possible that mid == from, if to == from + 1). Note that the postcondition
    // would be impossible to fulfil if mid == to unless we also have array[from] == array[to].
    boolean toLessThanMid = (array[to] < array[mid]);
    boolean midLessThanFrom = (array[mid] < array[from]);
    boolean toLessThanFrom = (array[to] < array[from]);
    if (toLessThanMid == midLessThanFrom) {
      // Either array[to] < array[mid] < array[from] or array[from] <= array[mid] <= array[to].
      swap(array, mid, from);
    } else if (toLessThanMid != toLessThanFrom) {
      // Either array[from] <= array[to] < array[mid] or array[mid] <= array[to] < array[from].
      swap(array, from, to);
    }
    // The postcondition now holds. So the median, our chosen pivot, is at from.
  }

  /**
   * Performs an in-place selection, like {@link #selectInPlace}, to select all the indexes {@code
   * allRequired[i]} for {@code i} in the range [{@code requiredFrom}, {@code requiredTo}]. These
   * indexes must be sorted in the array and must all be in the range [{@code from}, {@code to}].
   */
  private static void selectAllInPlace(
      int[] allRequired, int requiredFrom, int requiredTo, double[] array, int from, int to) {
    // Choose the first selection to do...
    int requiredChosen = chooseNextSelection(allRequired, requiredFrom, requiredTo, from, to);
    int required = allRequired[requiredChosen];

    // ...do the first selection...
    selectInPlace(required, array, from, to);

    // ...then recursively perform the selections in the range below...
    int requiredBelow = requiredChosen - 1;
    while (requiredBelow >= requiredFrom && allRequired[requiredBelow] == required) {
      requiredBelow--; // skip duplicates of required in the range below
    }
    if (requiredBelow >= requiredFrom) {
      selectAllInPlace(allRequired, requiredFrom, requiredBelow, array, from, required - 1);
    }

    // ...and then recursively perform the selections in the range above.
    int requiredAbove = requiredChosen + 1;
    while (requiredAbove <= requiredTo && allRequired[requiredAbove] == required) {
      requiredAbove++; // skip duplicates of required in the range above
    }
    if (requiredAbove <= requiredTo) {
      selectAllInPlace(allRequired, requiredAbove, requiredTo, array, required + 1, to);
    }
  }

  /**
   * Chooses the next selection to do from the required selections. It is required that the array
   * {@code allRequired} is sorted and that {@code allRequired[i]} are in the range [{@code from},
   * {@code to}] for all {@code i} in the range [{@code requiredFrom}, {@code requiredTo}]. The
   * value returned by this method is the {@code i} in that range such that {@code allRequired[i]}
   * is as close as possible to the center of the range [{@code from}, {@code to}]. Choosing the
   * value closest to the center of the range first is the most efficient strategy because it
   * minimizes the size of the subranges from which the remaining selections must be done.
   */
  private static int chooseNextSelection(
      int[] allRequired, int requiredFrom, int requiredTo, int from, int to) {
    if (requiredFrom == requiredTo) {
      return requiredFrom; // only one thing to choose, so choose it
    }

    // Find the center and round down. The true center is either centerFloor or halfway between
    // centerFloor and centerFloor + 1.
    int centerFloor = (from + to) >>> 1;

    // Do a binary search until we're down to the range of two which encloses centerFloor (unless
    // all values are lower or higher than centerFloor, in which case we find the two highest or
    // lowest respectively). If centerFloor is in allRequired, we will definitely find it. If not,
    // but centerFloor + 1 is, we'll definitely find that. The closest value to the true (unrounded)
    // center will be at either low or high.
    int low = requiredFrom;
    int high = requiredTo;
    while (high > low + 1) {
      int mid = (low + high) >>> 1;
      if (allRequired[mid] > centerFloor) {
        high = mid;
      } else if (allRequired[mid] < centerFloor) {
        low = mid;
      } else {
        return mid; // allRequired[mid] = centerFloor, so we can't get closer than that
      }
    }

    // Now pick the closest of the two candidates. Note that there is no rounding here.
    if (from + to - allRequired[low] - allRequired[high] > 0) {
      return high;
    } else {
      return low;
    }
  }

  /** Swaps the values at {@code i} and {@code j} in {@code array}. */
  private static void swap(double[] array, int i, int j) {
    double temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
}


/*
 * Copyright (C) 2008 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.collect;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Supplier;
import com.google.j2objc.annotations.WeakOuter;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;

/**
 * Implementation of {@code Table} whose iteration ordering across row keys is sorted by their
 * natural ordering or by a supplied comparator. Note that iterations across the columns keys for a
 * single row key may or may not be ordered, depending on the implementation. When rows and columns
 * are both sorted, it's easier to use the {@link TreeBasedTable} subclass.
 *
 *
The {@link #rowKeySet} method returns a {@link SortedSet} and the {@link #rowMap} method
 * returns a {@link SortedMap}, instead of the {@link Set} and {@link Map} specified by the {@link
 * Table} interface.
 *
 *
Null keys and values are not supported.
 *
 *
See the {@link StandardTable} superclass for more information about the behavior of this
 * class.
 *
 * @author Jared Levy
 */
@GwtCompatible
class StandardRowSortedTable<R, C, V> extends StandardTable<R, C, V>
    implements RowSortedTable<R, C, V> {
  /*
   * TODO(jlevy): Consider adding headTable, tailTable, and subTable methods,
   * which return a Table view with rows keys in a given range. Create a
   * RowSortedTable subinterface with the revised methods?
   */

  StandardRowSortedTable(
      SortedMap<R, Map<C, V>> backingMap, Supplier<? extends Map<C, V>> factory) {
    super(backingMap, factory);
  }

  private SortedMap<R, Map<C, V>> sortedBackingMap() {
    return (SortedMap<R, Map<C, V>>) backingMap;
  }

  /**
   * {@inheritDoc}
   *
   *
This method returns a {@link SortedSet}, instead of the {@code Set} specified in the {@link
   * Table} interface.
   */
  @Override
  public SortedSet<R> rowKeySet() {
    return (SortedSet<R>) rowMap().keySet();
  }

  /**
   * {@inheritDoc}
   *
   *
This method returns a {@link SortedMap}, instead of the {@code Map} specified in the {@link
   * Table} interface.
   */
  @Override
  public SortedMap<R, Map<C, V>> rowMap() {
    return (SortedMap<R, Map<C, V>>) super.rowMap();
  }

  @Override
  SortedMap<R, Map<C, V>> createRowMap() {
    return new RowSortedMap();
  }

  @WeakOuter
  private class RowSortedMap extends RowMap implements SortedMap<R, Map<C, V>> {
    @Override
    public SortedSet<R> keySet() {
      return (SortedSet<R>) super.keySet();
    }

    @Override
    SortedSet<R> createKeySet() {
      return new Maps.SortedKeySet<>(this);
    }

    @Override
    public Comparator<? super R> comparator() {
      return sortedBackingMap().comparator();
    }

    @Override
    public R firstKey() {
      return sortedBackingMap().firstKey();
    }

    @Override
    public R lastKey() {
      return sortedBackingMap().lastKey();
    }

    @Override
    public SortedMap<R, Map<C, V>> headMap(R toKey) {
      checkNotNull(toKey);
      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().headMap(toKey), factory)
          .rowMap();
    }

    @Override
    public SortedMap<R, Map<C, V>> subMap(R fromKey, R toKey) {
      checkNotNull(fromKey);
      checkNotNull(toKey);
      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().subMap(fromKey, toKey), factory)
          .rowMap();
    }

    @Override
    public SortedMap<R, Map<C, V>> tailMap(R fromKey) {
      checkNotNull(fromKey);
      return new StandardRowSortedTable<R, C, V>(sortedBackingMap().tailMap(fromKey), factory)
          .rowMap();
    }
  }

  private static final long serialVersionUID = 0;
}


/*
 * Copyright (C) 2008 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.primitives;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.POSITIVE_INFINITY;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * Static utility methods pertaining to {@code double} primitives, that are not already found in
 * either {@link Double} or {@link Arrays}.
 *
 *
See the Guava User Guide article on primitive utilities.
 *
 * @author Kevin Bourrillion
 * @since 1.0
 */
@GwtCompatible(emulated = true)
public final class Doubles {
  private Doubles() {}

  /**
   * The number of bytes required to represent a primitive {@code double} value.
   *
   *
Java 8 users: use {@link Double#BYTES} instead.
   *
   * @since 10.0
   */
  public static final int BYTES = Double.SIZE / Byte.SIZE;

  /**
   * Returns a hash code for {@code value}; equal to the result of invoking {@code ((Double)
   * value).hashCode()}.
   *
   *
Java 8 users: use {@link Double#hashCode(double)} instead.
   *
   * @param value a primitive {@code double} value
   * @return a hash code for the value
   */
  public static int hashCode(double value) {
    return ((Double) value).hashCode();
    // TODO(kevinb): do it this way when we can (GWT problem):
    // long bits = Double.doubleToLongBits(value);
    // return (int) (bits ^ (bits >>> 32));
  }

  /**
   * Compares the two specified {@code double} values. The sign of the value returned is the same as
   * that of ((Double) a).{@linkplain Double#compareTo compareTo}(b). As with that
   * method, {@code NaN} is treated as greater than all other values, and {@code 0.0 > -0.0}.
   *
   *
Note: this method simply delegates to the JDK method {@link Double#compare}. It is
   * provided for consistency with the other primitive types, whose compare methods were not added
   * to the JDK until JDK 7.
   *
   * @param a the first {@code double} to compare
   * @param b the second {@code double} to compare
   * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
   *     greater than {@code b}; or zero if they are equal
   */
  public static int compare(double a, double b) {
    return Double.compare(a, b);
  }

  /**
   * Returns {@code true} if {@code value} represents a real number. This is equivalent to, but not
   * necessarily implemented as, {@code !(Double.isInfinite(value) || Double.isNaN(value))}.
   *
   *
Java 8 users: use {@link Double#isFinite(double)} instead.
   *
   * @since 10.0
   */
  public static boolean isFinite(double value) {
    return NEGATIVE_INFINITY < value && value < POSITIVE_INFINITY;
  }

  /**
   * Returns {@code true} if {@code target} is present as an element anywhere in {@code array}. Note
   * that this always returns {@code false} when {@code target} is {@code NaN}.
   *
   * @param array an array of {@code double} values, possibly empty
   * @param target a primitive {@code double} value
   * @return {@code true} if {@code array[i] == target} for some value of {@code i}
   */
  public static boolean contains(double[] array, double target) {
    for (double value : array) {
      if (value == target) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns the index of the first appearance of the value {@code target} in {@code array}. Note
   * that this always returns {@code -1} when {@code target} is {@code NaN}.
   *
   * @param array an array of {@code double} values, possibly empty
   * @param target a primitive {@code double} value
   * @return the least index {@code i} for which {@code array[i] == target}, or {@code -1} if no
   *     such index exists.
   */
  public static int indexOf(double[] array, double target) {
    return indexOf(array, target, 0, array.length);
  }

  // TODO(kevinb): consider making this public
  private static int indexOf(double[] array, double target, int start, int end) {
    for (int i = start; i < end; i++) {
      if (array[i] == target) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Returns the start position of the first occurrence of the specified {@code target} within
   * {@code array}, or {@code -1} if there is no such occurrence.
   *
   *
More formally, returns the lowest index {@code i} such that {@code Arrays.copyOfRange(array,
   * i, i + target.length)} contains exactly the same elements as {@code target}.
   *
   *
Note that this always returns {@code -1} when {@code target} contains {@code NaN}.
   *
   * @param array the array to search for the sequence {@code target}
   * @param target the array to search for as a sub-sequence of {@code array}
   */
  public static int indexOf(double[] array, double[] target) {
    checkNotNull(array, "array");
    checkNotNull(target, "target");
    if (target.length == 0) {
      return 0;
    }

    outer:
    for (int i = 0; i < array.length - target.length + 1; i++) {
      for (int j = 0; j < target.length; j++) {
        if (array[i + j] != target[j]) {
          continue outer;
        }
      }
      return i;
    }
    return -1;
  }

  /**
   * Returns the index of the last appearance of the value {@code target} in {@code array}. Note
   * that this always returns {@code -1} when {@code target} is {@code NaN}.
   *
   * @param array an array of {@code double} values, possibly empty
   * @param target a primitive {@code double} value
   * @return the greatest index {@code i} for which {@code array[i] == target}, or {@code -1} if no
   *     such index exists.
   */
  public static int lastIndexOf(double[] array, double target) {
    return lastIndexOf(array, target, 0, array.length);
  }

  // TODO(kevinb): consider making this public
  private static int lastIndexOf(double[] array, double target, int start, int end) {
    for (int i = end - 1; i >= start; i--) {
      if (array[i] == target) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Returns the least value present in {@code array}, using the same rules of comparison as {@link
   * Math#min(double, double)}.
   *
   * @param array a nonempty array of {@code double} values
   * @return the value present in {@code array} that is less than or equal to every other value in
   *     the array
   * @throws IllegalArgumentException if {@code array} is empty
   */
  public static double min(double... array) {
    checkArgument(array.length > 0);
    double min = array[0];
    for (int i = 1; i < array.length; i++) {
      min = Math.min(min, array[i]);
    }
    return min;
  }

  /**
   * Returns the greatest value present in {@code array}, using the same rules of comparison as
   * {@link Math#max(double, double)}.
   *
   * @param array a nonempty array of {@code double} values
   * @return the value present in {@code array} that is greater than or equal to every other value
   *     in the array
   * @throws IllegalArgumentException if {@code array} is empty
   */
  public static double max(double... array) {
    checkArgument(array.length > 0);
    double max = array[0];
    for (int i = 1; i < array.length; i++) {
      max = Math.max(max, array[i]);
    }
    return max;
  }

  /**
   * Returns the value nearest to {@code value} which is within the closed range {@code [min..max]}.
   *
   *
If {@code value} is within the range {@code [min..max]}, {@code value} is returned
   * unchanged. If {@code value} is less than {@code min}, {@code min} is returned, and if {@code
   * value} is greater than {@code max}, {@code max} is returned.
   *
   * @param value the {@code double} value to constrain
   * @param min the lower bound (inclusive) of the range to constrain {@code value} to
   * @param max the upper bound (inclusive) of the range to constrain {@code value} to
   * @throws IllegalArgumentException if {@code min > max}
   * @since 21.0
   */
  @Beta
  public static double constrainToRange(double value, double min, double max) {
    checkArgument(min <= max, "min (%s) must be less than or equal to max (%s)", min, max);
    return Math.min(Math.max(value, min), max);
  }

  /**
   * Returns the values from each provided array combined into a single array. For example, {@code
   * concat(new double[] {a, b}, new double[] {}, new double[] {c}} returns the array {@code {a, b,
   * c}}.
   *
   * @param arrays zero or more {@code double} arrays
   * @return a single array containing all the values from the source arrays, in order
   */
  public static double[] concat(double[]... arrays) {
    int length = 0;
    for (double[] array : arrays) {
      length += array.length;
    }
    double[] result = new double[length];
    int pos = 0;
    for (double[] array : arrays) {
      System.arraycopy(array, 0, result, pos, array.length);
      pos += array.length;
    }
    return result;
  }

  private static final class DoubleConverter extends Converter<String, Double>
      implements Serializable {
    static final DoubleConverter INSTANCE = new DoubleConverter();

    @Override
    protected Double doForward(String value) {
      return Double.valueOf(value);
    }

    @Override
    protected String doBackward(Double value) {
      return value.toString();
    }

    @Override
    public String toString() {
      return "Doubles.stringConverter()";
    }

    private Object readResolve() {
      return INSTANCE;
    }

    private static final long serialVersionUID = 1;
  }

  /**
   * Returns a serializable converter object that converts between strings and doubles using {@link
   * Double#valueOf} and {@link Double#toString()}.
   *
   * @since 16.0
   */
  @Beta
  public static Converter<String, Double> stringConverter() {
    return DoubleConverter.INSTANCE;
  }

  /**
   * Returns an array containing the same values as {@code array}, but guaranteed to be of a
   * specified minimum length. If {@code array} already has a length of at least {@code minLength},
   * it is returned directly. Otherwise, a new array of size {@code minLength + padding} is
   * returned, containing the values of {@code array}, and zeroes in the remaining places.
   *
   * @param array the source array
   * @param minLength the minimum length the returned array must guarantee
   * @param padding an extra amount to "grow" the array by if growth is necessary
   * @throws IllegalArgumentException if {@code minLength} or {@code padding} is negative
   * @return an array containing the values of {@code array}, with guaranteed minimum length {@code
   *     minLength}
   */
  public static double[] ensureCapacity(double[] array, int minLength, int padding) {
    checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
    checkArgument(padding >= 0, "Invalid padding: %s", padding);
    return (array.length < minLength) ? Arrays.copyOf(array, minLength + padding) : array;
  }

  /**
   * Returns a string containing the supplied {@code double} values, converted to strings as
   * specified by {@link Double#toString(double)}, and separated by {@code separator}. For example,
   * {@code join("-", 1.0, 2.0, 3.0)} returns the string {@code "1.0-2.0-3.0"}.
   *
   *
Note that {@link Double#toString(double)} formats {@code double} differently in GWT
   * sometimes. In the previous example, it returns the string {@code "1-2-3"}.
   *
   * @param separator the text that should appear between consecutive values in the resulting string
   *     (but not at the start or end)
   * @param array an array of {@code double} values, possibly empty
   */
  public static String join(String separator, double... array) {
    checkNotNull(separator);
    if (array.length == 0) {
      return "";
    }

    // For pre-sizing a builder, just get the right order of magnitude
    StringBuilder builder = new StringBuilder(array.length * 12);
    builder.append(array[0]);
    for (int i = 1; i < array.length; i++) {
      builder.append(separator).append(array[i]);
    }
    return builder.toString();
  }

  /**
   * Returns a comparator that compares two {@code double} arrays lexicographically. That is, it
   * compares, using {@link #compare(double, double)}), the first pair of values that follow any
   * common prefix, or when one array is a prefix of the other, treats the shorter array as the
   * lesser. For example, {@code [] < [1.0] < [1.0, 2.0] < [2.0]}.
   *
   *
The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays
   * support only identity equality), but it is consistent with {@link Arrays#equals(double[],
   * double[])}.
   *
   * @since 2.0
   */
  public static Comparator<double[]> lexicographicalComparator() {
    return LexicographicalComparator.INSTANCE;
  }

  private enum LexicographicalComparator implements Comparator<double[]> {
    INSTANCE;

    @Override
    public int compare(double[] left, double[] right) {
      int minLength = Math.min(left.length, right.length);
      for (int i = 0; i < minLength; i++) {
        int result = Double.compare(left[i], right[i]);
        if (result != 0) {
          return result;
        }
      }
      return left.length - right.length;
    }

    @Override
    public String toString() {
      return "Doubles.lexicographicalComparator()";
    }
  }

  /**
   * Sorts the elements of {@code array} in descending order.
   *
   *
Note that this method uses the total order imposed by {@link Double#compare}, which treats
   * all NaN values as equal and 0.0 as greater than -0.0.
   *
   * @since 23.1
   */
  public static void sortDescending(double[] array) {
    checkNotNull(array);
    sortDescending(array, 0, array.length);
  }

  /**
   * Sorts the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
   * exclusive in descending order.
   *
   *
Note that this method uses the total order imposed by {@link Double#compare}, which treats
   * all NaN values as equal and 0.0 as greater than -0.0.
   *
   * @since 23.1
   */
  public static void sortDescending(double[] array, int fromIndex, int toIndex) {
    checkNotNull(array);
    checkPositionIndexes(fromIndex, toIndex, array.length);
    Arrays.sort(array, fromIndex, toIndex);
    reverse(array, fromIndex, toIndex);
  }

  /**
   * Reverses the elements of {@code array}. This is equivalent to {@code
   * Collections.reverse(Doubles.asList(array))}, but is likely to be more efficient.
   *
   * @since 23.1
   */
  public static void reverse(double[] array) {
    checkNotNull(array);
    reverse(array, 0, array.length);
  }

  /**
   * Reverses the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
   * exclusive. This is equivalent to {@code
   * Collections.reverse(Doubles.asList(array).subList(fromIndex, toIndex))}, but is likely to be
   * more efficient.
   *
   * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
   *     {@code toIndex > fromIndex}
   * @since 23.1
   */
  public static void reverse(double[] array, int fromIndex, int toIndex) {
    checkNotNull(array);
    checkPositionIndexes(fromIndex, toIndex, array.length);
    for (int i = fromIndex, j = toIndex - 1; i < j; i++, j--) {
      double tmp = array[i];
      array[i] = array[j];
      array[j] = tmp;
    }
  }

  /**
   * Returns an array containing each value of {@code collection}, converted to a {@code double}
   * value in the manner of {@link Number#doubleValue}.
   *
   *
Elements are copied from the argument collection as if by {@code collection.toArray()}.
   * Calling this method is as thread-safe as calling that method.
   *
   * @param collection a collection of {@code Number} instances
   * @return an array containing the same values as {@code collection}, in the same order, converted
   *     to primitives
   * @throws NullPointerException if {@code collection} or any of its elements is null
   * @since 1.0 (parameter was {@code Collection<Double>} before 12.0)
   */
  public static double[] toArray(Collection<? extends Number> collection) {
    if (collection instanceof DoubleArrayAsList) {
      return ((DoubleArrayAsList) collection).toDoubleArray();
    }

    Object[] boxedArray = collection.toArray();
    int len = boxedArray.length;
    double[] array = new double[len];
    for (int i = 0; i < len; i++) {
      // checkNotNull for GWT (do not optimize)
      array[i] = ((Number) checkNotNull(boxedArray[i])).doubleValue();
    }
    return array;
  }

  /**
   * Returns a fixed-size list backed by the specified array, similar to {@link
   * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)}, but any attempt to
   * set a value to {@code null} will result in a {@link NullPointerException}.
   *
   *
The returned list maintains the values, but not the identities, of {@code Double} objects
   * written to or read from it. For example, whether {@code list.get(0) == list.get(0)} is true for
   * the returned list is unspecified.
   *
   *
The returned list may have unexpected behavior if it contains {@code NaN}, or if {@code NaN}
   * is used as a parameter to any of its methods.
   *
   *
Note: when possible, you should represent your data as an {@link
   * ImmutableDoubleArray} instead, which has an {@link ImmutableDoubleArray#asList asList} view.
   *
   * @param backingArray the array to back the list
   * @return a list view of the array
   */
  public static List<Double> asList(double... backingArray) {
    if (backingArray.length == 0) {
      return Collections.emptyList();
    }
    return new DoubleArrayAsList(backingArray);
  }

  @GwtCompatible
  private static class DoubleArrayAsList extends AbstractList<Double>
      implements RandomAccess, Serializable {
    final double[] array;
    final int start;
    final int end;

    DoubleArrayAsList(double[] array) {
      this(array, 0, array.length);
    }

    DoubleArrayAsList(double[] array, int start, int end) {
      this.array = array;
      this.start = start;
      this.end = end;
    }

    @Override
    public int size() {
      return end - start;
    }

    @Override
    public boolean isEmpty() {
      return false;
    }

    @Override
    public Double get(int index) {
      checkElementIndex(index, size());
      return array[start + index];
    }

    @Override
    public boolean contains(Object target) {
      // Overridden to prevent a ton of boxing
      return (target instanceof Double)
          && Doubles.indexOf(array, (Double) target, start, end) != -1;
    }

    @Override
    public int indexOf(Object target) {
      // Overridden to prevent a ton of boxing
      if (target instanceof Double) {
        int i = Doubles.indexOf(array, (Double) target, start, end);
        if (i >= 0) {
          return i - start;
        }
      }
      return -1;
    }

    @Override
    public int lastIndexOf(Object target) {
      // Overridden to prevent a ton of boxing
      if (target instanceof Double) {
        int i = Doubles.lastIndexOf(array, (Double) target, start, end);
        if (i >= 0) {
          return i - start;
        }
      }
      return -1;
    }

    @Override
    public Double set(int index, Double element) {
      checkElementIndex(index, size());
      double oldValue = array[start + index];
      // checkNotNull for GWT (do not optimize)
      array[start + index] = checkNotNull(element);
      return oldValue;
    }

    @Override
    public List<Double> subList(int fromIndex, int toIndex) {
      int size = size();
      checkPositionIndexes(fromIndex, toIndex, size);
      if (fromIndex == toIndex) {
        return Collections.emptyList();
      }
      return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
    }

    @Override
    public boolean equals(@NullableDecl Object object) {
      if (object == this) {
        return true;
      }
      if (object instanceof DoubleArrayAsList) {
        DoubleArrayAsList that = (DoubleArrayAsList) object;
        int size = size();
        if (that.size() != size) {
          return false;
        }
        for (int i = 0; i < size; i++) {
          if (array[start + i] != that.array[that.start + i]) {
            return false;
          }
        }
        return true;
      }
      return super.equals(object);
    }

    @Override
    public int hashCode() {
      int result = 1;
      for (int i = start; i < end; i++) {
        result = 31 * result + Doubles.hashCode(array[i]);
      }
      return result;
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder(size() * 12);
      builder.append('[').append(array[start]);
      for (int i = start + 1; i < end; i++) {
        builder.append(", ").append(array[i]);
      }
      return builder.append(']').toString();
    }

    double[] toDoubleArray() {
      return Arrays.copyOfRange(array, start, end);
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * This is adapted from the regex suggested by {@link Double#valueOf(String)} for prevalidating
   * inputs. All valid inputs must pass this regex, but it's semantically fine if not all inputs
   * that pass this regex are valid -- only a performance hit is incurred, not a semantics bug.
   */
  @GwtIncompatible // regular expressions
  static final
  java.util.regex.Pattern
      FLOATING_POINT_PATTERN = fpPattern();

  @GwtIncompatible // regular expressions
  private static
  java.util.regex.Pattern
      fpPattern() {
    /*
     * We use # instead of * for possessive quantifiers. This lets us strip them out when building
     * the regex for RE2 (which doesn't support them) but leave them in when building it for
     * java.util.regex (where we want them in order to avoid catastrophic backtracking).
     */
    String decimal = "(?:\\d+#(?:\\.\\d*#)?|\\.\\d+#)";
    String completeDec = decimal + "(?:[eE][+-]?\\d+#)?[fFdD]?";
    String hex = "(?:[0-9a-fA-F]+#(?:\\.[0-9a-fA-F]*#)?|\\.[0-9a-fA-F]+#)";
    String completeHex = "0[xX]" + hex + "[pP][+-]?\\d+#[fFdD]?";
    String fpPattern = "[+-]?(?:NaN|Infinity|" + completeDec + "|" + completeHex + ")";
    fpPattern =
        fpPattern.replace(
            "#",
            "+"
            );
    return
    java.util.regex.Pattern
        .compile(fpPattern);
  }

  /**
   * Parses the specified string as a double-precision floating point value. The ASCII character
   * {@code '-'} ('\u002D') is recognized as the minus sign.
   *
   *
Unlike {@link Double#parseDouble(String)}, this method returns {@code null} instead of
   * throwing an exception if parsing fails. Valid inputs are exactly those accepted by {@link
   * Double#valueOf(String)}, except that leading and trailing whitespace is not permitted.
   *
   *
This implementation is likely to be faster than {@code Double.parseDouble} if many failures
   * are expected.
   *
   * @param string the string representation of a {@code double} value
   * @return the floating point value represented by {@code string}, or {@code null} if {@code
   *     string} has a length of zero or cannot be parsed as a {@code double} value
   * @since 14.0
   */
  @Beta
  @GwtIncompatible // regular expressions
  @NullableDecl
  public static Double tryParse(String string) {
    if (FLOATING_POINT_PATTERN.matcher(string).matches()) {
      // TODO(lowasser): could be potentially optimized, but only with
      // extensive testing
      try {
        return Double.parseDouble(string);
      } catch (NumberFormatException e) {
        // Double.parseDouble has changed specs several times, so fall through
        // gracefully
      }
    }
    return null;
  }
}


/*
 * Copyright (C) 2007 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.collect;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A list which forwards all its method calls to another list. Subclasses should override one or
 * more methods to modify the behavior of the backing list as desired per the decorator pattern.
 *
 *
This class does not implement {@link java.util.RandomAccess}. If the delegate supports random
 * access, the {@code ForwardingList} subclass should implement the {@code RandomAccess} interface.
 *
 *
Warning: The methods of {@code ForwardingList} forward indiscriminately to the
 * methods of the delegate. For example, overriding {@link #add} alone will not change the
 * behavior of {@link #addAll}, which can lead to unexpected behavior. In this case, you should
 * override {@code addAll} as well, either providing your own implementation, or delegating to the
 * provided {@code standardAddAll} method.
 *
 *
{@code default} method warning: This class does not forward calls to {@code
 * default} methods. Instead, it inherits their default implementations. When those implementations
 * invoke methods, they invoke methods on the {@code ForwardingList}.
 *
 *
The {@code standard} methods and any collection views they return are not guaranteed to be
 * thread-safe, even when all of the methods that they depend on are thread-safe.
 *
 * @author Mike Bostock
 * @author Louis Wasserman
 * @since 2.0
 */
@GwtCompatible
public abstract class ForwardingList<E> extends ForwardingCollection<E> implements List<E> {
  // TODO(lowasser): identify places where thread safety is actually lost

  /** Constructor for use by subclasses. */
  protected ForwardingList() {}

  @Override
  protected abstract List<E> delegate();

  @Override
  public void add(int index, E element) {
    delegate().add(index, element);
  }

  @CanIgnoreReturnValue
  @Override
  public boolean addAll(int index, Collection<? extends E> elements) {
    return delegate().addAll(index, elements);
  }

  @Override
  public E get(int index) {
    return delegate().get(index);
  }

  @Override
  public int indexOf(Object element) {
    return delegate().indexOf(element);
  }

  @Override
  public int lastIndexOf(Object element) {
    return delegate().lastIndexOf(element);
  }

  @Override
  public ListIterator<E> listIterator() {
    return delegate().listIterator();
  }

  @Override
  public ListIterator<E> listIterator(int index) {
    return delegate().listIterator(index);
  }

  @CanIgnoreReturnValue
  @Override
  public E remove(int index) {
    return delegate().remove(index);
  }

  @CanIgnoreReturnValue
  @Override
  public E set(int index, E element) {
    return delegate().set(index, element);
  }

  @Override
  public List<E> subList(int fromIndex, int toIndex) {
    return delegate().subList(fromIndex, toIndex);
  }

  @Override
  public boolean equals(@Nullable Object object) {
    return object == this || delegate().equals(object);
  }

  @Override
  public int hashCode() {
    return delegate().hashCode();
  }

  /**
   * A sensible default implementation of {@link #add(Object)}, in terms of {@link #add(int,
   * Object)}. If you override {@link #add(int, Object)}, you may wish to override {@link
   * #add(Object)} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardAdd(E element) {
    add(size(), element);
    return true;
  }

  /**
   * A sensible default implementation of {@link #addAll(int, Collection)}, in terms of the {@code
   * add} method of {@link #listIterator(int)}. If you override {@link #listIterator(int)}, you may
   * wish to override {@link #addAll(int, Collection)} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardAddAll(int index, Iterable<? extends E> elements) {
    return Lists.addAllImpl(this, index, elements);
  }

  /**
   * A sensible default implementation of {@link #indexOf}, in terms of {@link #listIterator()}. If
   * you override {@link #listIterator()}, you may wish to override {@link #indexOf} to forward to
   * this implementation.
   *
   * @since 7.0
   */
  protected int standardIndexOf(@Nullable Object element) {
    return Lists.indexOfImpl(this, element);
  }

  /**
   * A sensible default implementation of {@link #lastIndexOf}, in terms of {@link
   * #listIterator(int)}. If you override {@link #listIterator(int)}, you may wish to override
   * {@link #lastIndexOf} to forward to this implementation.
   *
   * @since 7.0
   */
  protected int standardLastIndexOf(@Nullable Object element) {
    return Lists.lastIndexOfImpl(this, element);
  }

  /**
   * A sensible default implementation of {@link #iterator}, in terms of {@link #listIterator()}. If
   * you override {@link #listIterator()}, you may wish to override {@link #iterator} to forward to
   * this implementation.
   *
   * @since 7.0
   */
  protected Iterator<E> standardIterator() {
    return listIterator();
  }

  /**
   * A sensible default implementation of {@link #listIterator()}, in terms of {@link
   * #listIterator(int)}. If you override {@link #listIterator(int)}, you may wish to override
   * {@link #listIterator()} to forward to this implementation.
   *
   * @since 7.0
   */
  protected ListIterator<E> standardListIterator() {
    return listIterator(0);
  }

  /**
   * A sensible default implementation of {@link #listIterator(int)}, in terms of {@link #size},
   * {@link #get(int)}, {@link #set(int, Object)}, {@link #add(int, Object)}, and {@link
   * #remove(int)}. If you override any of these methods, you may wish to override {@link
   * #listIterator(int)} to forward to this implementation.
   *
   * @since 7.0
   */
  @Beta
  protected ListIterator<E> standardListIterator(int start) {
    return Lists.listIteratorImpl(this, start);
  }

  /**
   * A sensible default implementation of {@link #subList(int, int)}. If you override any other
   * methods, you may wish to override {@link #subList(int, int)} to forward to this implementation.
   *
   * @since 7.0
   */
  @Beta
  protected List<E> standardSubList(int fromIndex, int toIndex) {
    return Lists.subListImpl(this, fromIndex, toIndex);
  }

  /**
   * A sensible definition of {@link #equals(Object)} in terms of {@link #size} and {@link
   * #iterator}. If you override either of those methods, you may wish to override {@link
   * #equals(Object)} to forward to this implementation.
   *
   * @since 7.0
   */
  @Beta
  protected boolean standardEquals(@Nullable Object object) {
    return Lists.equalsImpl(this, object);
  }

  /**
   * A sensible definition of {@link #hashCode} in terms of {@link #iterator}. If you override
   * {@link #iterator}, you may wish to override {@link #hashCode} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  @Beta
  protected int standardHashCode() {
    return Lists.hashCodeImpl(this);
  }
}