/*
 * Copyright (C) 2011 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 com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.math.MathPreconditions.checkNoOverflow;
import static com.google.common.math.MathPreconditions.checkNonNegative;
import static com.google.common.math.MathPreconditions.checkPositive;
import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static java.math.RoundingMode.HALF_EVEN;
import static java.math.RoundingMode.HALF_UP;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.UnsignedLongs;
import java.math.BigInteger;
import java.math.RoundingMode;

/**
 * A class for arithmetic on values of type {@code long}. Where possible, methods are defined and
 * named analogously to their {@code BigInteger} counterparts.
 *
 *
The implementations of many methods in this class are based on material from Henry S. Warren,
 * Jr.'s Hacker's Delight, (Addison Wesley, 2002).
 *
 *
Similar functionality for {@code int} and for {@link BigInteger} can be found in {@link
 * IntMath} and {@link BigIntegerMath} respectively. For other common operations on {@code long}
 * values, see {@link com.google.common.primitives.Longs}.
 *
 * @author Louis Wasserman
 * @since 11.0
 */
@GwtCompatible(emulated = true)
public final class LongMath {
  // NOTE: Whenever both tests are cheap and functional, it's faster to use &, | instead of &&, ||

  @VisibleForTesting static final long MAX_SIGNED_POWER_OF_TWO = 1L << (Long.SIZE - 2);

  /**
   * Returns the smallest power of two greater than or equal to {@code x}. This is equivalent to
   * {@code checkedPow(2, log2(x, CEILING))}.
   *
   * @throws IllegalArgumentException if {@code x <= 0}
   * @throws ArithmeticException of the next-higher power of two is not representable as a {@code
   *     long}, i.e. when {@code x > 2^62}
   * @since 20.0
   */
  @Beta
  public static long ceilingPowerOfTwo(long x) {
    checkPositive("x", x);
    if (x > MAX_SIGNED_POWER_OF_TWO) {
      throw new ArithmeticException("ceilingPowerOfTwo(" + x + ") is not representable as a long");
    }
    return 1L << -Long.numberOfLeadingZeros(x - 1);
  }

  /**
   * Returns the largest power of two less than or equal to {@code x}. This is equivalent to {@code
   * checkedPow(2, log2(x, FLOOR))}.
   *
   * @throws IllegalArgumentException if {@code x <= 0}
   * @since 20.0
   */
  @Beta
  public static long floorPowerOfTwo(long x) {
    checkPositive("x", x);

    // Long.highestOneBit was buggy on GWT.  We've fixed it, but I'm not certain when the fix will
    // be released.
    return 1L << ((Long.SIZE - 1) - Long.numberOfLeadingZeros(x));
  }

  /**
   * Returns {@code true} if {@code x} represents a power of two.
   *
   *
This differs from {@code Long.bitCount(x) == 1}, because {@code
   * Long.bitCount(Long.MIN_VALUE) == 1}, but {@link Long#MIN_VALUE} is not a power of two.
   */
  public static boolean isPowerOfTwo(long x) {
    return x > 0 & (x & (x - 1)) == 0;
  }

  /**
   * Returns 1 if {@code x < y} as unsigned longs, and 0 otherwise. Assumes that x - y fits into a
   * signed long. The implementation is branch-free, and benchmarks suggest it is measurably faster
   * than the straightforward ternary expression.
   */
  @VisibleForTesting
  static int lessThanBranchFree(long x, long y) {
    // Returns the sign bit of x - y.
    return (int) (~~(x - y) >>> (Long.SIZE - 1));
  }

  /**
   * Returns the base-2 logarithm of {@code x}, rounded according to the specified rounding mode.
   *
   * @throws IllegalArgumentException if {@code x <= 0}
   * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x}
   *     is not a power of two
   */
  @SuppressWarnings("fallthrough")
  // TODO(kevinb): remove after this warning is disabled globally
  public static int log2(long x, RoundingMode mode) {
    checkPositive("x", x);
    switch (mode) {
      case UNNECESSARY:
        checkRoundingUnnecessary(isPowerOfTwo(x));
        // fall through
      case DOWN:
      case FLOOR:
        return (Long.SIZE - 1) - Long.numberOfLeadingZeros(x);

      case UP:
      case CEILING:
        return Long.SIZE - Long.numberOfLeadingZeros(x - 1);

      case HALF_DOWN:
      case HALF_UP:
      case HALF_EVEN:
        // Since sqrt(2) is irrational, log2(x) - logFloor cannot be exactly 0.5
        int leadingZeros = Long.numberOfLeadingZeros(x);
        long cmp = MAX_POWER_OF_SQRT2_UNSIGNED >>> leadingZeros;
        // floor(2^(logFloor + 0.5))
        int logFloor = (Long.SIZE - 1) - leadingZeros;
        return logFloor + lessThanBranchFree(cmp, x);

      default:
        throw new AssertionError("impossible");
    }
  }

  /** The biggest half power of two that fits into an unsigned long */
  @VisibleForTesting static final long MAX_POWER_OF_SQRT2_UNSIGNED = 0xB504F333F9DE6484L;

  /**
   * Returns the base-10 logarithm of {@code x}, rounded according to the specified rounding mode.
   *
   * @throws IllegalArgumentException if {@code x <= 0}
   * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x}
   *     is not a power of ten
   */
  @GwtIncompatible // TODO
  @SuppressWarnings("fallthrough")
  // TODO(kevinb): remove after this warning is disabled globally
  public static int log10(long x, RoundingMode mode) {
    checkPositive("x", x);
    int logFloor = log10Floor(x);
    long floorPow = powersOf10[logFloor];
    switch (mode) {
      case UNNECESSARY:
        checkRoundingUnnecessary(x == floorPow);
        // fall through
      case FLOOR:
      case DOWN:
        return logFloor;
      case CEILING:
      case UP:
        return logFloor + lessThanBranchFree(floorPow, x);
      case HALF_DOWN:
      case HALF_UP:
      case HALF_EVEN:
        // sqrt(10) is irrational, so log10(x)-logFloor is never exactly 0.5
        return logFloor + lessThanBranchFree(halfPowersOf10[logFloor], x);
      default:
        throw new AssertionError();
    }
  }

  @GwtIncompatible // TODO
  static int log10Floor(long x) {
    /*
     * Based on Hacker's Delight Fig. 11-5, the two-table-lookup, branch-free implementation.
     *
     * The key idea is that based on the number of leading zeros (equivalently, floor(log2(x))), we
     * can narrow the possible floor(log10(x)) values to two. For example, if floor(log2(x)) is 6,
     * then 64 <= x < 128, so floor(log10(x)) is either 1 or 2.
     */
    int y = maxLog10ForLeadingZeros[Long.numberOfLeadingZeros(x)];
    /*
     * y is the higher of the two possible values of floor(log10(x)). If x < 10^y, then we want the
     * lower of the two possible values, or y - 1, otherwise, we want y.
     */
    return y - lessThanBranchFree(x, powersOf10[y]);
  }

  // maxLog10ForLeadingZeros[i] == floor(log10(2^(Long.SIZE - i)))
  @VisibleForTesting
  static final byte[] maxLog10ForLeadingZeros = {
    19, 18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12,
    12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3,
    3, 2, 2, 2, 1, 1, 1, 0, 0, 0
  };

  @GwtIncompatible // TODO
  @VisibleForTesting
  static final long[] powersOf10 = {
    1L,
    10L,
    100L,
    1000L,
    10000L,
    100000L,
    1000000L,
    10000000L,
    100000000L,
    1000000000L,
    10000000000L,
    100000000000L,
    1000000000000L,
    10000000000000L,
    100000000000000L,
    1000000000000000L,
    10000000000000000L,
    100000000000000000L,
    1000000000000000000L
  };

  // halfPowersOf10[i] = largest long less than 10^(i + 0.5)
  @GwtIncompatible // TODO
  @VisibleForTesting
  static final long[] halfPowersOf10 = {
    3L,
    31L,
    316L,
    3162L,
    31622L,
    316227L,
    3162277L,
    31622776L,
    316227766L,
    3162277660L,
    31622776601L,
    316227766016L,
    3162277660168L,
    31622776601683L,
    316227766016837L,
    3162277660168379L,
    31622776601683793L,
    316227766016837933L,
    3162277660168379331L
  };

  /**
   * Returns {@code b} to the {@code k}th power. Even if the result overflows, it will be equal to
   * {@code BigInteger.valueOf(b).pow(k).longValue()}. This implementation runs in {@code O(log k)}
   * time.
   *
   * @throws IllegalArgumentException if {@code k < 0}
   */
  @GwtIncompatible // TODO
  public static long pow(long b, int k) {
    checkNonNegative("exponent", k);
    if (-2 <= b && b <= 2) {
      switch ((int) b) {
        case 0:
          return (k == 0) ? 1 : 0;
        case 1:
          return 1;
        case (-1):
          return ((k & 1) == 0) ? 1 : -1;
        case 2:
          return (k < Long.SIZE) ? 1L << k : 0;
        case (-2):
          if (k < Long.SIZE) {
            return ((k & 1) == 0) ? 1L << k : -(1L << k);
          } else {
            return 0;
          }
        default:
          throw new AssertionError();
      }
    }
    for (long accum = 1; ; k >>= 1) {
      switch (k) {
        case 0:
          return accum;
        case 1:
          return accum * b;
        default:
          accum *= ((k & 1) == 0) ? 1 : b;
          b *= b;
      }
    }
  }

