--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java Mon Feb 07 18:02:30 2011 +0000
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java Tue Feb 08 15:50:30 2011 +0000
@@ -36,7 +36,7 @@
* @author Jon Bentley
* @author Josh Bloch
*
- * @version 2010.10.13 m765.827.12i:5\7p
+ * @version 2011.01.21 m765.827.12i:5\7pm
* @since 1.7
*/
final class DualPivotQuicksort {
@@ -51,6 +51,22 @@
*/
/**
+ * The maximum number of runs in merge sort.
+ */
+ private static final int MAX_RUN_COUNT = 67;
+
+ /**
+ * The maximum length of run in merge sort.
+ */
+ private static final int MAX_RUN_LENGTH = 33;
+
+ /**
+ * If the length of an array to be sorted is less than this
+ * constant, Quicksort is used in preference to merge sort.
+ */
+ private static final int QUICKSORT_THRESHOLD = 286;
+
+ /**
* If the length of an array to be sorted is less than this
* constant, insertion sort is used in preference to Quicksort.
*/
@@ -78,7 +94,7 @@
* @param a the array to be sorted
*/
public static void sort(int[] a) {
- sort(a, 0, a.length - 1, true);
+ sort(a, 0, a.length - 1);
}
/**
@@ -89,7 +105,89 @@
* @param right the index of the last element, inclusive, to be sorted
*/
public static void sort(int[] a, int left, int right) {
- sort(a, left, right, true);
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ int[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new int[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new int[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ int[] t = a; a = b; b = t;
+ }
}
/**
@@ -103,7 +201,7 @@
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -126,26 +224,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- int a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ int a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -202,19 +298,19 @@
}
}
- /*
- * 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.
- */
- int pivot1 = a[e2];
- int 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ int pivot1 = a[e2];
+ int pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -259,7 +355,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -269,7 +365,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -278,7 +374,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -299,10 +395,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -330,7 +427,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -348,12 +445,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = pivot1;
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -361,7 +458,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ int pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -383,35 +486,35 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
int ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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[k] = pivot;
}
a[great] = ak;
- great--;
+ --great;
}
}
@@ -431,7 +534,7 @@
* @param a the array to be sorted
*/
public static void sort(long[] a) {
- sort(a, 0, a.length - 1, true);
+ sort(a, 0, a.length - 1);
}
/**
@@ -442,7 +545,89 @@
* @param right the index of the last element, inclusive, to be sorted
*/
public static void sort(long[] a, int left, int right) {
- sort(a, left, right, true);
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ long t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ long[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new long[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new long[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ long[] t = a; a = b; b = t;
+ }
}
/**
@@ -456,7 +641,7 @@
private static void sort(long[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -479,26 +664,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- long a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ long a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -555,19 +738,19 @@
}
}
- /*
- * 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.
- */
- long pivot1 = a[e2];
- long 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ long pivot1 = a[e2];
+ long pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -612,7 +795,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -622,7 +805,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -631,7 +814,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -652,10 +835,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -683,7 +867,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -701,12 +885,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = pivot1;
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -714,7 +898,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ long pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -736,35 +926,35 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
long ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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[k] = pivot;
}
a[great] = ak;
- great--;
+ --great;
}
}
@@ -799,9 +989,9 @@
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
int[] count = new int[NUM_SHORT_VALUES];
- for (int i = left - 1; ++i <= right; ) {
- count[a[i] - Short.MIN_VALUE]++;
- }
+ 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);
@@ -812,7 +1002,7 @@
} while (--s > 0);
}
} else { // Use Dual-Pivot Quicksort on small arrays
- sort(a, left, right, true);
+ doSort(a, left, right);
}
}
@@ -820,6 +1010,99 @@
private static final int NUM_SHORT_VALUES = 1 << 16;
/**
+ * 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 doSort(short[] a, int left, int right) {
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ short t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ short[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new short[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new short[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ short[] t = a; a = b; b = t;
+ }
+ }
+
+ /**
* Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @param a the array to be sorted
@@ -827,10 +1110,10 @@
* @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(short[] a, int left, int right,boolean leftmost) {
+ private static void sort(short[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -853,26 +1136,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- short a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ short a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -929,19 +1210,19 @@
}
}
- /*
- * 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.
- */
- short pivot1 = a[e2];
- short 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ short pivot1 = a[e2];
+ short pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -986,7 +1267,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -996,7 +1277,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -1005,7 +1286,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -1026,10 +1307,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -1057,7 +1339,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -1075,12 +1357,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = pivot1;
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -1088,7 +1370,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ short pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -1110,35 +1398,35 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
short ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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[k] = pivot;
}
a[great] = ak;
- great--;
+ --great;
}
}
@@ -1173,9 +1461,9 @@
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
int[] count = new int[NUM_CHAR_VALUES];
- for (int i = left - 1; ++i <= right; ) {
- count[a[i]]++;
- }
+ 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;
@@ -1186,7 +1474,7 @@
} while (--s > 0);
}
} else { // Use Dual-Pivot Quicksort on small arrays
- sort(a, left, right, true);
+ doSort(a, left, right);
}
}
@@ -1194,6 +1482,99 @@
private static final int NUM_CHAR_VALUES = 1 << 16;
/**
+ * 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 doSort(char[] a, int left, int right) {
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ char t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ char[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new char[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new char[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ char[] t = a; a = b; b = t;
+ }
+ }
+
+ /**
* Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @param a the array to be sorted
@@ -1204,7 +1585,7 @@
private static void sort(char[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -1227,26 +1608,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- char a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ char a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -1303,19 +1682,19 @@
}
}
- /*
- * 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.
- */
- char pivot1 = a[e2];
- char 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ char pivot1 = a[e2];
+ char pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -1360,7 +1739,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -1370,7 +1749,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -1379,7 +1758,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -1400,10 +1779,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -1431,7 +1811,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -1449,12 +1829,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = pivot1;
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -1462,7 +1842,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ char pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -1484,35 +1870,35 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
char ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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[k] = pivot;
}
a[great] = ak;
- great--;
+ --great;
}
}
@@ -1550,9 +1936,9 @@
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 = 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);
@@ -1597,21 +1983,21 @@
* Phase 1: Move NaNs to the end of the array.
*/
while (left <= right && Float.isNaN(a[right])) {
- right--;
+ --right;
}
for (int k = right; --k >= left; ) {
float ak = a[k];
if (ak != ak) { // a[k] is NaN
a[k] = a[right];
a[right] = ak;
- right--;
+ --right;
}
}
/*
* Phase 2: Sort everything except NaNs (which are already in place).
*/
- sort(a, left, right, true);
+ doSort(a, left, right);
/*
* Phase 3: Place negative zeros before positive zeros.
@@ -1636,7 +2022,7 @@
* Skip the last negative value (if any) or all leading negative zeros.
*/
while (left <= right && Float.floatToRawIntBits(a[left]) < 0) {
- left++;
+ ++left;
}
/*
@@ -1673,6 +2059,99 @@
}
/**
+ * 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 doSort(float[] a, int left, int right) {
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ float t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ float[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new float[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new float[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ float[] t = a; a = b; b = t;
+ }
+ }
+
+ /**
* Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @param a the array to be sorted
@@ -1680,10 +2159,10 @@
* @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(float[] a, int left, int right,boolean leftmost) {
+ private static void sort(float[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -1706,26 +2185,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- float a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ float a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -1782,19 +2259,19 @@
}
}
- /*
- * 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.
- */
- float pivot1 = a[e2];
- float 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ float pivot1 = a[e2];
+ float pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -1839,7 +2316,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -1849,7 +2326,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -1858,7 +2335,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -1879,10 +2356,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -1910,7 +2388,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -1928,12 +2406,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -1941,7 +2419,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ float pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -1963,27 +2447,27 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
float ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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].
@@ -1991,7 +2475,7 @@
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
@@ -2026,21 +2510,21 @@
* Phase 1: Move NaNs to the end of the array.
*/
while (left <= right && Double.isNaN(a[right])) {
- right--;
+ --right;
}
for (int k = right; --k >= left; ) {
double ak = a[k];
if (ak != ak) { // a[k] is NaN
a[k] = a[right];
a[right] = ak;
- right--;
+ --right;
}
}
/*
* Phase 2: Sort everything except NaNs (which are already in place).
*/
- sort(a, left, right, true);
+ doSort(a, left, right);
/*
* Phase 3: Place negative zeros before positive zeros.
@@ -2065,7 +2549,7 @@
* Skip the last negative value (if any) or all leading negative zeros.
*/
while (left <= right && Double.doubleToRawLongBits(a[left]) < 0) {
- left++;
+ ++left;
}
/*
@@ -2102,6 +2586,99 @@
}
/**
+ * 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 doSort(double[] a, int left, int right) {
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT];
+ int count = 0; run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]);
+ } else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]);
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ double t = a[lo]; a[lo] = a[hi]; a[hi] = t;
+ }
+ } else { // equal
+ for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
+ if (--m == 0) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+ }
+
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ if (run[count] == right++) { // The last run contains one element
+ run[++count] = right;
+ } else if (count == 1) { // The array is already sorted
+ return;
+ }
+
+ /*
+ * Create temporary array, which is used for merging.
+ * Implementation note: variable "right" is increased by 1.
+ */
+ double[] b; byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1);
+
+ if (odd == 0) {
+ b = a; a = new double[b.length];
+ for (int i = left - 1; ++i < right; a[i] = b[i]);
+ } else {
+ b = new double[a.length];
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p] <= a[q]) {
+ b[i] = a[p++];
+ } else {
+ b[i] = a[q++];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i] = a[i]
+ );
+ run[++last] = right;
+ }
+ double[] t = a; a = b; b = t;
+ }
+ }
+
+ /**
* Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @param a the array to be sorted
@@ -2109,10 +2686,10 @@
* @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(double[] a, int left,int right,boolean leftmost) {
+ private static void sort(double[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on small arrays
+ // Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
@@ -2135,26 +2712,24 @@
* Skip the longest ascending sequence.
*/
do {
- if (left++ >= right) {
+ if (left >= right) {
return;
}
- } while (a[left - 1] <= a[left]);
+ } while (a[++left] >= a[left - 1]);
/*
* 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.
+ * the more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
*/
- for (int k = left--; (left += 2) <= right; ) {
- double a1, a2; k = left - 1;
+ for (int k = left; ++left <= right; k = ++left) {
+ double a1 = a[k], a2 = a[left];
- if (a[k] < a[left]) {
- a2 = a[k]; a1 = a[left];
- } else {
- a1 = a[k]; a2 = a[left];
+ if (a1 < a2) {
+ a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
@@ -2211,19 +2786,19 @@
}
}
- /*
- * 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.
- */
- double pivot1 = a[e2];
- double 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) {
+ if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ double pivot1 = a[e2];
+ double pivot2 = a[e4];
+
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
@@ -2268,7 +2843,7 @@
* of "a[i++] = b;" due to performance issue.
*/
a[less] = ak;
- less++;
+ ++less;
} else if (ak > pivot2) { // Move a[k] to right part
while (a[great] > pivot2) {
if (great-- == k) {
@@ -2278,7 +2853,7 @@
if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
@@ -2287,7 +2862,7 @@
* of "a[i--] = b;" due to performance issue.
*/
a[great] = ak;
- great--;
+ --great;
}
}
@@ -2308,10 +2883,11 @@
* Skip elements, which are equal to pivot values.
*/
while (a[less] == pivot1) {
- less++;
+ ++less;
}
+
while (a[great] == pivot2) {
- great--;
+ --great;
}
/*
@@ -2339,7 +2915,7 @@
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
+ ++less;
} else if (ak == pivot2) { // Move a[k] to right part
while (a[great] == pivot2) {
if (great-- == k) {
@@ -2357,12 +2933,12 @@
* accurate assignment a[less] = a[great].
*/
a[less] = a[great];
- less++;
+ ++less;
} else { // pivot1 < a[great] < pivot2
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}
}
@@ -2370,7 +2946,13 @@
// Sort center part recursively
sort(a, less, great, false);
- } else { // Pivots are equal
+ } else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ double pivot = a[e3];
+
/*
* Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
@@ -2392,27 +2974,27 @@
* Pointer k is the first index of ?-part.
*/
for (int k = less; k <= great; ++k) {
- if (a[k] == pivot1) {
+ if (a[k] == pivot) {
continue;
}
double ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
+ if (ak < pivot) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- while (a[great] > pivot1) {
- great--;
+ ++less;
+ } else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
}
- if (a[great] < pivot1) { // a[great] <= pivot1
+ if (a[great] < pivot) { // a[great] <= pivot
a[k] = a[less];
a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
+ ++less;
+ } else { // a[great] == pivot
/*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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].
@@ -2420,7 +3002,7 @@
a[k] = a[great];
}
a[great] = ak;
- great--;
+ --great;
}
}