DualPivotQuicksort.java revision 1804
1804N/A/*
1804N/A * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
1804N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1804N/A *
1804N/A * This code is free software; you can redistribute it and/or modify it
1804N/A * under the terms of the GNU General Public License version 2 only, as
1804N/A * published by the Free Software Foundation. Sun designates this
1804N/A * particular file as subject to the "Classpath" exception as provided
1804N/A * by Sun in the LICENSE file that accompanied this code.
1804N/A *
1804N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1804N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1804N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1804N/A * version 2 for more details (a copy is included in the LICENSE file that
1804N/A * accompanied this code).
1804N/A *
1804N/A * You should have received a copy of the GNU General Public License version
1804N/A * 2 along with this work; if not, write to the Free Software Foundation,
1804N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1804N/A *
1804N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
1804N/A * CA 95054 USA or visit www.sun.com if you need additional information or
1804N/A * have any questions.
1804N/A */
1804N/A
1804N/Apackage java.util;
1804N/A
1804N/A/**
1804N/A * This class implements the Dual-Pivot Quicksort algorithm by
1804N/A * Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. The algorithm
1804N/A * offers O(n log(n)) performance on many data sets that cause other
1804N/A * quicksorts to degrade to quadratic performance, and is typically
1804N/A * faster than traditional (one-pivot) Quicksort implementations.
1804N/A *
1804N/A * @author Vladimir Yaroslavskiy
1804N/A * @author Jon Bentley
1804N/A * @author Josh Bloch
1804N/A *
1804N/A * @version 2009.10.22 m765.827.v4
1804N/A */
1804N/Afinal class DualPivotQuicksort {
1804N/A
1804N/A // Suppresses default constructor, ensuring non-instantiability.
1804N/A private DualPivotQuicksort() {}
1804N/A
1804N/A /*
1804N/A * Tuning Parameters.
1804N/A */
1804N/A
1804N/A /**
1804N/A * If the length of an array to be sorted is less than this
1804N/A * constant, insertion sort is used in preference to Quicksort.
1804N/A */
1804N/A private static final int INSERTION_SORT_THRESHOLD = 32;
1804N/A
1804N/A /**
1804N/A * If the length of a byte array to be sorted is greater than
1804N/A * this constant, counting sort is used in preference to Quicksort.
1804N/A */
1804N/A private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 128;
1804N/A
1804N/A /**
1804N/A * If the length of a short or char array to be sorted is greater
1804N/A * than this constant, counting sort is used in preference to Quicksort.
1804N/A */
1804N/A private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
1804N/A
1804N/A /*
1804N/A * Sorting methods for the seven primitive types.
1804N/A */
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(int[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A int ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(int[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { int t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { int t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { int t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { int t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { int t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { int t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { int t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { int t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { int t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A int pivot1 = a[e2]; a[e2] = a[left];
1804N/A int pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A int ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A int ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(long[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A long ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(long[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { long t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { long t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { long t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { long t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { long t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { long t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { long t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { long t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { long t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A long pivot1 = a[e2]; a[e2] = a[left];
1804N/A long pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A long ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A long ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /** The number of distinct short values */
1804N/A private static final int NUM_SHORT_VALUES = 1 << 16;
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(short[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A short ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
1804N/A // Use counting sort on huge arrays
1804N/A int[] count = new int[NUM_SHORT_VALUES];
1804N/A
1804N/A for (int i = left; i <= right; i++) {
1804N/A count[a[i] - Short.MIN_VALUE]++;
1804N/A }
1804N/A for (int i = 0, k = left; i < count.length && k < right; i++) {
1804N/A short value = (short) (i + Short.MIN_VALUE);
1804N/A
1804N/A for (int s = count[i]; s > 0; s--) {
1804N/A a[k++] = value;
1804N/A }
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(short[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { short t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { short t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { short t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { short t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { short t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { short t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { short t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { short t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { short t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A short pivot1 = a[e2]; a[e2] = a[left];
1804N/A short pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A short ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A short ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A
1804N/A /** The number of distinct byte values */
1804N/A private static final int NUM_BYTE_VALUES = 1 << 8;
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(byte[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A byte ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
1804N/A // Use counting sort on large arrays
1804N/A int[] count = new int[NUM_BYTE_VALUES];
1804N/A
1804N/A for (int i = left; i <= right; i++) {
1804N/A count[a[i] - Byte.MIN_VALUE]++;
1804N/A }
1804N/A for (int i = 0, k = left; i < count.length && k < right; i++) {
1804N/A byte value = (byte) (i + Byte.MIN_VALUE);
1804N/A
1804N/A for (int s = count[i]; s > 0; s--) {
1804N/A a[k++] = value;
1804N/A }
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(byte[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { byte t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { byte t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { byte t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { byte t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { byte t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A byte pivot1 = a[e2]; a[e2] = a[left];
1804N/A byte pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A byte ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A byte ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A
1804N/A /** The number of distinct char values */
1804N/A private static final int NUM_CHAR_VALUES = 1 << 16;
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(char[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A char ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
1804N/A // Use counting sort on huge arrays
1804N/A int[] count = new int[NUM_CHAR_VALUES];
1804N/A
1804N/A for (int i = left; i <= right; i++) {
1804N/A count[a[i]]++;
1804N/A }
1804N/A for (int i = 0, k = left; i < count.length && k < right; i++) {
1804N/A for (int s = count[i]; s > 0; s--) {
1804N/A a[k++] = (char) i;
1804N/A }
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(char[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { char t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { char t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { char t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { char t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { char t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { char t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { char t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { char t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { char t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A char pivot1 = a[e2]; a[e2] = a[left];
1804N/A char pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A char ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A char ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(float[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A float ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(float[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { float t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { float t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { float t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { float t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { float t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { float t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { float t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { float t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { float t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A float pivot1 = a[e2]; a[e2] = a[left];
1804N/A float pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A float ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A float ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A static void sort(double[] a, int left, int right) {
1804N/A // Use insertion sort on tiny arrays
1804N/A if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
1804N/A for (int k = left + 1; k <= right; k++) {
1804N/A double ak = a[k];
1804N/A int j;
1804N/A
1804N/A for (j = k - 1; j >= left && ak < a[j]; j--) {
1804N/A a[j + 1] = a[j];
1804N/A }
1804N/A a[j + 1] = ak;
1804N/A }
1804N/A } else { // Use Dual-Pivot Quicksort on large arrays
1804N/A dualPivotQuicksort(a, left, right);
1804N/A }
1804N/A }
1804N/A
1804N/A /**
1804N/A * Sorts the specified range of the array into ascending order
1804N/A * by Dual-Pivot Quicksort.
1804N/A *
1804N/A * @param a the array to be sorted
1804N/A * @param left the index of the first element, inclusively, to be sorted
1804N/A * @param right the index of the last element, inclusively, to be sorted
1804N/A */
1804N/A private static void dualPivotQuicksort(double[] a, int left, int right) {
1804N/A // Compute indices of five evenly spaced elements
1804N/A int sixth = (right - left + 1) / 6;
1804N/A int e1 = left + sixth;
1804N/A int e5 = right - sixth;
1804N/A int e3 = (left + right) >>> 1; // The midpoint
1804N/A int e4 = e3 + sixth;
1804N/A int e2 = e3 - sixth;
1804N/A
1804N/A // Sort these elements in place using a 5-element sorting network
1804N/A if (a[e1] > a[e2]) { double t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
1804N/A if (a[e4] > a[e5]) { double t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A if (a[e1] > a[e3]) { double t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
1804N/A if (a[e2] > a[e3]) { double t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e1] > a[e4]) { double t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
1804N/A if (a[e3] > a[e4]) { double t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
1804N/A if (a[e2] > a[e5]) { double t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
1804N/A if (a[e2] > a[e3]) { double t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
1804N/A if (a[e4] > a[e5]) { double t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
1804N/A
1804N/A /*
1804N/A * Use the second and fourth of the five sorted elements as pivots.
1804N/A * These values are inexpensive approximations of the first and
1804N/A * second terciles of the array. Note that pivot1 <= pivot2.
1804N/A *
1804N/A * The pivots are stored in local variables, and the first and
1804N/A * the last of the sorted elements are moved to the locations
1804N/A * formerly occupied by the pivots. When partitioning is complete,
1804N/A * the pivots are swapped back into their final positions, and
1804N/A * excluded from subsequent sorting.
1804N/A */
1804N/A double pivot1 = a[e2]; a[e2] = a[left];
1804N/A double pivot2 = a[e4]; a[e4] = a[right];
1804N/A
1804N/A /*
1804N/A * Partitioning
1804N/A *
1804N/A * left part center part right part
1804N/A * ------------------------------------------------------------
1804N/A * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
1804N/A * ------------------------------------------------------------
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A */
1804N/A
1804N/A // Pointers
1804N/A int less = left + 1; // The index of first element of center part
1804N/A int great = right - 1; // The index before first element of right part
1804N/A
1804N/A boolean pivotsDiffer = pivot1 != pivot2;
1804N/A
1804N/A if (pivotsDiffer) {
1804N/A /*
1804N/A * Invariants:
1804N/A * all in (left, less) < pivot1
1804N/A * pivot1 <= all in [less, k) <= pivot2
1804N/A * all in (great, right) > pivot2
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A double ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else if (ak > pivot2) {
1804N/A while (a[great] > pivot2 && k < great) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A } else { // Pivots are equal
1804N/A /*
1804N/A * Partition degenerates to the traditional 3-way
1804N/A * (or "Dutch National Flag") partition:
1804N/A *
1804N/A * left part center part right part
1804N/A * -------------------------------------------------
1804N/A * [ < pivot | == pivot | ? | > pivot ]
1804N/A * -------------------------------------------------
1804N/A *
1804N/A * ^ ^ ^
1804N/A * | | |
1804N/A * less k great
1804N/A *
1804N/A * Invariants:
1804N/A *
1804N/A * all in (left, less) < pivot
1804N/A * all in [less, k) == pivot
1804N/A * all in (great, right) > pivot
1804N/A *
1804N/A * Pointer k is the first index of ?-part
1804N/A */
1804N/A for (int k = less; k <= great; k++) {
1804N/A double ak = a[k];
1804N/A
1804N/A if (ak == pivot1) {
1804N/A continue;
1804N/A }
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A } else {
1804N/A while (a[great] > pivot1) {
1804N/A great--;
1804N/A }
1804N/A a[k] = a[great];
1804N/A a[great--] = ak;
1804N/A ak = a[k];
1804N/A
1804N/A if (ak < pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = ak;
1804N/A }
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Swap pivots into their final positions
1804N/A a[left] = a[less - 1]; a[less - 1] = pivot1;
1804N/A a[right] = a[great + 1]; a[great + 1] = pivot2;
1804N/A
1804N/A // Sort left and right parts recursively, excluding known pivot values
1804N/A sort(a, left, less - 2);
1804N/A sort(a, great + 2, right);
1804N/A
1804N/A /*
1804N/A * If pivot1 == pivot2, all elements from center
1804N/A * part are equal and, therefore, already sorted
1804N/A */
1804N/A if (!pivotsDiffer) {
1804N/A return;
1804N/A }
1804N/A
1804N/A /*
1804N/A * If center part is too large (comprises > 5/6 of
1804N/A * the array), swap internal pivot values to ends
1804N/A */
1804N/A if (less < e1 && e5 < great) {
1804N/A while (a[less] == pivot1) {
1804N/A less++;
1804N/A }
1804N/A for (int k = less + 1; k <= great; k++) {
1804N/A if (a[k] == pivot1) {
1804N/A a[k] = a[less];
1804N/A a[less++] = pivot1;
1804N/A }
1804N/A }
1804N/A while (a[great] == pivot2) {
1804N/A great--;
1804N/A }
1804N/A for (int k = great - 1; k >= less; k--) {
1804N/A if (a[k] == pivot2) {
1804N/A a[k] = a[great];
1804N/A a[great--] = pivot2;
1804N/A }
1804N/A }
1804N/A }
1804N/A
1804N/A // Sort center part recursively, excluding known pivot values
1804N/A sort(a, less, great);
1804N/A }
1804N/A}