  /**
   * Returns the square root of {@code x}, rounded with the specified rounding mode.
   *
   * @throws IllegalArgumentException if {@code x < 0}
   * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code
   *     sqrt(x)} is not an integer
   */
  @GwtIncompatible // TODO
  @SuppressWarnings("fallthrough")
  public static long sqrt(long x, RoundingMode mode) {
    checkNonNegative("x", x);
    if (fitsInInt(x)) {
      return IntMath.sqrt((int) x, mode);
    }
    /*
     * Let k be the true value of floor(sqrt(x)), so that
     *
     *            k * k <= x          <  (k + 1) * (k + 1)
     * (double) (k * k) <= (double) x <= (double) ((k + 1) * (k + 1))
     *          since casting to double is nondecreasing.
     *          Note that the right-hand inequality is no longer strict.
     * Math.sqrt(k * k) <= Math.sqrt(x) <= Math.sqrt((k + 1) * (k + 1))
     *          since Math.sqrt is monotonic.
     * (long) Math.sqrt(k * k) <= (long) Math.sqrt(x) <= (long) Math.sqrt((k + 1) * (k + 1))
     *          since casting to long is monotonic
     * k <= (long) Math.sqrt(x) <= k + 1
     *          since (long) Math.sqrt(k * k) == k, as checked exhaustively in
     *          {@link LongMathTest#testSqrtOfPerfectSquareAsDoubleIsPerfect}
     */
    long guess = (long) Math.sqrt(x);
    // Note: guess is always <= FLOOR_SQRT_MAX_LONG.
    long guessSquared = guess * guess;
    // Note (2013-2-26): benchmarks indicate that, inscrutably enough, using if statements is
    // faster here than using lessThanBranchFree.
    switch (mode) {
      case UNNECESSARY:
        checkRoundingUnnecessary(guessSquared == x);
        return guess;
      case FLOOR:
      case DOWN:
        if (x < guessSquared) {
          return guess - 1;
        }
        return guess;
      case CEILING:
      case UP:
        if (x > guessSquared) {
          return guess + 1;
        }
        return guess;
      case HALF_DOWN:
      case HALF_UP:
      case HALF_EVEN:
        long sqrtFloor = guess - ((x < guessSquared) ? 1 : 0);
        long halfSquare = sqrtFloor * sqrtFloor + sqrtFloor;
        /*
         * We wish to test whether or not x <= (sqrtFloor + 0.5)^2 = halfSquare + 0.25. Since both x
         * and halfSquare are integers, this is equivalent to testing whether or not x <=
         * halfSquare. (We have to deal with overflow, though.)
         *
         * If we treat halfSquare as an unsigned long, we know that
         *            sqrtFloor^2 <= x < (sqrtFloor + 1)^2
         * halfSquare - sqrtFloor <= x < halfSquare + sqrtFloor + 1
         * so |x - halfSquare| <= sqrtFloor.  Therefore, it's safe to treat x - halfSquare as a
         * signed long, so lessThanBranchFree is safe for use.
         */
        return sqrtFloor + lessThanBranchFree(halfSquare, x);
      default:
        throw new AssertionError();
    }
  }

  /**
   * Returns the result of dividing {@code p} by {@code q}, rounding using the specified {@code
   * RoundingMode}.
   *
   * @throws ArithmeticException if {@code q == 0}, or if {@code mode == UNNECESSARY} and {@code a}
   *     is not an integer multiple of {@code b}
   */
  @GwtIncompatible // TODO
  @SuppressWarnings("fallthrough")
  public static long divide(long p, long q, RoundingMode mode) {
    checkNotNull(mode);
    long div = p / q; // throws if q == 0
    long rem = p - q * div; // equals p % q

    if (rem == 0) {
      return div;
    }

    /*
     * Normal Java division rounds towards 0, consistently with RoundingMode.DOWN. We just have to
     * deal with the cases where rounding towards 0 is wrong, which typically depends on the sign of
     * p / q.
     *
     * signum is 1 if p and q are both nonnegative or both negative, and -1 otherwise.
     */
    int signum = 1 | (int) ((p ^ q) >> (Long.SIZE - 1));
    boolean increment;
    switch (mode) {
      case UNNECESSARY:
        checkRoundingUnnecessary(rem == 0);
        // fall through
      case DOWN:
        increment = false;
        break;
      case UP:
        increment = true;
        break;
      case CEILING:
        increment = signum > 0;
        break;
      case FLOOR:
        increment = signum < 0;
        break;
      case HALF_EVEN:
      case HALF_DOWN:
      case HALF_UP:
        long absRem = abs(rem);
        long cmpRemToHalfDivisor = absRem - (abs(q) - absRem);
        // subtracting two nonnegative longs can't overflow
        // cmpRemToHalfDivisor has the same sign as compare(abs(rem), abs(q) / 2).
        if (cmpRemToHalfDivisor == 0) { // exactly on the half mark
          increment = (mode == HALF_UP | (mode == HALF_EVEN & (div & 1) != 0));
        } else {
          increment = cmpRemToHalfDivisor > 0; // closer to the UP value
        }
        break;
      default:
        throw new AssertionError();
    }
    return increment ? div + signum : div;
  }

  /**
   * Returns {@code x mod m}, a non-negative value less than {@code m}. This differs from {@code x %
   * m}, which might be negative.
   *
   *
For example:
   *
   *
{@code
   * mod(7, 4) == 3
   * mod(-7, 4) == 1
   * mod(-1, 4) == 3
   * mod(-8, 4) == 0
   * mod(8, 4) == 0
   * }

   *
   * @throws ArithmeticException if {@code m <= 0}
   * @see
   *     Remainder Operator
   */
  @GwtIncompatible // TODO
  public static int mod(long x, int m) {
    // Cast is safe because the result is guaranteed in the range [0, m)
    return (int) mod(x, (long) m);
  }

  /**
   * Returns {@code x mod m}, a non-negative value less than {@code m}. This differs from {@code x %
   * m}, which might be negative.
   *
   *
For example:
   *
   *
{@code
   * mod(7, 4) == 3
   * mod(-7, 4) == 1
   * mod(-1, 4) == 3
   * mod(-8, 4) == 0
   * mod(8, 4) == 0
   * }

   *
   * @throws ArithmeticException if {@code m <= 0}
   * @see
   *     Remainder Operator
   */
  @GwtIncompatible // TODO
  public static long mod(long x, long m) {
    if (m <= 0) {
      throw new ArithmeticException("Modulus must be positive");
    }
    long result = x % m;
    return (result >= 0) ? result : result + m;
  }

  /**
   * Returns the greatest common divisor of {@code a, b}. Returns {@code 0} if {@code a == 0 && b ==
   * 0}.
   *
   * @throws IllegalArgumentException if {@code a < 0} or {@code b < 0}
   */
  public static long gcd(long a, long b) {
    /*
     * The reason we require both arguments to be >= 0 is because otherwise, what do you return on
     * gcd(0, Long.MIN_VALUE)? BigInteger.gcd would return positive 2^63, but positive 2^63 isn't an
     * int.
     */
    checkNonNegative("a", a);
    checkNonNegative("b", b);
    if (a == 0) {
      // 0 % b == 0, so b divides a, but the converse doesn't hold.
      // BigInteger.gcd is consistent with this decision.
      return b;
    } else if (b == 0) {
      return a; // similar logic
    }
    /*
     * Uses the binary GCD algorithm; see http://en.wikipedia.org/wiki/Binary_GCD_algorithm. This is
     * >60% faster than the Euclidean algorithm in benchmarks.
     */
    int aTwos = Long.numberOfTrailingZeros(a);
    a >>= aTwos; // divide out all 2s
    int bTwos = Long.numberOfTrailingZeros(b);
    b >>= bTwos; // divide out all 2s
    while (a != b) { // both a, b are odd
      // The key to the binary GCD algorithm is as follows:
      // Both a and b are odd. Assume a > b; then gcd(a - b, b) = gcd(a, b).
      // But in gcd(a - b, b), a - b is even and b is odd, so we can divide out powers of two.

      // We bend over backwards to avoid branching, adapting a technique from
      // http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax

      long delta = a - b; // can't overflow, since a and b are nonnegative

      long minDeltaOrZero = delta & (delta >> (Long.SIZE - 1));
      // equivalent to Math.min(delta, 0)

      a = delta - minDeltaOrZero - minDeltaOrZero; // sets a to Math.abs(a - b)
      // a is now nonnegative and even

      b += minDeltaOrZero; // sets b to min(old a, b)
      a >>= Long.numberOfTrailingZeros(a); // divide out all 2s, since 2 doesn't divide b
    }
    return a << min(aTwos, bTwos);
  }

  /**
   * Returns the sum of {@code a} and {@code b}, provided it does not overflow.
   *
   * @throws ArithmeticException if {@code a + b} overflows in signed {@code long} arithmetic
   */
  @GwtIncompatible // TODO
  public static long checkedAdd(long a, long b) {
    long result = a + b;
    checkNoOverflow((a ^ b) < 0 | (a ^ result) >= 0, "checkedAdd", a, b);
    return result;
  }

  /**
   * Returns the difference of {@code a} and {@code b}, provided it does not overflow.
   *
   * @throws ArithmeticException if {@code a - b} overflows in signed {@code long} arithmetic
   */
  @GwtIncompatible // TODO
  public static long checkedSubtract(long a, long b) {
    long result = a - b;
    checkNoOverflow((a ^ b) >= 0 | (a ^ result) >= 0, "checkedSubtract", a, b);
    return result;
  }

  /**
   * Returns the product of {@code a} and {@code b}, provided it does not overflow.
   *
   * @throws ArithmeticException if {@code a * b} overflows in signed {@code long} arithmetic
   */
  public static long checkedMultiply(long a, long b) {
    // Hacker's Delight, Section 2-12
    int leadingZeros =
        Long.numberOfLeadingZeros(a)
            + Long.numberOfLeadingZeros(~a)
            + Long.numberOfLeadingZeros(b)
            + Long.numberOfLeadingZeros(~b);
    /*
     * If leadingZeros > Long.SIZE + 1 it's definitely fine, if it's < Long.SIZE it's definitely
     * bad. We do the leadingZeros check to avoid the division below if at all possible.
     *
     * Otherwise, if b == Long.MIN_VALUE, then the only allowed values of a are 0 and 1. We take
     * care of all a < 0 with their own check, because in particular, the case a == -1 will
     * incorrectly pass the division check below.
     *
     * In all other cases, we check that either a is 0 or the result is consistent with division.
     */
    if (leadingZeros > Long.SIZE + 1) {
      return a * b;
    }
    checkNoOverflow(leadingZeros >= Long.SIZE, "checkedMultiply", a, b);
    checkNoOverflow(a >= 0 | b != Long.MIN_VALUE, "checkedMultiply", a, b);
    long result = a * b;
    checkNoOverflow(a == 0 || result / a == b, "checkedMultiply", a, b);
    return result;
  }

  /**
   * Returns the {@code b} to the {@code k}th power, provided it does not overflow.
   *
   * @throws ArithmeticException if {@code b} to the {@code k}th power overflows in signed {@code
   *     long} arithmetic
   */
  @GwtIncompatible // TODO
  public static long checkedPow(long b, int k) {
    checkNonNegative("exponent", k);
    if (b >= -2 & b <= 2) {
      switch ((int) b) {
        case 0:
          return (k == 0) ? 1 : 0;
        case 1:
          return 1;
        case (-1):
          return ((k & 1) == 0) ? 1 : -1;
        case 2:
          checkNoOverflow(k < Long.SIZE - 1, "checkedPow", b, k);
          return 1L << k;
        case (-2):
          checkNoOverflow(k < Long.SIZE, "checkedPow", b, k);
          return ((k & 1) == 0) ? (1L << k) : (-1L << k);
        default:
          throw new AssertionError();
      }
    }
    long accum = 1;
    while (true) {
      switch (k) {
        case 0:
          return accum;
        case 1:
          return checkedMultiply(accum, b);
        default:
          if ((k & 1) != 0) {
            accum = checkedMultiply(accum, b);
          }
          k >>= 1;
          if (k > 0) {
            checkNoOverflow(
                -FLOOR_SQRT_MAX_LONG <= b && b <= FLOOR_SQRT_MAX_LONG, "checkedPow", b, k);
            b *= b;
          }
      }
    }
  }

  /**
   * Returns the sum of {@code a} and {@code b} unless it would overflow or underflow in which case
   * {@code Long.MAX_VALUE} or {@code Long.MIN_VALUE} is returned, respectively.
   *
   * @since 20.0
   */
  @Beta
  public static long saturatedAdd(long a, long b) {
    long naiveSum = a + b;
    if ((a ^ b) < 0 | (a ^ naiveSum) >= 0) {
      // If a and b have different signs or a has the same sign as the result then there was no
      // overflow, return.
      return naiveSum;
    }
    // we did over/under flow, if the sign is negative we should return MAX otherwise MIN
    return Long.MAX_VALUE + ((naiveSum >>> (Long.SIZE - 1)) ^ 1);
  }

  /**
   * Returns the difference of {@code a} and {@code b} unless it would overflow or underflow in
   * which case {@code Long.MAX_VALUE} or {@code Long.MIN_VALUE} is returned, respectively.
   *
   * @since 20.0
   */
  @Beta
  public static long saturatedSubtract(long a, long b) {
    long naiveDifference = a - b;
    if ((a ^ b) >= 0 | (a ^ naiveDifference) >= 0) {
      // If a and b have the same signs or a has the same sign as the result then there was no
      // overflow, return.
      return naiveDifference;
    }
    // we did over/under flow
    return Long.MAX_VALUE + ((naiveDifference >>> (Long.SIZE - 1)) ^ 1);
  }

  /**
   * Returns the product of {@code a} and {@code b} unless it would overflow or underflow in which
   * case {@code Long.MAX_VALUE} or {@code Long.MIN_VALUE} is returned, respectively.
   *
   * @since 20.0
   */
  @Beta
  public static long saturatedMultiply(long a, long b) {
    // see checkedMultiply for explanation
    int leadingZeros =
        Long.numberOfLeadingZeros(a)
            + Long.numberOfLeadingZeros(~a)
            + Long.numberOfLeadingZeros(b)
            + Long.numberOfLeadingZeros(~b);
    if (leadingZeros > Long.SIZE + 1) {
      return a * b;
    }
    // the return value if we will overflow (which we calculate by overflowing a long :) )
    long limit = Long.MAX_VALUE + ((a ^ b) >>> (Long.SIZE - 1));
    if (leadingZeros < Long.SIZE | (a < 0 & b == Long.MIN_VALUE)) {
      // overflow
      return limit;
    }
    long result = a * b;
    if (a == 0 || result / a == b) {
      return result;
    }
    return limit;
  }

  /**
   * Returns the {@code b} to the {@code k}th power, unless it would overflow or underflow in which
   * case {@code Long.MAX_VALUE} or {@code Long.MIN_VALUE} is returned, respectively.
   *
   * @since 20.0
   */
  @Beta
  public static long saturatedPow(long b, int k) {
    checkNonNegative("exponent", k);
    if (b >= -2 & b <= 2) {
      switch ((int) b) {
        case 0:
          return (k == 0) ? 1 : 0;
        case 1:
          return 1;
        case (-1):
          return ((k & 1) == 0) ? 1 : -1;
        case 2:
          if (k >= Long.SIZE - 1) {
            return Long.MAX_VALUE;
          }
          return 1L << k;
        case (-2):
          if (k >= Long.SIZE) {
            return Long.MAX_VALUE + (k & 1);
          }
          return ((k & 1) == 0) ? (1L << k) : (-1L << k);
        default:
          throw new AssertionError();
      }
    }
    long accum = 1;
    // if b is negative and k is odd then the limit is MIN otherwise the limit is MAX
    long limit = Long.MAX_VALUE + ((b >>> Long.SIZE - 1) & (k & 1));
    while (true) {
      switch (k) {
        case 0:
          return accum;
        case 1:
          return saturatedMultiply(accum, b);
        default:
          if ((k & 1) != 0) {
            accum = saturatedMultiply(accum, b);
          }
          k >>= 1;
          if (k > 0) {
            if (-FLOOR_SQRT_MAX_LONG > b | b > FLOOR_SQRT_MAX_LONG) {
              return limit;
            }
            b *= b;
          }
      }
    }
  }

  @VisibleForTesting static final long FLOOR_SQRT_MAX_LONG = 3037000499L;

  /**
   * Returns {@code n!}, that is, the product of the first {@code n} positive integers, {@code 1} if
   * {@code n == 0}, or {@link Long#MAX_VALUE} if the result does not fit in a {@code long}.
   *
   * @throws IllegalArgumentException if {@code n < 0}
   */
  @GwtIncompatible // TODO
  public static long factorial(int n) {
    checkNonNegative("n", n);
    return (n < factorials.length) ? factorials[n] : Long.MAX_VALUE;
  }

  static final long[] factorials = {
    1L,
    1L,
    1L * 2,
    1L * 2 * 3,
    1L * 2 * 3 * 4,
    1L * 2 * 3 * 4 * 5,
    1L * 2 * 3 * 4 * 5 * 6,
    1L * 2 * 3 * 4 * 5 * 6 * 7,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19,
    1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20
  };

  /**
   * Returns {@code n} choose {@code k}, also known as the binomial coefficient of {@code n} and
   * {@code k}, or {@link Long#MAX_VALUE} if the result does not fit in a {@code long}.
   *
   * @throws IllegalArgumentException if {@code n < 0}, {@code k < 0}, or {@code k > n}
   */
  public static long binomial(int n, int k) {
    checkNonNegative("n", n);
    checkNonNegative("k", k);
    checkArgument(k <= n, "k (%s) > n (%s)", k, n);
    if (k > (n >> 1)) {
      k = n - k;
    }
    switch (k) {
      case 0:
        return 1;
      case 1:
        return n;
      default:
        if (n < factorials.length) {
          return factorials[n] / (factorials[k] * factorials[n - k]);
        } else if (k >= biggestBinomials.length || n > biggestBinomials[k]) {
          return Long.MAX_VALUE;
        } else if (k < biggestSimpleBinomials.length && n <= biggestSimpleBinomials[k]) {
          // guaranteed not to overflow
          long result = n--;
          for (int i = 2; i <= k; n--, i++) {
            result *= n;
            result /= i;
          }
          return result;
        } else {
          int nBits = LongMath.log2(n, RoundingMode.CEILING);

          long result = 1;
          long numerator = n--;
          long denominator = 1;

          int numeratorBits = nBits;
          // This is an upper bound on log2(numerator, ceiling).

          /*
           * We want to do this in long math for speed, but want to avoid overflow. We adapt the
           * technique previously used by BigIntegerMath: maintain separate numerator and
           * denominator accumulators, multiplying the fraction into result when near overflow.
           */
          for (int i = 2; i <= k; i++, n--) {
            if (numeratorBits + nBits < Long.SIZE - 1) {
              // It's definitely safe to multiply into numerator and denominator.
              numerator *= n;
              denominator *= i;
              numeratorBits += nBits;
            } else {
              // It might not be safe to multiply into numerator and denominator,
              // so multiply (numerator / denominator) into result.
              result = multiplyFraction(result, numerator, denominator);
              numerator = n;
              denominator = i;
              numeratorBits = nBits;
            }
          }
          return multiplyFraction(result, numerator, denominator);
        }
    }
  }

  /** Returns (x * numerator / denominator), which is assumed to come out to an integral value. */
  static long multiplyFraction(long x, long numerator, long denominator) {
    if (x == 1) {
      return numerator / denominator;
    }
    long commonDivisor = gcd(x, denominator);
    x /= commonDivisor;
    denominator /= commonDivisor;
    // We know gcd(x, denominator) = 1, and x * numerator / denominator is exact,
    // so denominator must be a divisor of numerator.
    return x * (numerator / denominator);
  }

  /*
   * binomial(biggestBinomials[k], k) fits in a long, but not binomial(biggestBinomials[k] + 1, k).
   */
  static final int[] biggestBinomials = {
    Integer.MAX_VALUE,
    Integer.MAX_VALUE,
    Integer.MAX_VALUE,
    3810779,
    121977,
    16175,
    4337,
    1733,
    887,
    534,
    361,
    265,
    206,
    169,
    143,
    125,
    111,
    101,
    94,
    88,
    83,
    79,
    76,
    74,
    72,
    70,
    69,
    68,
    67,
    67,
    66,
    66,
    66,
    66
  };

  /*
   * binomial(biggestSimpleBinomials[k], k) doesn't need to use the slower GCD-based impl, but
   * binomial(biggestSimpleBinomials[k] + 1, k) does.
   */
  @VisibleForTesting
  static final int[] biggestSimpleBinomials = {
    Integer.MAX_VALUE,
    Integer.MAX_VALUE,
    Integer.MAX_VALUE,
    2642246,
    86251,
    11724,
    3218,
    1313,
    684,
    419,
    287,
    214,
    169,
    139,
    119,
    105,
    95,
    87,
    81,
    76,
    73,
    70,
    68,
    66,
    64,
    63,
    62,
    62,
    61,
    61,
    61
  };
  // These values were generated by using checkedMultiply to see when the simple multiply/divide
  // algorithm would lead to an overflow.

  static boolean fitsInInt(long x) {
    return (int) x == x;
  }

  /**
   * Returns the arithmetic mean of {@code x} and {@code y}, rounded toward negative infinity. This
   * method is resilient to overflow.
   *
   * @since 14.0
   */
  public static long mean(long x, long y) {
    // Efficient method for computing the arithmetic mean.
    // The alternative (x + y) / 2 fails for large values.
    // The alternative (x + y) >>> 1 fails for negative values.
    return (x & y) + ((x ^ y) >> 1);
  }

  /*
   * This bitmask is used as an optimization for cheaply testing for divisiblity by 2, 3, or 5.
   * Each bit is set to 1 for all remainders that indicate divisibility by 2, 3, or 5, so
   * 1, 7, 11, 13, 17, 19, 23, 29 are set to 0. 30 and up don't matter because they won't be hit.
   */
  private static final int SIEVE_30 =
      ~((1 << 1) | (1 << 7) | (1 << 11) | (1 << 13) | (1 << 17) | (1 << 19) | (1 << 23)
          | (1 << 29));

  /**
   * Returns {@code true} if {@code n} is a prime number: an integer greater
   * than one that cannot be factored into a product of smaller positive integers.
   * Returns {@code false} if {@code n} is zero, one, or a composite number (one which can be
   * factored into smaller positive integers).
   *
   *
To test larger numbers, use {@link BigInteger#isProbablePrime}.
   *
   * @throws IllegalArgumentException if {@code n} is negative
   * @since 20.0
   */
  @GwtIncompatible // TODO
  @Beta
  public static boolean isPrime(long n) {
    if (n < 2) {
      checkNonNegative("n", n);
      return false;
    }
    if (n == 2 || n == 3 || n == 5 || n == 7 || n == 11 || n == 13) {
      return true;
    }

    if ((SIEVE_30 & (1 << (n % 30))) != 0) {
      return false;
    }
    if (n % 7 == 0 || n % 11 == 0 || n % 13 == 0) {
      return false;
    }
    if (n < 17 * 17) {
      return true;
    }

    for (long[] baseSet : millerRabinBaseSets) {
      if (n <= baseSet[0]) {
        for (int i = 1; i < baseSet.length; i++) {
          if (!MillerRabinTester.test(baseSet[i], n)) {
            return false;
          }
        }
        return true;
      }
    }
    throw new AssertionError();
  }

  /*
   * If n <= millerRabinBases[i][0], then testing n against bases millerRabinBases[i][1..] suffices
   * to prove its primality. Values from miller-rabin.appspot.com.
   *
   * NOTE: We could get slightly better bases that would be treated as unsigned, but benchmarks
   * showed negligible performance improvements.
   */
  private static final long[][] millerRabinBaseSets = {
    {291830, 126401071349994536L},
    {885594168, 725270293939359937L, 3569819667048198375L},
    {273919523040L, 15, 7363882082L, 992620450144556L},
    {47636622961200L, 2, 2570940, 211991001, 3749873356L},
    {
      7999252175582850L,
      2,
      4130806001517L,
      149795463772692060L,
      186635894390467037L,
      3967304179347715805L
    },
    {
      585226005592931976L,
      2,
      123635709730000L,
      9233062284813009L,
      43835965440333360L,
      761179012939631437L,
      1263739024124850375L
    },
    {Long.MAX_VALUE, 2, 325, 9375, 28178, 450775, 9780504, 1795265022}
  };

  private enum MillerRabinTester {
    /** Works for inputs ≤ FLOOR_SQRT_MAX_LONG. */
    SMALL {
      @Override
      long mulMod(long a, long b, long m) {
        /*
         * NOTE(lowasser, 2015-Feb-12): Benchmarks suggest that changing this to
         * UnsignedLongs.remainder and increasing the threshold to 2^32 doesn't pay for itself, and
         * adding another enum constant hurts performance further -- I suspect because bimorphic
         * implementation is a sweet spot for the JVM.
         */
        return (a * b) % m;
      }

      @Override
      long squareMod(long a, long m) {
        return (a * a) % m;
      }
    },
    /** Works for all nonnegative signed longs. */
    LARGE {
      /** Returns (a + b) mod m. Precondition: {@code 0 <= a}, {@code b < m < 2^63}. */
      private long plusMod(long a, long b, long m) {
        return (a >= m - b) ? (a + b - m) : (a + b);
      }

      /** Returns (a * 2^32) mod m. a may be any unsigned long. */
      private long times2ToThe32Mod(long a, long m) {
        int remainingPowersOf2 = 32;
        do {
          int shift = Math.min(remainingPowersOf2, Long.numberOfLeadingZeros(a));
          // shift is either the number of powers of 2 left to multiply a by, or the biggest shift
          // possible while keeping a in an unsigned long.
          a = UnsignedLongs.remainder(a << shift, m);
          remainingPowersOf2 -= shift;
        } while (remainingPowersOf2 > 0);
        return a;
      }

      @Override
      long mulMod(long a, long b, long m) {
        long aHi = a >>> 32; // < 2^31
        long bHi = b >>> 32; // < 2^31
        long aLo = a & 0xFFFFFFFFL; // < 2^32
        long bLo = b & 0xFFFFFFFFL; // < 2^32

        /*
         * a * b == aHi * bHi * 2^64 + (aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo.
         *       == (aHi * bHi * 2^32 + aHi * bLo + aLo * bHi) * 2^32 + aLo * bLo
         *
         * We carry out this computation in modular arithmetic. Since times2ToThe32Mod accepts any
         * unsigned long, we don't have to do a mod on every operation, only when intermediate
         * results can exceed 2^63.
         */
        long result = times2ToThe32Mod(aHi * bHi /* < 2^62 */, m); // < m < 2^63
        result += aHi * bLo; // aHi * bLo < 2^63, result < 2^64
        if (result < 0) {
          result = UnsignedLongs.remainder(result, m);
        }
        // result < 2^63 again
        result += aLo * bHi; // aLo * bHi < 2^63, result < 2^64
        result = times2ToThe32Mod(result, m); // result < m < 2^63
        return plusMod(result, UnsignedLongs.remainder(aLo * bLo /* < 2^64 */, m), m);
      }

      @Override
      long squareMod(long a, long m) {
        long aHi = a >>> 32; // < 2^31
        long aLo = a & 0xFFFFFFFFL; // < 2^32

        /*
         * a^2 == aHi^2 * 2^64 + aHi * aLo * 2^33 + aLo^2
         *     == (aHi^2 * 2^32 + aHi * aLo * 2) * 2^32 + aLo^2
         * We carry out this computation in modular arithmetic.  Since times2ToThe32Mod accepts any
         * unsigned long, we don't have to do a mod on every operation, only when intermediate
         * results can exceed 2^63.
         */
        long result = times2ToThe32Mod(aHi * aHi /* < 2^62 */, m); // < m < 2^63
        long hiLo = aHi * aLo * 2;
        if (hiLo < 0) {
          hiLo = UnsignedLongs.remainder(hiLo, m);
        }
        // hiLo < 2^63
        result += hiLo; // result < 2^64
        result = times2ToThe32Mod(result, m); // result < m < 2^63
        return plusMod(result, UnsignedLongs.remainder(aLo * aLo /* < 2^64 */, m), m);
      }
    };

    static boolean test(long base, long n) {
      // Since base will be considered % n, it's okay if base > FLOOR_SQRT_MAX_LONG,
      // so long as n <= FLOOR_SQRT_MAX_LONG.
      return ((n <= FLOOR_SQRT_MAX_LONG) ? SMALL : LARGE).testWitness(base, n);
    }

    /** Returns a * b mod m. */
    abstract long mulMod(long a, long b, long m);

    /** Returns a^2 mod m. */
    abstract long squareMod(long a, long m);

    /** Returns a^p mod m. */
    private long powMod(long a, long p, long m) {
      long res = 1;
      for (; p != 0; p >>= 1) {
        if ((p & 1) != 0) {
          res = mulMod(res, a, m);
        }
        a = squareMod(a, m);
      }
      return res;
    }

    /** Returns true if n is a strong probable prime relative to the specified base. */
    private boolean testWitness(long base, long n) {
      int r = Long.numberOfTrailingZeros(n - 1);
      long d = (n - 1) >> r;
      base %= n;
      if (base == 0) {
        return true;
      }
      // Calculate a := base^d mod n.
      long a = powMod(base, d, n);
      // n passes this test if
      //    base^d = 1 (mod n)
      // or base^(2^j * d) = -1 (mod n) for some 0 <= j < r.
      if (a == 1) {
        return true;
      }
      int j = 0;
      while (a != n - 1) {
        if (++j == r) {
          return false;
        }
        a = squareMod(a, n);
      }
      return true;
    }
  }

  private LongMath() {}
}


/*
 * 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 com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
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.qual.Nullable;

/**
 * Static utility methods pertaining to {@code char} primitives, that are not already found in
 * either {@link Character} or {@link Arrays}.
 *
 *
All the operations in this class treat {@code char} values strictly numerically; they are
 * neither Unicode-aware nor locale-dependent.
 *
 *
See the Guava User Guide article on primitive utilities.
 *
 * @author Kevin Bourrillion
 * @since 1.0
 */
@GwtCompatible(emulated = true)
public final class Chars {
  private Chars() {}

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

  /**
   * Returns a hash code for {@code value}; equal to the result of invoking {@code ((Character)
   * value).hashCode()}.
   *
   *
Java 8 users: use {@link Character#hashCode(char)} instead.
   *
   * @param value a primitive {@code char} value
   * @return a hash code for the value
   */
  public static int hashCode(char value) {
    return value;
  }

  /**
   * Returns the {@code char} value that is equal to {@code value}, if possible.
   *
   * @param value any value in the range of the {@code char} type
   * @return the {@code char} value that equals {@code value}
   * @throws IllegalArgumentException if {@code value} is greater than {@link Character#MAX_VALUE}
   *     or less than {@link Character#MIN_VALUE}
   */
  public static char checkedCast(long value) {
    char result = (char) value;
    checkArgument(result == value, "Out of range: %s", value);
    return result;
  }

  /**
   * Returns the {@code char} nearest in value to {@code value}.
   *
   * @param value any {@code long} value
   * @return the same value cast to {@code char} if it is in the range of the {@code char} type,
   *     {@link Character#MAX_VALUE} if it is too large, or {@link Character#MIN_VALUE} if it is too
   *     small
   */
  public static char saturatedCast(long value) {
    if (value > Character.MAX_VALUE) {
      return Character.MAX_VALUE;
    }
    if (value < Character.MIN_VALUE) {
      return Character.MIN_VALUE;
    }
    return (char) value;
  }

  /**
   * Compares the two specified {@code char} values. The sign of the value returned is the same as
   * that of {@code ((Character) a).compareTo(b)}.
   *
   *
Note for Java 7 and later: this method should be treated as deprecated; use the
   * equivalent {@link Character#compare} method instead.
   *
   * @param a the first {@code char} to compare
   * @param b the second {@code char} 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(char a, char b) {
    return a - b; // safe due to restricted range
  }

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

  /**
   * Returns the index of the first appearance of the value {@code target} in {@code array}.
   *
   * @param array an array of {@code char} values, possibly empty
   * @param target a primitive {@code char} 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(char[] array, char target) {
    return indexOf(array, target, 0, array.length);
  }

  // TODO(kevinb): consider making this public
  private static int indexOf(char[] array, char 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}.
   *
   * @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(char[] array, char[] 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}.
   *
   * @param array an array of {@code char} values, possibly empty
   * @param target a primitive {@code char} 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(char[] array, char target) {
    return lastIndexOf(array, target, 0, array.length);
  }

  // TODO(kevinb): consider making this public
  private static int lastIndexOf(char[] array, char 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}.
   *
   * @param array a nonempty array of {@code char} 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 char min(char... array) {
    checkArgument(array.length > 0);
    char min = array[0];
    for (int i = 1; i < array.length; i++) {
      if (array[i] < min) {
        min = array[i];
      }
    }
    return min;
  }

  /**
   * Returns the greatest value present in {@code array}.
   *
   * @param array a nonempty array of {@code char} 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 char max(char... array) {
    checkArgument(array.length > 0);
    char max = array[0];
    for (int i = 1; i < array.length; i++) {
      if (array[i] > 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 char} 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 char constrainToRange(char value, char min, char max) {
    checkArgument(min <= max, "min (%s) must be less than or equal to max (%s)", min, max);
    return value < min ? min : value < max ? value : max;
  }

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

  /**
   * Returns a big-endian representation of {@code value} in a 2-element byte array; equivalent to
   * {@code ByteBuffer.allocate(2).putChar(value).array()}. For example, the input value {@code
   * '\\u5432'} would yield the byte array {@code {0x54, 0x32}}.
   *
   *
If you need to convert and concatenate several values (possibly even of different types),
   * use a shared {@link java.nio.ByteBuffer} instance, or use {@link
   * com.google.common.io.ByteStreams#newDataOutput()} to get a growable buffer.
   */
  @GwtIncompatible // doesn't work
  public static byte[] toByteArray(char value) {
    return new byte[] {(byte) (value >> 8), (byte) value};
  }

  /**
   * Returns the {@code char} value whose big-endian representation is stored in the first 2 bytes
   * of {@code bytes}; equivalent to {@code ByteBuffer.wrap(bytes).getChar()}. For example, the
   * input byte array {@code {0x54, 0x32}} would yield the {@code char} value {@code '\\u5432'}.
   *
   *
Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that library exposes much more
   * flexibility at little cost in readability.
   *
   * @throws IllegalArgumentException if {@code bytes} has fewer than 2 elements
   */
  @GwtIncompatible // doesn't work
  public static char fromByteArray(byte[] bytes) {
    checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
    return fromBytes(bytes[0], bytes[1]);
  }

  /**
   * Returns the {@code char} value whose byte representation is the given 2 bytes, in big-endian
   * order; equivalent to {@code Chars.fromByteArray(new byte[] {b1, b2})}.
   *
   * @since 7.0
   */
  @GwtIncompatible // doesn't work
  public static char fromBytes(byte b1, byte b2) {
    return (char) ((b1 << 8) | (b2 & 0xFF));
  }

  /**
   * 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 char[] ensureCapacity(char[] 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 char} values separated by {@code separator}.
   * For example, {@code join("-", '1', '2', '3')} 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 char} values, possibly empty
   */
  public static String join(String separator, char... array) {
    checkNotNull(separator);
    int len = array.length;
    if (len == 0) {
      return "";
    }

    StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
    builder.append(array[0]);
    for (int i = 1; i < len; i++) {
      builder.append(separator).append(array[i]);
    }
    return builder.toString();
  }

  /**
   * Returns a comparator that compares two {@code char} arrays lexicographically; not advisable
   * for sorting user-visible strings as the ordering may not match the conventions of the user's
   * locale. That is, it compares, using {@link #compare(char, char)}), 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 [] < ['a'] < ['a', 'b'] < ['b']}.
   *
   *
The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays
   * support only identity equality), but it is consistent with {@link Arrays#equals(char[],
   * char[])}.
   *
   * @since 2.0
   */
  public static Comparator<char[]> lexicographicalComparator() {
    return LexicographicalComparator.INSTANCE;
  }

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

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

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

  /**
   * Copies a collection of {@code Character} instances into a new array of primitive {@code char}
   * values.
   *
   *
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 Character} objects
   * @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
   */
  public static char[] toArray(Collection<Character> collection) {
    if (collection instanceof CharArrayAsList) {
      return ((CharArrayAsList) collection).toCharArray();
    }

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

  /**
   * Sorts the elements of {@code array} in descending order.
   *
   * @since 23.1
   */
  public static void sortDescending(char[] 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.
   *
   * @since 23.1
   */
  public static void sortDescending(char[] 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(Chars.asList(array))}, but is likely to be more efficient.
   *
   * @since 23.1
   */
  public static void reverse(char[] 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(Chars.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(char[] array, int fromIndex, int toIndex) {
    checkNotNull(array);
    checkPositionIndexes(fromIndex, toIndex, array.length);
    for (int i = fromIndex, j = toIndex - 1; i < j; i++, j--) {
      char tmp = array[i];
      array[i] = array[j];
      array[j] = tmp;
    }
  }

  /**
   * 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 Character} 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.
   *
   * @param backingArray the array to back the list
   * @return a list view of the array
   */
  public static List<Character> asList(char... backingArray) {
    if (backingArray.length == 0) {
      return Collections.emptyList();
    }
    return new CharArrayAsList(backingArray);
  }

  @GwtCompatible
  private static class CharArrayAsList extends AbstractList<Character>
      implements RandomAccess, Serializable {
    final char[] array;
    final int start;
    final int end;

    CharArrayAsList(char[] array) {
      this(array, 0, array.length);
    }

    CharArrayAsList(char[] 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 Character 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 Character)
          && Chars.indexOf(array, (Character) target, start, end) != -1;
    }

    @Override
    public int indexOf(Object target) {
      // Overridden to prevent a ton of boxing
      if (target instanceof Character) {
        int i = Chars.indexOf(array, (Character) 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 Character) {
        int i = Chars.lastIndexOf(array, (Character) target, start, end);
        if (i >= 0) {
          return i - start;
        }
      }
      return -1;
    }

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

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

    @Override
    public boolean equals(@Nullable Object object) {
      if (object == this) {
        return true;
      }
      if (object instanceof CharArrayAsList) {
        CharArrayAsList that = (CharArrayAsList) 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 + Chars.hashCode(array[i]);
      }
      return result;
    }

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

    char[] toCharArray() {
      return Arrays.copyOfRange(array, start, end);
    }

    private static final long serialVersionUID = 0;
  }
}


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

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.annotations.GwtIncompatible;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Extracts non-overlapping substrings from an input string, typically by recognizing appearances of
 * a separator sequence. This separator can be specified as a single {@linkplain #on(char)
 * character}, fixed {@linkplain #on(String) string}, {@linkplain #onPattern regular expression} or
 * {@link #on(CharMatcher) CharMatcher} instance. Or, instead of using a separator at all, a
 * splitter can extract adjacent substrings of a given {@linkplain #fixedLength fixed length}.
 *
 *
For example, this expression:
 *
 *
{@code
 * Splitter.on(',').split("foo,bar,qux")
 * }

 *
 * ... produces an {@code Iterable} containing {@code "foo"}, {@code "bar"} and {@code "qux"}, in
 * that order.
 *
 *
By default, {@code Splitter}'s behavior is simplistic and unassuming. The following
 * expression:
 *
 *
{@code
 * Splitter.on(',').split(" foo,,,  bar ,")
 * }

 *
 * ... yields the substrings {@code [" foo", "", "", " bar ", ""]}. If this is not the desired
 * behavior, use configuration methods to obtain a new splitter instance with modified
 * behavior:
 *
 *
{@code
 * private static final Splitter MY_SPLITTER = Splitter.on(',')
 *     .trimResults()
 *     .omitEmptyStrings();
 * }

 *
 *
Now {@code MY_SPLITTER.split("foo,,, bar ,")} returns just {@code ["foo", "bar"]}. Note that
 * the order in which these configuration methods are called is never significant.
 *
 *
Warning: Splitter instances are immutable. Invoking a configuration method has no
 * effect on the receiving instance; you must store and use the new splitter instance it returns
 * instead.
 *
 *
{@code
 * // Do NOT do this
 * Splitter splitter = Splitter.on('/');
 * splitter.trimResults(); // does nothing!
 * return splitter.split("wrong / wrong / wrong");
 * }

 *
 *
For separator-based splitters that do not use {@code omitEmptyStrings}, an input string
 * containing {@code n} occurrences of the separator naturally yields an iterable of size {@code n +
 * 1}. So if the separator does not occur anywhere in the input, a single substring is returned
 * containing the entire input. Consequently, all splitters split the empty string to {@code [""]}
 * (note: even fixed-length splitters).
 *
 *
Splitter instances are thread-safe immutable, and are therefore safe to store as {@code static
 * final} constants.
 *
 *
The {@link Joiner} class provides the inverse operation to splitting, but note that a
 * round-trip between the two should be assumed to be lossy.
 *
 *
See the Guava User Guide article on {@code Splitter}.
 *
 * @author Julien Silland
 * @author Jesse Wilson
 * @author Kevin Bourrillion
 * @author Louis Wasserman
 * @since 1.0
 */
@GwtCompatible(emulated = true)
public final class Splitter {
  private final CharMatcher trimmer;
  private final boolean omitEmptyStrings;
  private final Strategy strategy;
  private final int limit;

  private Splitter(Strategy strategy) {
    this(strategy, false, CharMatcher.none(), Integer.MAX_VALUE);
  }

  private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) {
    this.strategy = strategy;
    this.omitEmptyStrings = omitEmptyStrings;
    this.trimmer = trimmer;
    this.limit = limit;
  }

  /**
   * Returns a splitter that uses the given single-character separator. For example, {@code
   * Splitter.on(',').split("foo,,bar")} returns an iterable containing {@code ["foo", "", "bar"]}.
   *
   * @param separator the character to recognize as a separator
   * @return a splitter, with default settings, that recognizes that separator
   */
  public static Splitter on(char separator) {
    return on(CharMatcher.is(separator));
  }

  /**
   * Returns a splitter that considers any single character matched by the given {@code CharMatcher}
   * to be a separator. For example, {@code
   * Splitter.on(CharMatcher.anyOf(";,")).split("foo,;bar,quux")} returns an iterable containing
   * {@code ["foo", "", "bar", "quux"]}.
   *
   * @param separatorMatcher a {@link CharMatcher} that determines whether a character is a
   *     separator
   * @return a splitter, with default settings, that uses this matcher
   */
  public static Splitter on(final CharMatcher separatorMatcher) {
    checkNotNull(separatorMatcher);

    return new Splitter(
        new Strategy() {
          @Override
          public SplittingIterator iterator(Splitter splitter, final CharSequence toSplit) {
            return new SplittingIterator(splitter, toSplit) {
              @Override
              int separatorStart(int start) {
                return separatorMatcher.indexIn(toSplit, start);
              }

              @Override
              int separatorEnd(int separatorPosition) {
                return separatorPosition + 1;
              }
            };
          }
        });
  }

  /**
   * Returns a splitter that uses the given fixed string as a separator. For example, {@code
   * Splitter.on(", ").split("foo, bar,baz")} returns an iterable containing {@code ["foo",
   * "bar,baz"]}.
   *
   * @param separator the literal, nonempty string to recognize as a separator
   * @return a splitter, with default settings, that recognizes that separator
   */
  public static Splitter on(final String separator) {
    checkArgument(separator.length() != 0, "The separator may not be the empty string.");
    if (separator.length() == 1) {
      return Splitter.on(separator.charAt(0));
    }
    return new Splitter(
        new Strategy() {
          @Override
          public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) {
            return new SplittingIterator(splitter, toSplit) {
              @Override
              public int separatorStart(int start) {
                int separatorLength = separator.length();

                positions:
                for (int p = start, last = toSplit.length() - separatorLength; p <= last; p++) {
                  for (int i = 0; i < separatorLength; i++) {
                    if (toSplit.charAt(i + p) != separator.charAt(i)) {
                      continue positions;
                    }
                  }
                  return p;
                }
                return -1;
              }

              @Override
              public int separatorEnd(int separatorPosition) {
                return separatorPosition + separator.length();
              }
            };
          }
        });
  }

  /**
   * Returns a splitter that considers any subsequence matching {@code pattern} to be a separator.
   * For example, {@code Splitter.on(Pattern.compile("\r?\n")).split(entireFile)} splits a string
   * into lines whether it uses DOS-style or UNIX-style line terminators.
   *
   * @param separatorPattern the pattern that determines whether a subsequence is a separator. This
   *     pattern may not match the empty string.
   * @return a splitter, with default settings, that uses this pattern
   * @throws IllegalArgumentException if {@code separatorPattern} matches the empty string
   */
  @GwtIncompatible // java.util.regex
  public static Splitter on(Pattern separatorPattern) {
    return on(new JdkPattern(separatorPattern));
  }

  private static Splitter on(final CommonPattern separatorPattern) {
    checkArgument(
        !separatorPattern.matcher("").matches(),
        "The pattern may not match the empty string: %s",
        separatorPattern);

    return new Splitter(
        new Strategy() {
          @Override
          public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
            final CommonMatcher matcher = separatorPattern.matcher(toSplit);
            return new SplittingIterator(splitter, toSplit) {
              @Override
              public int separatorStart(int start) {
                return matcher.find(start) ? matcher.start() : -1;
              }

              @Override
              public int separatorEnd(int separatorPosition) {
                return matcher.end();
              }
            };
          }
        });
  }

  /**
   * Returns a splitter that considers any subsequence matching a given pattern (regular expression)
   * to be a separator. For example, {@code Splitter.onPattern("\r?\n").split(entireFile)} splits a
   * string into lines whether it uses DOS-style or UNIX-style line terminators. This is equivalent
   * to {@code Splitter.on(Pattern.compile(pattern))}.
   *
   * @param separatorPattern the pattern that determines whether a subsequence is a separator. This
   *     pattern may not match the empty string.
   * @return a splitter, with default settings, that uses this pattern
   * @throws IllegalArgumentException if {@code separatorPattern} matches the empty string or is a
   *     malformed expression
   */
  @GwtIncompatible // java.util.regex
  public static Splitter onPattern(String separatorPattern) {
    return on(Platform.compilePattern(separatorPattern));
  }

  /**
   * Returns a splitter that divides strings into pieces of the given length. For example, {@code
   * Splitter.fixedLength(2).split("abcde")} returns an iterable containing {@code ["ab", "cd",
   * "e"]}. The last piece can be smaller than {@code length} but will never be empty.
   *
   *
Note: if {@link #fixedLength} is used in conjunction with {@link #limit}, the final
   * split piece may be longer than the specified fixed length. This is because the splitter
   * will stop splitting when the limit is reached, and just return the final piece as-is.
   *
   *
Exception: for consistency with separator-based splitters, {@code split("")} does not
   * yield an empty iterable, but an iterable containing {@code ""}. This is the only case in which
   * {@code Iterables.size(split(input))} does not equal {@code IntMath.divide(input.length(),
   * length, CEILING)}. To avoid this behavior, use {@code omitEmptyStrings}.
   *
   * @param length the desired length of pieces after splitting, a positive integer
   * @return a splitter, with default settings, that can split into fixed sized pieces
   * @throws IllegalArgumentException if {@code length} is zero or negative
   */
  public static Splitter fixedLength(final int length) {
    checkArgument(length > 0, "The length may not be less than 1");

    return new Splitter(
        new Strategy() {
          @Override
          public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
            return new SplittingIterator(splitter, toSplit) {
              @Override
              public int separatorStart(int start) {
                int nextChunkStart = start + length;
                return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
              }

              @Override
              public int separatorEnd(int separatorPosition) {
                return separatorPosition;
              }
            };
          }
        });
  }

  /**
   * Returns a splitter that behaves equivalently to {@code this} splitter, but automatically omits
   * empty strings from the results. For example, {@code
   * Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an iterable containing only
   * {@code ["a", "b", "c"]}.
   *
   *
If either {@code trimResults} option is also specified when creating a splitter, that
   * splitter always trims results first before checking for emptiness. So, for example, {@code
   * Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns an empty iterable.
   *
   *
Note that it is ordinarily not possible for {@link #split(CharSequence)} to return an empty
   * iterable, but when using this option, it can (if the input sequence consists of nothing but
   * separators).
   *
   * @return a splitter with the desired configuration
   */
  public Splitter omitEmptyStrings() {
    return new Splitter(strategy, true, trimmer, limit);
  }

  /**
   * Returns a splitter that behaves equivalently to {@code this} splitter but stops splitting after
   * it reaches the limit. The limit defines the maximum number of items returned by the iterator,
   * or the maximum size of the list returned by {@link #splitToList}.
   *
   *
For example, {@code Splitter.on(',').limit(3).split("a,b,c,d")} returns an iterable
   * containing {@code ["a", "b", "c,d"]}. When omitting empty strings, the omitted strings do not
   * count. Hence, {@code Splitter.on(',').limit(3).omitEmptyStrings().split("a,,,b,,,c,d")} returns
   * an iterable containing {@code ["a", "b", "c,d"}. When trim is requested, all entries are
   * trimmed, including the last. Hence {@code Splitter.on(',').limit(3).trimResults().split(" a , b
   * , c , d ")} results in {@code ["a", "b", "c , d"]}.
   *
   * @param limit the maximum number of items returned
   * @return a splitter with the desired configuration
   * @since 9.0
   */
  public Splitter limit(int limit) {
    checkArgument(limit > 0, "must be greater than zero: %s", limit);
    return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
  }

  /**
   * Returns a splitter that behaves equivalently to {@code this} splitter, but automatically
   * removes leading and trailing {@linkplain CharMatcher#whitespace whitespace} from each returned
   * substring; equivalent to {@code trimResults(CharMatcher.whitespace())}. For example, {@code
   * Splitter.on(',').trimResults().split(" a, b ,c ")} returns an iterable containing {@code ["a",
   * "b", "c"]}.
   *
   * @return a splitter with the desired configuration
   */
  public Splitter trimResults() {
    return trimResults(CharMatcher.whitespace());
  }

  /**
   * Returns a splitter that behaves equivalently to {@code this} splitter, but removes all leading
   * or trailing characters matching the given {@code CharMatcher} from each returned substring. For
   * example, {@code Splitter.on(',').trimResults(CharMatcher.is('_')).split("_a ,_b_ ,c__")}
   * returns an iterable containing {@code ["a ", "b_ ", "c"]}.
   *
   * @param trimmer a {@link CharMatcher} that determines whether a character should be removed from
   *     the beginning/end of a subsequence
   * @return a splitter with the desired configuration
   */
  // TODO(kevinb): throw if a trimmer was already specified!
  public Splitter trimResults(CharMatcher trimmer) {
    checkNotNull(trimmer);
    return new Splitter(strategy, omitEmptyStrings, trimmer, limit);
  }

  /**
   * Splits {@code sequence} into string components and makes them available through an {@link
   * Iterator}, which may be lazily evaluated. If you want an eagerly computed {@link List}, use
   * {@link #splitToList(CharSequence)}.
   *
   * @param sequence the sequence of characters to split
   * @return an iteration over the segments split from the parameter
   */
  public Iterable<String> split(final CharSequence sequence) {
    checkNotNull(sequence);

    return new Iterable<String>() {
      @Override
      public Iterator<String> iterator() {
        return splittingIterator(sequence);
      }

      @Override
      public String toString() {
        return Joiner.on(", ")
            .appendTo(new StringBuilder().append('['), this)
            .append(']')
            .toString();
      }
    };
  }

  private Iterator<String> splittingIterator(CharSequence sequence) {
    return strategy.iterator(this, sequence);
  }

  /**
   * Splits {@code sequence} into string components and returns them as an immutable list. If you
   * want an {@link Iterable} which may be lazily evaluated, use {@link #split(CharSequence)}.
   *
   * @param sequence the sequence of characters to split
   * @return an immutable list of the segments split from the parameter
   * @since 15.0
   */
  public List<String> splitToList(CharSequence sequence) {
    checkNotNull(sequence);

    Iterator<String> iterator = splittingIterator(sequence);
    List<String> result = new ArrayList<>();

    while (iterator.hasNext()) {
      result.add(iterator.next());
    }

    return Collections.unmodifiableList(result);
  }

  /**
   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
   * into keys and values using the specified separator.
   *
   * @since 10.0
   */
  @Beta
  public MapSplitter withKeyValueSeparator(String separator) {
    return withKeyValueSeparator(on(separator));
  }

  /**
   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
   * into keys and values using the specified separator.
   *
   * @since 14.0
   */
  @Beta
  public MapSplitter withKeyValueSeparator(char separator) {
    return withKeyValueSeparator(on(separator));
  }

  /**
   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
   * into keys and values using the specified key-value splitter.
   *
   *
Note: Any configuration option configured on this splitter, such as {@link #trimResults},
   * does not change the behavior of the {@code keyValueSplitter}.
   *
   *
Example:
   *
   *
{@code
   * String toSplit = " x -> y, z-> a ";
   * Splitter outerSplitter = Splitter.on(',').trimResults();
   * MapSplitter mapSplitter = outerSplitter.withKeyValueSeparator(Splitter.on("->"));
   * Map<String, String> result = mapSplitter.split(toSplit);
   * assertThat(result).isEqualTo(ImmutableMap.of("x ", " y", "z", " a"));
   * }

   *
   * @since 10.0
   */
  @Beta
  public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
    return new MapSplitter(this, keyValueSplitter);
  }

  /**
   * An object that splits strings into maps as {@code Splitter} splits iterables and lists. Like
   * {@code Splitter}, it is thread-safe and immutable. The common way to build instances is by
   * providing an additional {@linkplain Splitter#withKeyValueSeparator key-value separator} to
   * {@link Splitter}.
   *
   * @since 10.0
   */
  @Beta
  public static final class MapSplitter {
    private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
    private final Splitter outerSplitter;
    private final Splitter entrySplitter;

    private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) {
      this.outerSplitter = outerSplitter; // only "this" is passed
      this.entrySplitter = checkNotNull(entrySplitter);
    }

    /**
     * Splits {@code sequence} into substrings, splits each substring into an entry, and returns an
     * unmodifiable map with each of the entries. For example, {@code
     * Splitter.on(';').trimResults().withKeyValueSeparator("=>").split("a=>b ; c=>b")} will return
     * a mapping from {@code "a"} to {@code "b"} and {@code "c"} to {@code "b"}.
     *
     *
The returned map preserves the order of the entries from {@code sequence}.
     *
     * @throws IllegalArgumentException if the specified sequence does not split into valid map
     *     entries, or if there are duplicate keys
     */
    public Map<String, String> split(CharSequence sequence) {
      Map<String, String> map = new LinkedHashMap<>();
      for (String entry : outerSplitter.split(sequence)) {
        Iterator<String> entryFields = entrySplitter.splittingIterator(entry);

        checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
        String key = entryFields.next();
        checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);

        checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
        String value = entryFields.next();
        map.put(key, value);

        checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
      }
      return Collections.unmodifiableMap(map);
    }
  }

