jdk/src/share/classes/java/util/DualPivotQuicksort.java
changeset 6896 d229d56fd918
parent 5995 0b76e67c2054
child 8188 b90884cf34f5
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Thu Oct 14 18:01:47 2010 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Fri Oct 15 12:10:32 2010 +0100
@@ -36,7 +36,7 @@
  * @author Jon Bentley
  * @author Josh Bloch
  *
- * @version 2010.06.21 m765.827.12i:5\7
+ * @version 2010.10.13 m765.827.12i:5\7p
  * @since 1.7
  */
 final class DualPivotQuicksort {
@@ -54,26 +54,26 @@
      * If the length of an array to be sorted is less than this
      * constant, insertion sort is used in preference to Quicksort.
      */
-    private static final int INSERTION_SORT_THRESHOLD = 32;
+    private static final int INSERTION_SORT_THRESHOLD = 47;
 
     /**
-     * If the length of a byte array to be sorted is greater than
-     * this constant, counting sort is used in preference to Quicksort.
+     * If the length of a byte array to be sorted is greater than this
+     * constant, counting sort is used in preference to insertion sort.
      */
-    private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 128;
+    private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 29;
 
     /**
      * If the length of a short or char array to be sorted is greater
      * than this constant, counting sort is used in preference to Quicksort.
      */
-    private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
+    private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 3200;
 
     /*
      * Sorting methods for seven primitive types.
      */
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
@@ -82,58 +82,34 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(int[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sort(a, fromIndex, toIndex - 1, true);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     */
+    public static void sort(int[] a, int left, int right) {
+        sort(a, left, right, true);
+    }
+
+    /**
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(int[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    int ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     int ai = a[i + 1];
@@ -145,12 +121,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    int a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                int last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -232,10 +250,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 int ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -244,13 +266,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -265,7 +291,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -299,7 +325,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     int ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -311,7 +337,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -337,7 +363,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -356,28 +382,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 int ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -397,14 +415,18 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
@@ -413,58 +435,34 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(long[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sort(a, fromIndex, toIndex - 1, true);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     */
+    public static void sort(long[] a, int left, int right) {
+        sort(a, left, right, true);
+    }
+
+    /**
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(long[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    long ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     long ai = a[i + 1];
@@ -476,12 +474,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    long a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                long last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -563,10 +603,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 long ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -575,13 +619,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -596,7 +644,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -630,7 +678,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     long ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -642,7 +690,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -668,7 +716,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -687,28 +735,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 long ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -728,45 +768,51 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(short[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
+    public static void sort(short[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            int[] count = new int[NUM_SHORT_VALUES];
 
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i] - Short.MIN_VALUE]++;
+            }
+            for (int i = NUM_SHORT_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                short value = (short) (i + Short.MIN_VALUE);
+                int s = count[i];
+
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
+            }
+        } else { // Use Dual-Pivot Quicksort on small arrays
+            sort(a, left, right, true);
         }
     }
 
@@ -774,66 +820,23 @@
     private static final int NUM_SHORT_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void countingSort(short[] a, int left, int right) {
-        int[] count = new int[NUM_SHORT_VALUES];
-
-        for (int i = left; i <= right; i++) {
-            count[a[i] - Short.MIN_VALUE]++;
-        }
-        for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) {
-            while (count[i] == 0) {
-                i--;
-            }
-            short value = (short) (i + Short.MIN_VALUE);
-            int s = count[i];
-
-            do {
-                a[k--] = value;
-            } while (--s > 0);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(short[] a, int left, int right,boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    short ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     short ai = a[i + 1];
@@ -845,12 +848,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    short a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                short last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -932,10 +977,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 short ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -944,13 +993,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -965,7 +1018,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -999,7 +1052,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     short ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -1011,7 +1064,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -1037,7 +1090,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -1056,28 +1109,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 short ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -1097,45 +1142,51 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(char[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
+    public static void sort(char[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            int[] count = new int[NUM_CHAR_VALUES];
 
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i]]++;
+            }
+            for (int i = NUM_CHAR_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                char value = (char) i;
+                int s = count[i];
+
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
+            }
+        } else { // Use Dual-Pivot Quicksort on small arrays
+            sort(a, left, right, true);
         }
     }
 
@@ -1143,66 +1194,23 @@
     private static final int NUM_CHAR_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void countingSort(char[] a, int left, int right) {
-        int[] count = new int[NUM_CHAR_VALUES];
-
-        for (int i = left; i <= right; i++) {
-            count[a[i]]++;
-        }
-        for (int i = 0, k = left; k <= right; i++) {
-            while (count[i] == 0) {
-                i++;
-            }
-            char value = (char) i;
-            int s = count[i];
-
-            do {
-                a[k++] = value;
-            } while (--s > 0);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(char[] a, int left, int right, boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    char ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     char ai = a[i + 1];
@@ -1214,12 +1222,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    char a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                char last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -1301,10 +1351,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 char ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -1313,13 +1367,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -1334,7 +1392,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -1368,7 +1426,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     char ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -1380,7 +1438,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -1406,7 +1464,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -1425,28 +1483,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 char ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -1466,442 +1516,90 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(byte[] a) {
-        if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            countingSort(a, 0, a.length - 1);
-        } else {
-            sort(a, 0, a.length - 1, true);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(byte[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-
-        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            countingSort(a, fromIndex, toIndex - 1);
-        } else {
-            sort(a, fromIndex, toIndex - 1, true);
-        }
-    }
-
     /** The number of distinct byte values. */
     private static final int NUM_BYTE_VALUES = 1 << 8;
 
     /**
-     * Sorts the specified range of the array by counting sort.
+     * Sorts the specified array.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(byte[] a) {
+        sort(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void countingSort(byte[] a, int left, int right) {
-        int[] count = new int[NUM_BYTE_VALUES];
+    public static void sort(byte[] a, int left, int right) {
+        // Use counting sort on large arrays
+        if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+            int[] count = new int[NUM_BYTE_VALUES];
+
+            for (int i = left - 1; ++i <= right; ) {
+                count[a[i] - Byte.MIN_VALUE]++;
+            }
+            for (int i = NUM_BYTE_VALUES, k = right + 1; k > left; ) {
+                while (count[--i] == 0);
+                byte value = (byte) (i + Byte.MIN_VALUE);
+                int s = count[i];
 
-        for (int i = left; i <= right; i++) {
-            count[a[i] - Byte.MIN_VALUE]++;
-        }
-        for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) {
-            while (count[i] == 0) {
-                i--;
+                do {
+                    a[--k] = value;
+                } while (--s > 0);
             }
-            byte value = (byte) (i + Byte.MIN_VALUE);
-            int s = count[i];
-
-            do {
-                a[k--] = value;
-            } while (--s > 0);
+        } else { // Use insertion sort on small arrays
+            for (int i = left, j = i; i < right; j = ++i) {
+                byte ai = a[i + 1];
+                while (ai < a[j]) {
+                    a[j + 1] = a[j];
+                    if (j-- == left) {
+                        break;
+                    }
+                }
+                a[j + 1] = ai;
+            }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
-     */
-    private static void sort(byte[] a, int left, int right, boolean leftmost) {
-        int length = right - left + 1;
-
-        // Use insertion sort on tiny arrays
-        if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
-                /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    byte ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
-                 */
-                for (int i = left, j = i; i < right; j = ++i) {
-                    byte ai = a[i + 1];
-                    while (ai < a[j]) {
-                        a[j + 1] = a[j];
-                        if (j-- == left) {
-                            break;
-                        }
-                    }
-                    a[j + 1] = ai;
-                }
-            }
-            return;
-        }
-
-        // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
-
-        /*
-         * Sort five evenly spaced elements around (and including) the
-         * center element in the range. These elements will be used for
-         * pivot selection as described below. The choice for spacing
-         * these elements was empirically determined to work well on
-         * a wide variety of inputs.
-         */
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e2 = e3 - seventh;
-        int e1 = e2 - seventh;
-        int e4 = e3 + seventh;
-        int e5 = e4 + seventh;
-
-        // Sort these elements using insertion sort
-        if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
-
-        if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t;
-            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-        }
-        if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t;
-            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
-                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-            }
-        }
-        if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t;
-            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
-                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
-                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
-                }
-            }
-        }
-
-        /*
-         * Use the second and fourth of the five sorted elements as pivots.
-         * These values are inexpensive approximations of the first and
-         * second terciles of the array. Note that pivot1 <= pivot2.
-         */
-        byte pivot1 = a[e2];
-        byte pivot2 = a[e4];
-
-        // Pointers
-        int less  = left;  // The index of the first element of center part
-        int great = right; // The index before the first element of right part
-
-        if (pivot1 != pivot2) {
-            /*
-             * The first and the last elements to be sorted are moved to the
-             * locations formerly occupied by the pivots. When partitioning
-             * is complete, the pivots are swapped back into their final
-             * positions, and excluded from subsequent sorting.
-             */
-            a[e2] = a[left];
-            a[e4] = a[right];
-
-            /*
-             * Skip elements, which are less or greater than pivot values.
-             */
-            while (a[++less] < pivot1);
-            while (a[--great] > pivot2);
-
-            /*
-             * Partitioning:
-             *
-             *   left part           center part                   right part
-             * +--------------------------------------------------------------+
-             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
-             * +--------------------------------------------------------------+
-             *               ^                          ^       ^
-             *               |                          |       |
-             *              less                        k     great
-             *
-             * Invariants:
-             *
-             *              all in (left, less)   < pivot1
-             *    pivot1 <= all in [less, k)     <= pivot2
-             *              all in (great, right) > pivot2
-             *
-             * Pointer k is the first index of ?-part.
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-                if (ak < pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less] = ak;
-                    less++;
-                } else if (ak > pivot2) { // Move a[k] to right part
-                    while (a[great] > pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] < pivot1) {
-                        a[k] = a[less];
-                        a[less] = a[great];
-                        less++;
-                    } else { // pivot1 <= a[great] <= pivot2
-                        a[k] = a[great];
-                    }
-                    a[great] = ak;
-                    great--;
-                }
-            }
-
-            // Swap pivots into their final positions
-            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-            a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-            // Sort left and right parts recursively, excluding known pivots
-            sort(a, left, less - 2, leftmost);
-            sort(a, great + 2, right, false);
-
-            /*
-             * If center part is too large (comprises > 5/7 of the array),
-             * swap internal pivot values to ends.
-             */
-            if (less < e1 && e5 < great) {
-                /*
-                 * Skip elements, which are equal to pivot values.
-                 */
-                while (a[less] == pivot1) {
-                    less++;
-                }
-                while (a[great] == pivot2) {
-                    great--;
-                }
-
-                /*
-                 * Partitioning:
-                 *
-                 *   left part         center part                  right part
-                 * +----------------------------------------------------------+
-                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-                 * +----------------------------------------------------------+
-                 *              ^                        ^       ^
-                 *              |                        |       |
-                 *             less                      k     great
-                 *
-                 * Invariants:
-                 *
-                 *              all in (*,  less) == pivot1
-                 *     pivot1 < all in [less,  k)  < pivot2
-                 *              all in (great, *) == pivot2
-                 *
-                 * Pointer k is the first index of ?-part.
-                 */
-                outer:
-                for (int k = less; k <= great; k++) {
-                    byte ak = a[k];
-                    if (ak == pivot1) { // Move a[k] to left part
-                        a[k] = a[less];
-                        a[less] = ak;
-                        less++;
-                    } else if (ak == pivot2) { // Move a[k] to right part
-                        while (a[great] == pivot2) {
-                            if (great-- == k) {
-                                break outer;
-                            }
-                        }
-                        if (a[great] == pivot1) {
-                            a[k] = a[less];
-                            /*
-                             * Even though a[great] equals to pivot1, the
-                             * assignment a[less] = pivot1 may be incorrect,
-                             * if a[great] and pivot1 are floating-point zeros
-                             * of different signs. Therefore in float and
-                             * double sorting methods we have to use more
-                             * accurate assignment a[less] = a[great].
-                             */
-                            a[less] = pivot1;
-                            less++;
-                        } else { // pivot1 < a[great] < pivot2
-                            a[k] = a[great];
-                        }
-                        a[great] = ak;
-                        great--;
-                    }
-                }
-            }
-
-            // Sort center part recursively
-            sort(a, less, great, false);
-
-        } else { // Pivots are equal
-            /*
-             * Partition degenerates to the traditional 3-way
-             * (or "Dutch National Flag") schema:
-             *
-             *   left part    center part              right part
-             * +-------------------------------------------------+
-             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
-             * +-------------------------------------------------+
-             *              ^              ^        ^
-             *              |              |        |
-             *             less            k      great
-             *
-             * Invariants:
-             *
-             *   all in (left, less)   < pivot
-             *   all in [less, k)     == pivot
-             *   all in (great, right) > pivot
-             *
-             * Pointer k is the first index of ?-part.
-             */
-            for (int k = left; k <= great; k++) {
-                if (a[k] == pivot1) {
-                    continue;
-                }
-                byte ak = a[k];
-
-                if (ak < pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less] = ak;
-                    less++;
-                } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
-                    while (a[great] > pivot1) {
-                        // assert great > k;
-                        great--;
-                    }
-                    if (a[great] < pivot1) {
-                        a[k] = a[less];
-                        a[less] = a[great];
-                        less++;
-                    } else { // a[great] == pivot1
-                        /*
-                         * Even though a[great] equals to pivot1, the
-                         * assignment a[k] = pivot1 may be incorrect,
-                         * if a[great] and pivot1 are floating-point
-                         * zeros of different signs. Therefore in float
-                         * and double sorting methods we have to use
-                         * more accurate assignment a[k] = a[great].
-                         */
-                        a[k] = pivot1;
-                    }
-                    a[great] = ak;
-                    great--;
-                }
-            }
-
-            // Sort left and right parts recursively
-            sort(a, left, less - 1, leftmost);
-            sort(a, great + 1, right, false);
-        }
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(float[] a) {
-        sortNegZeroAndNaN(a, 0, a.length - 1);
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(float[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The
-     * sort is done in three phases to avoid expensive comparisons in the
-     * inner loop. The comparisons would be expensive due to anomalies
-     * associated with negative zero {@code -0.0f} and {@code Float.NaN}.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void sortNegZeroAndNaN(float[] a, int left, int right) {
+    public static void sort(float[] a, int left, int right) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
         while (left <= right && Float.isNaN(a[right])) {
             right--;
         }
-        for (int k = right - 1; k >= left; k--) {
+        for (int k = right; --k >= left; ) {
             float ak = a[k];
             if (ak != ak) { // a[k] is NaN
                 a[k] = a[right];
@@ -1921,7 +1619,7 @@
         int hi = right;
 
         /*
-         * Search first zero, or first positive, or last negative element.
+         * Find the first zero, or first positive, or last negative element.
          */
         while (left < hi) {
             int middle = (left + hi) >>> 1;
@@ -1946,12 +1644,12 @@
          *
          * Partitioning:
          *
-         * +---------------------------------------------------+
-         * |   < 0.0   |   -0.0   |    0.0    |  ?  ( >= 0.0 ) |
-         * +---------------------------------------------------+
-         *              ^          ^           ^
-         *              |          |           |
-         *             left        p           k
+         * +----------------------------------------------------+
+         * |   < 0.0   |   -0.0   |   0.0   |   ?  ( >= 0.0 )   |
+         * +----------------------------------------------------+
+         *              ^          ^         ^
+         *              |          |         |
+         *             left        p         k
          *
          * Invariants:
          *
@@ -1962,53 +1660,36 @@
          *
          * Pointer k is the first index of ?-part.
          */
-        for (int k = left + 1, p = left; k <= right; k++) {
+        for (int k = left, p = left - 1; ++k <= right; ) {
             float ak = a[k];
             if (ak != 0.0f) {
                 break;
             }
             if (Float.floatToRawIntBits(ak) < 0) { // ak is -0.0f
                 a[k] = 0.0f;
-                a[p++] = -0.0f;
+                a[++p] = -0.0f;
             }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(float[] a, int left, int right,boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    float ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     float ai = a[i + 1];
@@ -2020,12 +1701,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    float a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                float last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -2107,10 +1830,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 float ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -2119,13 +1846,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -2140,7 +1871,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -2174,7 +1905,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     float ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -2186,7 +1917,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -2212,7 +1943,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -2231,28 +1962,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 float ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -2272,73 +1995,40 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
 
     /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
+     * Sorts the specified array.
      *
      * @param a the array to be sorted
      */
     public static void sort(double[] a) {
-        sortNegZeroAndNaN(a, 0, a.length - 1);
+        sort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty (and the call is a no-op).
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(double[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The
-     * sort is done in three phases to avoid expensive comparisons in the
-     * inner loop. The comparisons would be expensive due to anomalies
-     * associated with negative zero {@code -0.0d} and {@code Double.NaN}.
+     * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void sortNegZeroAndNaN(double[] a, int left, int right) {
+    public static void sort(double[] a, int left, int right) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
         while (left <= right && Double.isNaN(a[right])) {
             right--;
         }
-        for (int k = right - 1; k >= left; k--) {
+        for (int k = right; --k >= left; ) {
             double ak = a[k];
             if (ak != ak) { // a[k] is NaN
                 a[k] = a[right];
@@ -2358,7 +2048,7 @@
         int hi = right;
 
         /*
-         * Search first zero, or first positive, or last negative element.
+         * Find the first zero, or first positive, or last negative element.
          */
         while (left < hi) {
             int middle = (left + hi) >>> 1;
@@ -2383,12 +2073,12 @@
          *
          * Partitioning:
          *
-         * +---------------------------------------------------+
-         * |   < 0.0   |   -0.0   |    0.0    |  ?  ( >= 0.0 ) |
-         * +---------------------------------------------------+
-         *              ^          ^           ^
-         *              |          |           |
-         *             left        p           k
+         * +----------------------------------------------------+
+         * |   < 0.0   |   -0.0   |   0.0   |   ?  ( >= 0.0 )   |
+         * +----------------------------------------------------+
+         *              ^          ^         ^
+         *              |          |         |
+         *             left        p         k
          *
          * Invariants:
          *
@@ -2399,53 +2089,36 @@
          *
          * Pointer k is the first index of ?-part.
          */
-        for (int k = left + 1, p = left; k <= right; k++) {
+        for (int k = left, p = left - 1; ++k <= right; ) {
             double ak = a[k];
             if (ak != 0.0d) {
                 break;
             }
             if (Double.doubleToRawLongBits(ak) < 0) { // ak is -0.0d
                 a[k] = 0.0d;
-                a[p++] = -0.0d;
+                a[++p] = -0.0d;
             }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm. This method differs from the public
-     * {@code sort} method in that the {@code right} index is inclusive,
-     * it does no range checking on {@code left} or {@code right}, and has
-     * boolean flag whether insertion sort with sentinel is used or not.
+     * Sorts the specified range of the array by Dual-Pivot Quicksort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
-     * @param leftmost indicates if the part is the most left in the range
+     * @param leftmost indicates if this part is the leftmost in the range
      */
     private static void sort(double[] a, int left,int right,boolean leftmost) {
         int length = right - left + 1;
 
-        // Use insertion sort on tiny arrays
+        // Use insertion sort on small arrays
         if (length < INSERTION_SORT_THRESHOLD) {
-            if (!leftmost) {
+            if (leftmost) {
                 /*
-                 * Every element in adjoining part plays the role
-                 * of sentinel, therefore this allows us to avoid
-                 * the j >= left check on each iteration.
-                 */
-                for (int j, i = left + 1; i <= right; i++) {
-                    double ai = a[i];
-                    for (j = i - 1; ai < a[j]; j--) {
-                        // assert j >= left;
-                        a[j + 1] = a[j];
-                    }
-                    a[j + 1] = ai;
-                }
-            } else {
-                /*
-                 * For case of leftmost part traditional (without a sentinel)
-                 * insertion sort, optimized for server JVM, is used.
+                 * Traditional (without sentinel) insertion sort,
+                 * optimized for server VM, is used in case of
+                 * the leftmost part.
                  */
                 for (int i = left, j = i; i < right; j = ++i) {
                     double ai = a[i + 1];
@@ -2457,12 +2130,54 @@
                     }
                     a[j + 1] = ai;
                 }
+            } else {
+                /*
+                 * Skip the longest ascending sequence.
+                 */
+                do {
+                    if (left++ >= right) {
+                        return;
+                    }
+                } while (a[left - 1] <= a[left]);
+
+                /*
+                 * Every element from adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid the
+                 * left range check on each iteration. Moreover, we use
+                 * the best improved algorithm, so called pair insertion
+                 * sort, which is faster than traditional implementation
+                 * in the context of Dual-Pivot Quicksort.
+                 */
+                for (int k = left--; (left += 2) <= right; ) {
+                    double a1, a2; k = left - 1;
+
+                    if (a[k] < a[left]) {
+                        a2 = a[k]; a1 = a[left];
+                    } else {
+                        a1 = a[k]; a2 = a[left];
+                    }
+                    while (a1 < a[--k]) {
+                        a[k + 2] = a[k];
+                    }
+                    a[++k + 1] = a1;
+
+                    while (a2 < a[--k]) {
+                        a[k + 1] = a[k];
+                    }
+                    a[k + 1] = a2;
+                }
+                double last = a[right];
+
+                while (last < a[--right]) {
+                    a[right + 1] = a[right];
+                }
+                a[right + 1] = last;
             }
             return;
         }
 
         // Inexpensive approximation of length / 7
-        int seventh = (length >>> 3) + (length >>> 6) + 1;
+        int seventh = (length >> 3) + (length >> 6) + 1;
 
         /*
          * Sort five evenly spaced elements around (and including) the
@@ -2544,10 +2259,14 @@
              * Pointer k is the first index of ?-part.
              */
             outer:
-            for (int k = less; k <= great; k++) {
+            for (int k = less - 1; ++k <= great; ) {
                 double ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
+                    /*
+                     * Here and below we use "a[i] = b; i++;" instead
+                     * of "a[i++] = b;" due to performance issue.
+                     */
                     a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
@@ -2556,13 +2275,17 @@
                             break outer;
                         }
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot2
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
                     }
+                    /*
+                     * Here and below we use "a[i] = b; i--;" instead
+                     * of "a[i--] = b;" due to performance issue.
+                     */
                     a[great] = ak;
                     great--;
                 }
@@ -2577,7 +2300,7 @@
             sort(a, great + 2, right, false);
 
             /*
-             * If center part is too large (comprises > 5/7 of the array),
+             * If center part is too large (comprises > 4/7 of the array),
              * swap internal pivot values to ends.
              */
             if (less < e1 && e5 < great) {
@@ -2611,7 +2334,7 @@
                  * Pointer k is the first index of ?-part.
                  */
                 outer:
-                for (int k = less; k <= great; k++) {
+                for (int k = less - 1; ++k <= great; ) {
                     double ak = a[k];
                     if (ak == pivot1) { // Move a[k] to left part
                         a[k] = a[less];
@@ -2623,7 +2346,7 @@
                                 break outer;
                             }
                         }
-                        if (a[great] == pivot1) {
+                        if (a[great] == pivot1) { // a[great] < pivot2
                             a[k] = a[less];
                             /*
                              * Even though a[great] equals to pivot1, the
@@ -2649,7 +2372,7 @@
 
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way
+             * Partitioning degenerates to the traditional 3-way
              * (or "Dutch National Flag") schema:
              *
              *   left part    center part              right part
@@ -2668,28 +2391,20 @@
              *
              * Pointer k is the first index of ?-part.
              */
-            for (int k = left; k <= great; k++) {
+            for (int k = less; k <= great; ++k) {
                 if (a[k] == pivot1) {
                     continue;
                 }
                 double ak = a[k];
-
                 if (ak < pivot1) { // Move a[k] to left part
                     a[k] = a[less];
                     a[less] = ak;
                     less++;
                 } else { // a[k] > pivot1 - Move a[k] to right part
-                    /*
-                     * We know that pivot1 == a[e3] == pivot2. Thus, we know
-                     * that great will still be >= k when the following loop
-                     * terminates, even though we don't test for it explicitly.
-                     * In other words, a[e3] acts as a sentinel for great.
-                     */
                     while (a[great] > pivot1) {
-                        // assert great > k;
                         great--;
                     }
-                    if (a[great] < pivot1) {
+                    if (a[great] < pivot1) { // a[great] <= pivot1
                         a[k] = a[less];
                         a[less] = a[great];
                         less++;
@@ -2709,26 +2424,13 @@
                 }
             }
 
-            // Sort left and right parts recursively
+            /*
+             * Sort left and right parts recursively.
+             * All elements from center part are equal
+             * and, therefore, already sorted.
+             */
             sort(a, left, less - 1, leftmost);
             sort(a, great + 1, right, false);
         }
     }
-
-    /**
-     * Checks that {@code fromIndex} and {@code toIndex} are in the range,
-     * otherwise throws an appropriate exception.
-     */
-    private static void rangeCheck(int length, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException(
-                "fromIndex: " + fromIndex + " > toIndex: " + toIndex);
-        }
-        if (fromIndex < 0) {
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        }
-        if (toIndex > length) {
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-        }
-    }
 }