/**
  * Shuffles the given array with the given random function.
  *
  * @return mutated parameter array that was shuffled beforehand.
  */
 @SafeVarargs
 public static <T> T[] multiShuffle(T[] array, Random rnd, T[]... additions) {
   for (int i = array.length; i > 1; i--) {
     final int swapIndex = rnd.nextInt(i);
     swap(array, i - 1, swapIndex);
     for (T[] arr : additions) {
       swap(arr, i - 1, swapIndex);
     }
   }
   return array;
 }
 /**
  * Partitions the given array in-place and uses the end element as pivot, everything less than the
  * pivot will be placed left and everything greater will be placed right of the pivot. It returns
  * the index of the pivot element after partitioning.
  */
 public static int partition(double[] array, int start, int end) {
   final int ending = end - 1;
   final double x = array[ending];
   int i = start - 1;
   for (int j = start; j < ending; j++) {
     if (array[j] <= x) {
       i++;
       swap(array, i, j);
     }
   }
   i++;
   swap(array, i, ending);
   return i;
 }
 /**
  * Partitions the given array in-place and uses the end element as pivot, everything less than the
  * pivot will be placed left and everything greater will be placed right of the pivot. It returns
  * the index of the pivot element after partitioning.
  */
 public static <T extends Comparable<T>> int partition(T[] array, int start, int end) {
   final int ending = end - 1;
   final T x = array[ending];
   int i = start - 1;
   for (int j = start; j < ending; j++) {
     if (array[j].compareTo(x) < 0) {
       i++;
       swap(array, i, j);
     }
   }
   i++;
   swap(array, i, ending);
   return i;
 }
  /**
   * Partitions the given array in-place and uses the end element as pivot, everything less than the
   * pivot will be placed left and everything greater will be placed right of the pivot. It returns
   * the index of the pivot element after partitioning. This is a multi way partitioning algorithm,
   * you have to provide a partition array index to know which is the array that needs to be
   * partitioned. The swap operations are applied on the other elements as well.
   */
  private static int multiPartition(int[][] array, int start, int end, int partitionArrayIndex) {
    final int ending = end - 1;
    final int x = array[partitionArrayIndex][ending];
    int i = start - 1;
    for (int j = start; j < ending; j++) {
      if (array[partitionArrayIndex][j] <= x) {
        i++;
        for (int[] anArray : array) {
          swap(anArray, i, j);
        }
      }
    }
    i++;
    for (int[] anArray : array) {
      swap(anArray, i, ending);
    }

    return i;
  }
  /**
   * Partitions the given array in-place and uses the end element as pivot, everything less than the
   * pivot will be placed left and everything greater will be placed right of the pivot. It returns
   * the index of the pivot element after partitioning. This is a multi way partitioning algorithm,
   * you have to provide a partition array index to know which is the array that needs to be
   * partitioned. The swap operations are applied on the other elements as well.
   */
  private static <T extends Comparable<T>> int multiPartition(
      T[][] array, int start, int end, int partitionArrayIndex) {
    final int ending = end - 1;
    final T x = array[partitionArrayIndex][ending];
    int i = start - 1;
    for (int j = start; j < ending; j++) {
      if (array[partitionArrayIndex][j].compareTo(x) < 0) {
        i++;
        for (T[] anArray : array) {
          swap(anArray, i, j);
        }
      }
    }
    i++;
    for (T[] anArray : array) {
      swap(anArray, i, ending);
    }

    return i;
  }
 /**
  * Shuffles the given array with the given random function.
  *
  * @return mutated parameter array that was shuffled beforehand.
  */
 public static <T> T[] shuffle(T[] array, Random rnd) {
   for (int i = array.length; i > 1; i--) swap(array, i - 1, rnd.nextInt(i));
   return array;
 }