  private interface Strategy {
    Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
  }

  private abstract static class SplittingIterator extends AbstractIterator<String> {
    final CharSequence toSplit;
    final CharMatcher trimmer;
    final boolean omitEmptyStrings;

    /**
     * Returns the first index in {@code toSplit} at or after {@code start} that contains the
     * separator.
     */
    abstract int separatorStart(int start);

    /**
     * Returns the first index in {@code toSplit} after {@code separatorPosition} that does not
     * contain a separator. This method is only invoked after a call to {@code separatorStart}.
     */
    abstract int separatorEnd(int separatorPosition);

    int offset = 0;
    int limit;

    protected SplittingIterator(Splitter splitter, CharSequence toSplit) {
      this.trimmer = splitter.trimmer;
      this.omitEmptyStrings = splitter.omitEmptyStrings;
      this.limit = splitter.limit;
      this.toSplit = toSplit;
    }

    @Override
    protected String computeNext() {
      /*
       * The returned string will be from the end of the last match to the beginning of the next
       * one. nextStart is the start position of the returned substring, while offset is the place
       * to start looking for a separator.
       */
      int nextStart = offset;
      while (offset != -1) {
        int start = nextStart;
        int end;

        int separatorPosition = separatorStart(offset);
        if (separatorPosition == -1) {
          end = toSplit.length();
          offset = -1;
        } else {
          end = separatorPosition;
          offset = separatorEnd(separatorPosition);
        }
        if (offset == nextStart) {
          /*
           * This occurs when some pattern has an empty match, even if it doesn't match the empty
           * string -- for example, if it requires lookahead or the like. The offset must be
           * increased to look for separators beyond this point, without changing the start position
           * of the next returned substring -- so nextStart stays the same.
           */
          offset++;
          if (offset > toSplit.length()) {
            offset = -1;
          }
          continue;
        }

        while (start < end && trimmer.matches(toSplit.charAt(start))) {
          start++;
        }
        while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
          end--;
        }

        if (omitEmptyStrings && start == end) {
          // Don't include the (unused) separator in next split string.
          nextStart = offset;
          continue;
        }

        if (limit == 1) {
          // The limit has been reached, return the rest of the string as the
          // final item. This is tested after empty string removal so that
          // empty strings do not count towards the limit.
          end = toSplit.length();
          offset = -1;
          // Since we may have changed the end, we need to trim it again.
          while (end > start && trimmer.matches(toSplit.charAt(end - 1))) {
            end--;
          }
        } else {
          limit--;
        }

        return toSplit.subSequence(start, end).toString();
      }
      return endOfData();
    }
  }
}


