forked from Speiger/Primitive-Collections
Added Parallel Sorting Methods.
This commit is contained in:
parent
66430d5a8a
commit
0c53fbab6b
|
@ -1,39 +1,50 @@
|
|||
package speiger.src.collections.utils;
|
||||
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
|
||||
public class SanityChecks
|
||||
{
|
||||
public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
private static ForkJoinPool WORK_POOL = ForkJoinPool.commonPool();
|
||||
|
||||
public static byte castToByte(int value)
|
||||
{
|
||||
public static byte castToByte(int value) {
|
||||
if(value > Byte.MAX_VALUE || value < Byte.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Byte[-128,127] range");
|
||||
return (byte)value;
|
||||
}
|
||||
|
||||
public static short castToShort(int value)
|
||||
{
|
||||
public static short castToShort(int value) {
|
||||
if(value > Short.MAX_VALUE || value < Short.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Short[-32768,32767] range");
|
||||
return (short)value;
|
||||
}
|
||||
|
||||
public static char castToChar(int value)
|
||||
{
|
||||
public static char castToChar(int value) {
|
||||
if(value > Character.MAX_VALUE || value < Character.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Character[0,65535] range");
|
||||
return (char)value;
|
||||
}
|
||||
|
||||
public static float castToFloat(double value)
|
||||
{
|
||||
public static float castToFloat(double value) {
|
||||
if(Double.isNaN(value)) return Float.NaN;
|
||||
if(Double.isInfinite(value)) return value > 0 ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
|
||||
if(value < -Float.MAX_VALUE || value > Float.MAX_VALUE) throw new IllegalStateException("Value ["+value+"] out of Float range");
|
||||
return (float)value;
|
||||
}
|
||||
|
||||
public static void checkArrayCapacity(int arraySize, int offset, int accessSize)
|
||||
{
|
||||
public static void checkArrayCapacity(int arraySize, int offset, int accessSize) {
|
||||
if(offset < 0) throw new IllegalStateException("Offset is negative ("+offset+")");
|
||||
else if(accessSize < 0) throw new IllegalStateException("Size is negative ("+accessSize+")");
|
||||
else if(arraySize < offset + accessSize) throw new IndexOutOfBoundsException("Index (" + offset + accessSize + ") is not in size (" + arraySize + ")");
|
||||
}
|
||||
|
||||
public static boolean canParallelTask() {
|
||||
return WORK_POOL.getParallelism() > 1;
|
||||
}
|
||||
|
||||
public static <T> void invokeTask(ForkJoinTask<T> task) {
|
||||
WORK_POOL.invoke(task);
|
||||
}
|
||||
|
||||
public static void setWorkPool(ForkJoinPool pool) {
|
||||
WORK_POOL = pool == null ? ForkJoinPool.commonPool() : pool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,20 @@ package speiger.src.collections.PACKAGE.utils;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.RecursiveAction;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
#else
|
||||
import java.util.Comparator;
|
||||
|
||||
#endif
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class ARRAYS
|
||||
{
|
||||
public static final int BASE_THRESHOLD = 16;
|
||||
public static final int PARALLEL_THRESHOLD = 8192;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public static final KEY_TYPE[] EMPTY_ARRAY = new KEY_TYPE[0];
|
||||
|
||||
|
@ -151,7 +155,7 @@ public class ARRAYS
|
|||
}
|
||||
|
||||
public static GENERIC_BRACES void mergeSort(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
if(to - from < 16) {
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
|
@ -179,7 +183,7 @@ public class ARRAYS
|
|||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void mergeSort(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to) {
|
||||
if(to - from < 16) {
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
|
@ -198,6 +202,38 @@ public class ARRAYS
|
|||
}
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMergeSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelMergeSort(array, null, 0, array.length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMergeSort(KEY_TYPE[] array, int length, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelMergeSort(array, null, 0, length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMergeSort(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new MergeSortActionCompBRACES(array, supp, from, to, comp));
|
||||
return;
|
||||
}
|
||||
mergeSort(array, supp, from, to, comp);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMergeSort(KEY_TYPE[] array) {
|
||||
parallelMergeSort(array, null, 0, array.length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMergeSort(KEY_TYPE[] array, int length) {
|
||||
parallelMergeSort(array, null, 0, length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMergeSort(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new MergeSortActionBRACES(array, supp, from, to));
|
||||
return;
|
||||
}
|
||||
mergeSort(array, supp, from, to);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void memFreeMergeSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
memFreeMergeSort(array, 0, array.length, comp);
|
||||
}
|
||||
|
@ -207,7 +243,7 @@ public class ARRAYS
|
|||
}
|
||||
|
||||
public static GENERIC_BRACES void memFreeMergeSort(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
if(to - from < 16) {
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
|
@ -242,7 +278,7 @@ public class ARRAYS
|
|||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void memFreeMergeSort(KEY_TYPE[] array, int from, int to) {
|
||||
if(to - from < 16) {
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
|
@ -268,6 +304,38 @@ public class ARRAYS
|
|||
}
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelMemFreeMergeSort(array, 0, array.length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array, int length, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelMemFreeMergeSort(array, 0, length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new MemFreeMergeSortActionCompBRACES(array, from, to, comp));
|
||||
return;
|
||||
}
|
||||
memFreeMergeSort(array, from, to, comp);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array) {
|
||||
parallelMemFreeMergeSort(array, 0, array.length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array, int length) {
|
||||
parallelMemFreeMergeSort(array, 0, length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelMemFreeMergeSort(KEY_TYPE[] array, int from, int to) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new MemFreeMergeSortActionBRACES(array, from, to));
|
||||
return;
|
||||
}
|
||||
memFreeMergeSort(array, from, to);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void quickSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
quickSort(array, 0, array.length, comp);
|
||||
}
|
||||
|
@ -279,7 +347,7 @@ public class ARRAYS
|
|||
public static GENERIC_BRACES void quickSort(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
int length = to - from;
|
||||
if(length <= 0) return;
|
||||
if(length < 16) {
|
||||
if(length < BASE_THRESHOLD) {
|
||||
selectionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
|
@ -311,7 +379,7 @@ public class ARRAYS
|
|||
public static COMPAREABLE_BRACES void quickSort(KEY_TYPE[] array, int from, int to) {
|
||||
int length = to - from;
|
||||
if(length <= 0) return;
|
||||
if(length < 16) {
|
||||
if(length < BASE_THRESHOLD) {
|
||||
selectionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
|
@ -332,6 +400,38 @@ public class ARRAYS
|
|||
if((length = d - c) > 1) quickSort(array, to - length, to);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelQuickSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelQuickSort(array, 0, array.length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelQuickSort(KEY_TYPE[] array, int length, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
parallelQuickSort(array, 0, length, comp);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void parallelQuickSort(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new QuickSortActionCompBRACES(array, from, to, comp));
|
||||
return;
|
||||
}
|
||||
quickSort(array, from, to, comp);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelQuickSort(KEY_TYPE[] array) {
|
||||
parallelQuickSort(array, 0, array.length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelQuickSort(KEY_TYPE[] array, int length) {
|
||||
parallelQuickSort(array, 0, length);
|
||||
}
|
||||
|
||||
public static COMPAREABLE_BRACES void parallelQuickSort(KEY_TYPE[] array, int from, int to) {
|
||||
if(SanityChecks.canParallelTask() && to - from >= PARALLEL_THRESHOLD) {
|
||||
SanityChecks.invokeTask(new QuickSortActionBRACES(array, from, to));
|
||||
return;
|
||||
}
|
||||
quickSort(array, from, to);
|
||||
}
|
||||
|
||||
public static GENERIC_BRACES void swap(KEY_TYPE[] a, int from, int to) {
|
||||
KEY_TYPE t = a[from];
|
||||
a[from] = a[to];
|
||||
|
@ -377,7 +477,7 @@ public class ARRAYS
|
|||
{
|
||||
int length = to - from;
|
||||
if(length <= 0) return;
|
||||
if(length < 16) {
|
||||
if(length < BASE_THRESHOLD) {
|
||||
selectionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
|
@ -420,7 +520,7 @@ public class ARRAYS
|
|||
{
|
||||
int length = to - from;
|
||||
if(length <= 0) return;
|
||||
if(length < 16) {
|
||||
if(length < BASE_THRESHOLD) {
|
||||
selectionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
|
@ -442,4 +542,167 @@ public class ARRAYS
|
|||
else if(d - c > 1) new QuickSortActionCompBRACES(array, to - (d - c), to, comp).invoke();
|
||||
}
|
||||
}
|
||||
|
||||
static class MergeSortAction KEY_COMPAREABLE_TYPE extends RecursiveAction {
|
||||
private static final long serialVersionUID = 0L;
|
||||
KEY_TYPE[] array;
|
||||
KEY_TYPE[] supp;
|
||||
int from;
|
||||
int to;
|
||||
|
||||
MergeSortAction(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to)
|
||||
{
|
||||
this.array = array;
|
||||
this.supp = supp;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute()
|
||||
{
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
if(supp == null) supp = Arrays.copyOf(array, to);
|
||||
int mid = (from + to) >>> 1;
|
||||
invokeAll(new MergeSortActionBRACES(supp, array, from, mid), new MergeSortActionBRACES(supp, array, mid, to));
|
||||
if(COMPARE_TO(supp[mid - 1], supp[mid]) <= 0)
|
||||
{
|
||||
System.arraycopy(supp, from, array, from, to - from);
|
||||
return;
|
||||
}
|
||||
for(int p = from, q = mid;from < to;from++) {
|
||||
if(q >= to || p < mid && COMPARE_TO(supp[p], supp[q]) < 0) array[from] = supp[p++];
|
||||
else array[from] = supp[q++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MergeSortActionComp KEY_GENERIC_TYPE extends RecursiveAction {
|
||||
private static final long serialVersionUID = 0L;
|
||||
KEY_TYPE[] array;
|
||||
KEY_TYPE[] supp;
|
||||
int from;
|
||||
int to;
|
||||
COMPARATOR KEY_GENERIC_TYPE comp;
|
||||
|
||||
MergeSortActionComp(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp)
|
||||
{
|
||||
this.array = array;
|
||||
this.supp = supp;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.comp = comp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute()
|
||||
{
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
if(supp == null) supp = Arrays.copyOf(array, to);
|
||||
int mid = (from + to) >>> 1;
|
||||
invokeAll(new MergeSortActionCompBRACES(supp, array, from, mid, comp), new MergeSortActionCompBRACES(supp, array, mid, to, comp));
|
||||
if(comp.compare(supp[mid - 1], supp[mid]) <= 0)
|
||||
{
|
||||
System.arraycopy(supp, from, array, from, to - from);
|
||||
return;
|
||||
}
|
||||
for(int p = from, q = mid;from < to;from++) {
|
||||
if(q >= to || p < mid && comp.compare(supp[p], supp[q]) < 0) array[from] = supp[p++];
|
||||
else array[from] = supp[q++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MemFreeMergeSortAction KEY_COMPAREABLE_TYPE extends RecursiveAction {
|
||||
private static final long serialVersionUID = 0L;
|
||||
KEY_TYPE[] array;
|
||||
int from;
|
||||
int to;
|
||||
|
||||
MemFreeMergeSortAction(KEY_TYPE[] array, int from, int to)
|
||||
{
|
||||
this.array = array;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute()
|
||||
{
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to);
|
||||
return;
|
||||
}
|
||||
int mid = (from + to) >>> 1;
|
||||
invokeAll(new MemFreeMergeSortActionBRACES(array, from, mid), new MemFreeMergeSortActionBRACES(array, mid, to));
|
||||
if(COMPARE_TO(array[mid - 1], array[mid]) <= 0)
|
||||
return;
|
||||
for(int i = from, j = mid, comp;i < j && j < to;) {
|
||||
if((comp = COMPARE_TO(array[i], array[j])) < 0)
|
||||
i++;
|
||||
else if(comp == 0) swap(array, ++i, j);
|
||||
else {
|
||||
swap(array, i++, j);
|
||||
int k = j;
|
||||
for(;k < to - 1 && COMPARE_TO(array[j], array[k + 1]) > 0;k++);
|
||||
if(j == k)
|
||||
continue;
|
||||
KEY_TYPE value = array[j];
|
||||
System.arraycopy(array, j + 1, array, j, k - j);
|
||||
array[k] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MemFreeMergeSortActionComp KEY_GENERIC_TYPE extends RecursiveAction {
|
||||
private static final long serialVersionUID = 0L;
|
||||
KEY_TYPE[] array;
|
||||
int from;
|
||||
int to;
|
||||
COMPARATOR KEY_GENERIC_TYPE comp;
|
||||
|
||||
MemFreeMergeSortActionComp(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp)
|
||||
{
|
||||
this.array = array;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.comp = comp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute()
|
||||
{
|
||||
if(to - from < BASE_THRESHOLD) {
|
||||
insertionSort(array, from, to, comp);
|
||||
return;
|
||||
}
|
||||
int mid = (from + to) >>> 1;
|
||||
invokeAll(new MemFreeMergeSortActionCompBRACES(array, from, mid, comp), new MemFreeMergeSortActionCompBRACES(array, mid, to, comp));
|
||||
|
||||
if(comp.compare(array[mid - 1], array[mid]) <= 0)
|
||||
return;
|
||||
for(int i = from, j = mid, compare;i < j && j < to;) {
|
||||
if((compare = comp.compare(array[i], array[j])) < 0)
|
||||
i++;
|
||||
else if(compare == 0) swap(array, ++i, j);
|
||||
else {
|
||||
swap(array, i++, j);
|
||||
int k = j;
|
||||
for(;k < to - 1 && comp.compare(array[j], array[k + 1]) > 0;k++);
|
||||
if(j == k)
|
||||
continue;
|
||||
KEY_TYPE value = array[j];
|
||||
System.arraycopy(array, j + 1, array, j, k - j);
|
||||
array[k] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue