Added Parallel Sorting Methods.

This commit is contained in:
Speiger 2020-11-30 02:27:58 +01:00
parent 66430d5a8a
commit 0c53fbab6b
2 changed files with 294 additions and 20 deletions

View File

@ -1,39 +1,50 @@
package speiger.src.collections.utils; package speiger.src.collections.utils;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class SanityChecks public class SanityChecks
{ {
public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 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"); if(value > Byte.MAX_VALUE || value < Byte.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Byte[-128,127] range");
return (byte)value; 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"); if(value > Short.MAX_VALUE || value < Short.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Short[-32768,32767] range");
return (short)value; 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"); if(value > Character.MAX_VALUE || value < Character.MIN_VALUE) throw new IllegalStateException("Value ["+value+"] out of Character[0,65535] range");
return (char)value; return (char)value;
} }
public static float castToFloat(double value) public static float castToFloat(double value) {
{
if(Double.isNaN(value)) return Float.NaN; if(Double.isNaN(value)) return Float.NaN;
if(Double.isInfinite(value)) return value > 0 ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; 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"); if(value < -Float.MAX_VALUE || value > Float.MAX_VALUE) throw new IllegalStateException("Value ["+value+"] out of Float range");
return (float)value; 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+")"); if(offset < 0) throw new IllegalStateException("Offset is negative ("+offset+")");
else if(accessSize < 0) throw new IllegalStateException("Size is negative ("+accessSize+")"); 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 + ")"); 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;
}
} }

View File

@ -2,16 +2,20 @@ package speiger.src.collections.PACKAGE.utils;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveAction;
#if !TYPE_OBJECT #if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR; import speiger.src.collections.PACKAGE.functions.COMPARATOR;
import speiger.src.collections.utils.SanityChecks;
#else #else
import java.util.Comparator; import java.util.Comparator;
#endif #endif
import speiger.src.collections.utils.SanityChecks;
public class ARRAYS public class ARRAYS
{ {
public static final int BASE_THRESHOLD = 16;
public static final int PARALLEL_THRESHOLD = 8192;
#if !TYPE_OBJECT #if !TYPE_OBJECT
public static final KEY_TYPE[] EMPTY_ARRAY = new KEY_TYPE[0]; 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) { 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); insertionSort(array, from, to, comp);
return; return;
} }
@ -179,7 +183,7 @@ public class ARRAYS
} }
public static COMPAREABLE_BRACES void mergeSort(KEY_TYPE[] array, KEY_TYPE[] supp, int from, int to) { 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); insertionSort(array, from, to);
return; 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) { public static GENERIC_BRACES void memFreeMergeSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
memFreeMergeSort(array, 0, array.length, 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) { 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); insertionSort(array, from, to, comp);
return; return;
} }
@ -242,7 +278,7 @@ public class ARRAYS
} }
public static COMPAREABLE_BRACES void memFreeMergeSort(KEY_TYPE[] array, int from, int to) { 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); insertionSort(array, from, to);
return; 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) { public static GENERIC_BRACES void quickSort(KEY_TYPE[] array, COMPARATOR KEY_GENERIC_TYPE comp) {
quickSort(array, 0, array.length, 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) { public static GENERIC_BRACES void quickSort(KEY_TYPE[] array, int from, int to, COMPARATOR KEY_GENERIC_TYPE comp) {
int length = to - from; int length = to - from;
if(length <= 0) return; if(length <= 0) return;
if(length < 16) { if(length < BASE_THRESHOLD) {
selectionSort(array, from, to, comp); selectionSort(array, from, to, comp);
return; return;
} }
@ -311,7 +379,7 @@ public class ARRAYS
public static COMPAREABLE_BRACES void quickSort(KEY_TYPE[] array, int from, int to) { public static COMPAREABLE_BRACES void quickSort(KEY_TYPE[] array, int from, int to) {
int length = to - from; int length = to - from;
if(length <= 0) return; if(length <= 0) return;
if(length < 16) { if(length < BASE_THRESHOLD) {
selectionSort(array, from, to); selectionSort(array, from, to);
return; return;
} }
@ -332,6 +400,38 @@ public class ARRAYS
if((length = d - c) > 1) quickSort(array, to - length, to); 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) { public static GENERIC_BRACES void swap(KEY_TYPE[] a, int from, int to) {
KEY_TYPE t = a[from]; KEY_TYPE t = a[from];
a[from] = a[to]; a[from] = a[to];
@ -377,7 +477,7 @@ public class ARRAYS
{ {
int length = to - from; int length = to - from;
if(length <= 0) return; if(length <= 0) return;
if(length < 16) { if(length < BASE_THRESHOLD) {
selectionSort(array, from, to); selectionSort(array, from, to);
return; return;
} }
@ -420,7 +520,7 @@ public class ARRAYS
{ {
int length = to - from; int length = to - from;
if(length <= 0) return; if(length <= 0) return;
if(length < 16) { if(length < BASE_THRESHOLD) {
selectionSort(array, from, to, comp); selectionSort(array, from, to, comp);
return; return;
} }
@ -442,4 +542,167 @@ public class ARRAYS
else if(d - c > 1) new QuickSortActionCompBRACES(array, to - (d - c), to, comp).invoke(); 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;
}
}
}
}
} }