/*
 * 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.common.base.Objects;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A multiset which forwards all its method calls to another multiset. Subclasses should override
 * one or more methods to modify the behavior of the backing multiset as desired per the decorator pattern.
 *
 *
Warning: The methods of {@code ForwardingMultiset} forward indiscriminately to
 * the methods of the delegate. For example, overriding {@link #add(Object, int)} alone will
 * not change the behavior of {@link #add(Object)}, which can lead to unexpected behavior. In
 * this case, you should override {@code add(Object)} as well, either providing your own
 * implementation, or delegating to the provided {@code standardAdd} 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 ForwardingMultiset}.
 *
 *
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 Kevin Bourrillion
 * @author Louis Wasserman
 * @since 2.0
 */
@GwtCompatible
public abstract class ForwardingMultiset<E> extends ForwardingCollection<E> implements Multiset<E> {

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

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

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

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

  @CanIgnoreReturnValue
  @Override
  public int remove(Object element, int occurrences) {
    return delegate().remove(element, occurrences);
  }

  @Override
  public Set<E> elementSet() {
    return delegate().elementSet();
  }

  @Override
  public Set<Entry<E>> entrySet() {
    return delegate().entrySet();
  }

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

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

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

  @CanIgnoreReturnValue
  @Override
  public boolean setCount(E element, int oldCount, int newCount) {
    return delegate().setCount(element, oldCount, newCount);
  }

  /**
   * A sensible definition of {@link #contains} in terms of {@link #count}. If you override {@link
   * #count}, you may wish to override {@link #contains} to forward to this implementation.
   *
   * @since 7.0
   */
  @Override
  protected boolean standardContains(@Nullable Object object) {
    return count(object) > 0;
  }

  /**
   * A sensible definition of {@link #clear} in terms of the {@code iterator} method of {@link
   * #entrySet}. If you override {@link #entrySet}, you may wish to override {@link #clear} to
   * forward to this implementation.
   *
   * @since 7.0
   */
  @Override
  protected void standardClear() {
    Iterators.clear(entrySet().iterator());
  }

  /**
   * A sensible, albeit inefficient, definition of {@link #count} in terms of {@link #entrySet}. If
   * you override {@link #entrySet}, you may wish to override {@link #count} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  @Beta
  protected int standardCount(@Nullable Object object) {
    for (Entry<?> entry : this.entrySet()) {
      if (Objects.equal(entry.getElement(), object)) {
        return entry.getCount();
      }
    }
    return 0;
  }

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

  /**
   * A sensible definition of {@link #addAll(Collection)} in terms of {@link #add(Object)} and
   * {@link #add(Object, int)}. If you override either of these methods, you may wish to override
   * {@link #addAll(Collection)} to forward to this implementation.
   *
   * @since 7.0
   */
  @Beta
  @Override
  protected boolean standardAddAll(Collection<? extends E> elementsToAdd) {
    return Multisets.addAllImpl(this, elementsToAdd);
  }

  /**
   * A sensible definition of {@link #remove(Object)} in terms of {@link #remove(Object, int)}. If
   * you override {@link #remove(Object, int)}, you may wish to override {@link #remove(Object)} to
   * forward to this implementation.
   *
   * @since 7.0
   */
  @Override
  protected boolean standardRemove(Object element) {
    return remove(element, 1) > 0;
  }

  /**
   * A sensible definition of {@link #removeAll} in terms of the {@code removeAll} method of {@link
   * #elementSet}. If you override {@link #elementSet}, you may wish to override {@link #removeAll}
   * to forward to this implementation.
   *
   * @since 7.0
   */
  @Override
  protected boolean standardRemoveAll(Collection<?> elementsToRemove) {
    return Multisets.removeAllImpl(this, elementsToRemove);
  }

  /**
   * A sensible definition of {@link #retainAll} in terms of the {@code retainAll} method of {@link
   * #elementSet}. If you override {@link #elementSet}, you may wish to override {@link #retainAll}
   * to forward to this implementation.
   *
   * @since 7.0
   */
  @Override
  protected boolean standardRetainAll(Collection<?> elementsToRetain) {
    return Multisets.retainAllImpl(this, elementsToRetain);
  }

  /**
   * A sensible definition of {@link #setCount(Object, int)} in terms of {@link #count(Object)},
   * {@link #add(Object, int)}, and {@link #remove(Object, int)}. {@link #entrySet()}. If you
   * override any of these methods, you may wish to override {@link #setCount(Object, int)} to
   * forward to this implementation.
   *
   * @since 7.0
   */
  protected int standardSetCount(E element, int count) {
    return Multisets.setCountImpl(this, element, count);
  }

  /**
   * A sensible definition of {@link #setCount(Object, int, int)} in terms of {@link #count(Object)}
   * and {@link #setCount(Object, int)}. If you override either of these methods, you may wish to
   * override {@link #setCount(Object, int, int)} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardSetCount(E element, int oldCount, int newCount) {
    return Multisets.setCountImpl(this, element, oldCount, newCount);
  }

  /**
   * A sensible implementation of {@link Multiset#elementSet} in terms of the following methods:
   * {@link ForwardingMultiset#clear}, {@link ForwardingMultiset#contains}, {@link
   * ForwardingMultiset#containsAll}, {@link ForwardingMultiset#count}, {@link
   * ForwardingMultiset#isEmpty}, the {@link Set#size} and {@link Set#iterator} methods of {@link
   * ForwardingMultiset#entrySet}, and {@link ForwardingMultiset#remove(Object, int)}. In many
   * situations, you may wish to override {@link ForwardingMultiset#elementSet} to forward to this
   * implementation or a subclass thereof.
   *
   * @since 10.0
   */
  @Beta
  protected class StandardElementSet extends Multisets.ElementSet<E> {
    /** Constructor for use by subclasses. */
    public StandardElementSet() {}

    @Override
    Multiset<E> multiset() {
      return ForwardingMultiset.this;
    }

    @Override
    public Iterator<E> iterator() {
      return Multisets.elementIterator(multiset().entrySet().iterator());
    }
  }

  /**
   * A sensible definition of {@link #iterator} in terms of {@link #entrySet} and {@link
   * #remove(Object)}. If you override either of these methods, you may wish to override {@link
   * #iterator} to forward to this implementation.
   *
   * @since 7.0
   */
  protected Iterator<E> standardIterator() {
    return Multisets.iteratorImpl(this);
  }

  /**
   * A sensible, albeit inefficient, definition of {@link #size} in terms of {@link #entrySet}. If
   * you override {@link #entrySet}, you may wish to override {@link #size} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  protected int standardSize() {
    return Multisets.linearTimeSizeImpl(this);
  }

  /**
   * A sensible, albeit inefficient, definition of {@link #equals} in terms of {@code
   * entrySet().size()} and {@link #count}. If you override either of these methods, you may wish to
   * override {@link #equals} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardEquals(@Nullable Object object) {
    return Multisets.equalsImpl(this, object);
  }

  /**
   * A sensible definition of {@link #hashCode} as {@code entrySet().hashCode()} . If you override
   * {@link #entrySet}, you may wish to override {@link #hashCode} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  protected int standardHashCode() {
    return entrySet().hashCode();
  }

  /**
   * A sensible definition of {@link #toString} as {@code entrySet().toString()} . If you override
   * {@link #entrySet}, you may wish to override {@link #toString} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  @Override
  protected String standardToString() {
    return entrySet().toString();
  }
}