6899694: Dual-pivot quicksort improvements

Co-authored-by: Joshua Bloch <joshua.bloch@google.com>
Reviewed-by: jjb
This commit is contained in:
Vladimir Yaroslavskiy 2009-11-11 14:38:01 +00:00 committed by Alan Bateman
parent a5e7fb4543
commit 0d83336729
3 changed files with 1912 additions and 651 deletions

View File

@ -57,51 +57,14 @@ public class Arrays {
// Suppresses default constructor, ensuring non-instantiability. // Suppresses default constructor, ensuring non-instantiability.
private Arrays() {} private Arrays() {}
// Sorting /*
* Sorting of primitive type arrays.
*/
/** /**
* Sorts the specified array into ascending numerical order. * Sorts the specified array into ascending numerical order.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
public static void sort(long[] a) {
sort(a, 0, a.length);
}
/**
* Sorts the specified range of the specified array into ascending order. The
* range of to be sorted extends from the index {@code fromIndex}, inclusive,
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(long[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
* Sorts the specified array into ascending numerical order.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
@ -110,37 +73,76 @@ public class Arrays {
* @param a the array to be sorted * @param a the array to be sorted
*/ */
public static void sort(int[] a) { public static void sort(int[] a) {
sort(a, 0, a.length); DualPivotQuicksort.sort(a);
} }
/** /**
* Sorts the specified range of the specified array into ascending order. The * Sorts the specified range of the array into ascending order. The range
* range of to be sorted extends from the index {@code fromIndex}, inclusive, * to be sorted extends from the index {@code fromIndex}, inclusive, to
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty. * the range to be sorted is empty.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations. * faster than traditional (one-pivot) Quicksort implementations.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted * @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted * @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException * @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length} * if {@code fromIndex < 0} or {@code toIndex > a.length}
*/ */
public static void sort(int[] a, int fromIndex, int toIndex) { public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); DualPivotQuicksort.sort(a, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
} }
/** /**
* Sorts the specified array into ascending numerical order. * Sorts the specified array into ascending numerical order.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
public static void sort(long[] a) {
DualPivotQuicksort.sort(a);
}
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(long[] a, int fromIndex, int toIndex) {
DualPivotQuicksort.sort(a, fromIndex, toIndex);
}
/**
* Sorts the specified array into ascending numerical order.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
@ -149,37 +151,37 @@ public class Arrays {
* @param a the array to be sorted * @param a the array to be sorted
*/ */
public static void sort(short[] a) { public static void sort(short[] a) {
sort(a, 0, a.length); DualPivotQuicksort.sort(a);
} }
/** /**
* Sorts the specified range of the specified array into ascending order. The * Sorts the specified range of the array into ascending order. The range
* range of to be sorted extends from the index {@code fromIndex}, inclusive, * to be sorted extends from the index {@code fromIndex}, inclusive, to
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty. * the range to be sorted is empty.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations. * faster than traditional (one-pivot) Quicksort implementations.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted * @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted * @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException * @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length} * if {@code fromIndex < 0} or {@code toIndex > a.length}
*/ */
public static void sort(short[] a, int fromIndex, int toIndex) { public static void sort(short[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); DualPivotQuicksort.sort(a, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
} }
/** /**
* Sorts the specified array into ascending numerical order. * Sorts the specified array into ascending numerical order.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
@ -188,37 +190,37 @@ public class Arrays {
* @param a the array to be sorted * @param a the array to be sorted
*/ */
public static void sort(char[] a) { public static void sort(char[] a) {
sort(a, 0, a.length); DualPivotQuicksort.sort(a);
} }
/** /**
* Sorts the specified range of the specified array into ascending order. The * Sorts the specified range of the array into ascending order. The range
* range of to be sorted extends from the index {@code fromIndex}, inclusive, * to be sorted extends from the index {@code fromIndex}, inclusive, to
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty. * the range to be sorted is empty.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations. * faster than traditional (one-pivot) Quicksort implementations.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted * @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted * @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException * @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length} * if {@code fromIndex < 0} or {@code toIndex > a.length}
*/ */
public static void sort(char[] a, int fromIndex, int toIndex) { public static void sort(char[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); DualPivotQuicksort.sort(a, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
} }
/** /**
* Sorts the specified array into ascending numerical order. * Sorts the specified array into ascending numerical order.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
@ -227,160 +229,45 @@ public class Arrays {
* @param a the array to be sorted * @param a the array to be sorted
*/ */
public static void sort(byte[] a) { public static void sort(byte[] a) {
sort(a, 0, a.length); DualPivotQuicksort.sort(a);
} }
/** /**
* Sorts the specified range of the specified array into ascending order. The * Sorts the specified range of the array into ascending order. The range
* range of to be sorted extends from the index {@code fromIndex}, inclusive, * to be sorted extends from the index {@code fromIndex}, inclusive, to
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty. * the range to be sorted is empty.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations. * faster than traditional (one-pivot) Quicksort implementations.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted * @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted * @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException * @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length} * if {@code fromIndex < 0} or {@code toIndex > a.length}
*/ */
public static void sort(byte[] a, int fromIndex, int toIndex) { public static void sort(byte[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); DualPivotQuicksort.sort(a, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
} }
/** /**
* Sorts the specified array into ascending numerical order. * Sorts the specified array into ascending numerical order.
* *
* <p>The {@code <} relation does not provide a total order on * <p>The {@code <} relation does not provide a total order on all float
* all floating-point values; although they are distinct numbers * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
* {@code -0.0d == 0.0d} is {@code true} and a NaN value compares * value compares neither less than, greater than, nor equal to any value,
* neither less than, greater than, nor equal to any floating-point * even itself. This method uses the total order imposed by the method
* value, even itself. To allow the sort to proceed, instead of using * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
* the {@code <} relation to determine ascending numerical order, * {@code 0.0f} and {@code Float.NaN} is considered greater than any
* this method uses the total order imposed by {@link Double#compareTo}. * other value and all {@code Float.NaN} values are considered equal.
* This ordering differs from the {@code <} relation in that {@code -0.0d}
* is treated as less than {@code 0.0d} and NaN is considered greater than
* any other floating-point value. For the purposes of sorting, all NaN
* values are considered equivalent and equal.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
public static void sort(double[] a) {
sort(a, 0, a.length);
}
/**
* Sorts the specified range of the specified array into ascending order. The
* range of to be sorted extends from the index {@code fromIndex}, inclusive,
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
*
* <p>The {@code <} relation does not provide a total order on
* all floating-point values; although they are distinct numbers
* {@code -0.0d == 0.0d} is {@code true} and a NaN value compares
* neither less than, greater than, nor equal to any floating-point
* value, even itself. To allow the sort to proceed, instead of using
* the {@code <} relation to determine ascending numerical order,
* this method uses the total order imposed by {@link Double#compareTo}.
* This ordering differs from the {@code <} relation in that {@code -0.0d}
* is treated as less than {@code 0.0d} and NaN is considered greater than
* any other floating-point value. For the purposes of sorting, all NaN
* values are considered equivalent and equal.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(double[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
sortNegZeroAndNaN(a, fromIndex, toIndex);
}
private static void sortNegZeroAndNaN(double[] a, int fromIndex, int toIndex) {
final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);
/*
* The sort is done in three phases to avoid the expense of using
* NaN and -0.0d aware comparisons during the main sort.
*
* Preprocessing phase: move any NaN's to end of array, count the
* number of -0.0d's, and turn them into 0.0d's.
*/
int numNegZeros = 0;
int i = fromIndex;
int n = toIndex;
double temp;
while (i < n) {
if (a[i] != a[i]) {
n--;
temp = a[i];
a[i] = a[n];
a[n] = temp;
}
else {
if (a[i] == 0 && Double.doubleToLongBits(a[i]) == NEG_ZERO_BITS) {
a[i] = 0.0d;
numNegZeros++;
}
i++;
}
}
// Main sort phase: quicksort everything but the NaN's
DualPivotQuicksort.sort(a, fromIndex, n - 1);
// Postprocessing phase: change 0.0d's to -0.0d's as required
if (numNegZeros != 0) {
int j = binarySearch0(a, fromIndex, n, 0.0d); // position of ANY zero
do {
j--;
}
while (j >= fromIndex && a[j] == 0.0d);
// j is now one less than the index of the FIRST zero
for (int k = 0; k < numNegZeros; k++) {
a[++j] = -0.0d;
}
}
}
/**
* Sorts the specified array into ascending numerical order.
*
* <p>The {@code <} relation does not provide a total order on
* all floating-point values; although they are distinct numbers
* {@code -0.0f == 0.0f} is {@code true} and a NaN value compares
* neither less than, greater than, nor equal to any floating-point
* value, even itself. To allow the sort to proceed, instead of using
* the {@code <} relation to determine ascending numerical order,
* this method uses the total order imposed by {@link Float#compareTo}.
* This ordering differs from the {@code <} relation in that {@code -0.0f}
* is treated as less than {@code 0.0f} and NaN is considered greater than
* any other floating-point value. For the purposes of sorting, all NaN
* values are considered equivalent and equal.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
@ -389,92 +276,100 @@ public class Arrays {
* @param a the array to be sorted * @param a the array to be sorted
*/ */
public static void sort(float[] a) { public static void sort(float[] a) {
sort(a, 0, a.length); DualPivotQuicksort.sort(a);
} }
/** /**
* Sorts the specified range of the specified array into ascending order. The * Sorts the specified range of the array into ascending order. The range
* range of to be sorted extends from the index {@code fromIndex}, inclusive, * to be sorted extends from the index {@code fromIndex}, inclusive, to
* to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty. * the range to be sorted is empty.
* *
* <p>The {@code <} relation does not provide a total order on * <p>The {@code <} relation does not provide a total order on all float
* all floating-point values; although they are distinct numbers * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
* {@code -0.0f == 0.0f} is {@code true} and a NaN value compares * value compares neither less than, greater than, nor equal to any value,
* neither less than, greater than, nor equal to any floating-point * even itself. This method uses the total order imposed by the method
* value, even itself. To allow the sort to proceed, instead of using * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
* the {@code <} relation to determine ascending numerical order, * {@code 0.0f} and {@code Float.NaN} is considered greater than any
* this method uses the total order imposed by {@link Float#compareTo}. * other value and all {@code Float.NaN} values are considered equal.
* This ordering differs from the {@code <} relation in that {@code -0.0f}
* is treated as less than {@code 0.0f} and NaN is considered greater than
* any other floating-point value. For the purposes of sorting, all NaN
* values are considered equivalent and equal.
* *
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort, * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other * offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically * quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations. * faster than traditional (one-pivot) Quicksort implementations.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param fromIndex the index of the first element, inclusively, to be sorted * @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusively, to be sorted * @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex} * @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException * @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length} * if {@code fromIndex < 0} or {@code toIndex > a.length}
*/ */
public static void sort(float[] a, int fromIndex, int toIndex) { public static void sort(float[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); DualPivotQuicksort.sort(a, fromIndex, toIndex);
sortNegZeroAndNaN(a, fromIndex, toIndex);
} }
private static void sortNegZeroAndNaN(float[] a, int fromIndex, int toIndex) { /**
final int NEG_ZERO_BITS = Float.floatToIntBits(-0.0f); * Sorts the specified array into ascending numerical order.
/*
* The sort is done in three phases to avoid the expense of using
* NaN and -0.0f aware comparisons during the main sort.
* *
* Preprocessing phase: move any NaN's to end of array, count the * <p>The {@code <} relation does not provide a total order on all double
* number of -0.0f's, and turn them into 0.0f's. * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
* value compares neither less than, greater than, nor equal to any value,
* even itself. This method uses the total order imposed by the method
* {@link Double#compareTo}: {@code -0.0d} is treated as less than value
* {@code 0.0d} and {@code Double.NaN} is considered greater than any
* other value and all {@code Double.NaN} values are considered equal.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/ */
int numNegZeros = 0; public static void sort(double[] a) {
int i = fromIndex; DualPivotQuicksort.sort(a);
int n = toIndex; }
float temp;
while (i < n) { /**
if (a[i] != a[i]) { * Sorts the specified range of the array into ascending order. The range
n--; * to be sorted extends from the index {@code fromIndex}, inclusive, to
temp = a[i]; * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
a[i] = a[n]; * the range to be sorted is empty.
a[n] = temp; *
* <p>The {@code <} relation does not provide a total order on all double
* values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
* value compares neither less than, greater than, nor equal to any value,
* even itself. This method uses the total order imposed by the method
* {@link Double#compareTo}: {@code -0.0d} is treated as less than value
* {@code 0.0d} and {@code Double.NaN} is considered greater than any
* other value and all {@code Double.NaN} values are considered equal.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
*
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(double[] a, int fromIndex, int toIndex) {
DualPivotQuicksort.sort(a, fromIndex, toIndex);
} }
else {
if (a[i] == 0 && Float.floatToIntBits(a[i]) == NEG_ZERO_BITS) {
a[i] = 0.0f;
numNegZeros++;
}
i++;
}
}
// Main sort phase: quicksort everything but the NaN's
DualPivotQuicksort.sort(a, fromIndex, n - 1);
// Postprocessing phase: change 0.0f's to -0.0f's as required /*
if (numNegZeros != 0) { * Sorting of complex type arrays.
int j = binarySearch0(a, fromIndex, n, 0.0f); // position of ANY zero *
*/
do {
j--;
}
while (j >= fromIndex && a[j] == 0.0f);
// j is now one less than the index of the FIRST zero
for (int k = 0; k < numNegZeros; k++) {
a[++j] = -0.0f;
}
}
}
/** /**
* Old merge sort implementation can be selected (for * Old merge sort implementation can be selected (for

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff