diff --git a/app/src/main/java/de/uni_marburg/powersort/sort/SortEnum.java b/app/src/main/java/de/uni_marburg/powersort/sort/SortEnum.java index 8ae042a..56a9901 100644 --- a/app/src/main/java/de/uni_marburg/powersort/sort/SortEnum.java +++ b/app/src/main/java/de/uni_marburg/powersort/sort/SortEnum.java @@ -2,10 +2,12 @@ package de.uni_marburg.powersort.sort; import de.uni_marburg.powersort.FinnSort.FinnSort; import de.uni_marburg.powersort.benchmark.NaturalOrder; +import de.uni_marburg.powersort.sort.dpqs.DualPivotQuicksort; public enum SortEnum { BUBBLE_SORT, QUICK_SORT, + DPQS, MERGE_SORT, TIM_SORT, FINN_SORT, @@ -15,6 +17,7 @@ public enum SortEnum { return switch (this) { case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE); case QUICK_SORT -> array -> QuickSort.sort(array, NaturalOrder.INSTANCE); + case DPQS -> array -> DualPivotQuicksort.sort(array, 0, array.length); case MERGE_SORT -> array -> MergeSort.legacyMergeSort(array, NaturalOrder.INSTANCE); case TIM_SORT -> array -> TimSort.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0); case FINN_SORT -> array -> FinnSort.sort(array, NaturalOrder.INSTANCE); diff --git a/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/DualPivotQuicksort.java b/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/DualPivotQuicksort.java index 1177807..ed95833 100644 --- a/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/DualPivotQuicksort.java +++ b/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/DualPivotQuicksort.java @@ -1,4 +1,6 @@ // Imported from JDK23 DualPivotQuicksort.java +// Removed parallel parts +// Changed from int[] to Object[] package de.uni_marburg.powersort.sort.dpqs; @@ -27,6 +29,8 @@ package de.uni_marburg.powersort.sort.dpqs; * questions. */ +import de.uni_marburg.powersort.benchmark.NaturalOrder; + import java.util.Arrays; /** @@ -95,35 +99,6 @@ public final class DualPivotQuicksort { */ private static final int MAX_RECURSION_DEPTH = 64 * DELTA; - /** - * Represents a function that accepts the array and sorts the specified range - * of the array into ascending order. - */ - @FunctionalInterface - private interface SortOperation { - /** - * Sorts the specified range of the array. - * - * @param a the array to be sorted - * @param low the index of the first element, inclusive, to be sorted - * @param high the index of the last element, exclusive, to be sorted - */ - void sort(A a, int low, int high); - } - - /** - * Sorts the specified range of the array into ascending numerical order. - * - * @param array the array to be sorted - * the array to sort, otherwise if the array is {@code null},an absolute - * address pointing to the first element to sort from. - * @param low the index of the first element, inclusive, to be sorted - * @param high the index of the last element, exclusive, to be sorted - * @param so the method reference for the fallback implementation - */ - private static void sort(A array, int low, int high, SortOperation so) { - so.sort(array, low, high); - } /** * Represents a function that accepts the array and partitions the specified range @@ -153,24 +128,17 @@ public final class DualPivotQuicksort { * @param po the method reference for the fallback implementation */ private static int[] partition(A array, int high, int pivotIndex1, int pivotIndex2, PartitionOperation po) { - return po.partition(array, Unsafe.ARRAY_INT_BASE_OFFSET, high, pivotIndex1, pivotIndex2); + return po.partition(array, 0, high, pivotIndex1, pivotIndex2); } /** - * Sorts the specified range of the array using parallel merge - * sort and/or Dual-Pivot Quicksort. - *

- * To balance the faster splitting and parallelism of merge sort - * with the faster element partitioning of Quicksort, ranges are - * subdivided in tiers such that, if there is enough parallelism, - * the four-way parallel merge is started, still ensuring enough - * parallelism to process the partitions. + * Sorts the specified range of the array Dual-Pivot Quicksort. * * @param a the array to be sorted * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - public static void sort(int[] a, int low, int high) { + public static void sort(Object[] a, int low, int high) { sort(a, 0, low, high); } @@ -184,14 +152,14 @@ public final class DualPivotQuicksort { * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - static void sort(int[] a, int bits, int low, int high) { + static void sort(Object[] a, int bits, int low, int high) { while (true) { int end = high - 1, size = high - low; /* * Run mixed insertion sort on small non-leftmost parts. */ if (size < MAX_MIXED_INSERTION_SORT_SIZE + bits && (bits & 1) > 0) { - sort(a, low, high, DualPivotQuicksort::mixedInsertionSort); + mixedInsertionSort(a, low, high); return; } @@ -199,7 +167,7 @@ public final class DualPivotQuicksort { * Invoke insertion sort on small leftmost part. */ if (size < MAX_INSERTION_SORT_SIZE) { - sort(a, low, high, DualPivotQuicksort::insertionSort); + insertionSort(a, low, high); return; } @@ -238,7 +206,7 @@ public final class DualPivotQuicksort { int e3 = (e1 + e5) >>> 1; int e2 = (e1 + e3) >>> 1; int e4 = (e3 + e5) >>> 1; - int a3 = a[e3]; + Object a3 = a[e3]; /* * Sort these elements in place by the combination @@ -252,34 +220,34 @@ public final class DualPivotQuicksort { * | | * 1 ------------o-----o------------ */ - if (a[e5] < a[e2]) { - int t = a[e5]; + if (NaturalOrder.INSTANCE.compare(a[e5] , a[e2])<0) { + Object t = a[e5]; a[e5] = a[e2]; a[e2] = t; } - if (a[e4] < a[e1]) { - int t = a[e4]; + if (NaturalOrder.INSTANCE.compare(a[e4] , a[e1])<0) { + Object t = a[e4]; a[e4] = a[e1]; a[e1] = t; } - if (a[e5] < a[e4]) { - int t = a[e5]; + if (NaturalOrder.INSTANCE.compare(a[e5] , a[e4])<0) { + Object t = a[e5]; a[e5] = a[e4]; a[e4] = t; } - if (a[e2] < a[e1]) { - int t = a[e2]; + if (NaturalOrder.INSTANCE.compare(a[e2] , a[e1])<0) { + Object t = a[e2]; a[e2] = a[e1]; a[e1] = t; } - if (a[e4] < a[e2]) { - int t = a[e4]; + if (NaturalOrder.INSTANCE.compare(a[e4] , a[e2])<0) { + Object t = a[e4]; a[e4] = a[e2]; a[e2] = t; } - if (a3 < a[e2]) { - if (a3 < a[e1]) { + if (NaturalOrder.INSTANCE.compare(a3 , a[e2])<0) { + if (NaturalOrder.INSTANCE.compare(a3 , a[e1])<0) { a[e3] = a[e2]; a[e2] = a[e1]; a[e1] = a3; @@ -287,8 +255,8 @@ public final class DualPivotQuicksort { a[e3] = a[e2]; a[e2] = a3; } - } else if (a3 > a[e4]) { - if (a3 > a[e5]) { + } else if (NaturalOrder.INSTANCE.compare(a3 , a[e4])>0) { + if (NaturalOrder.INSTANCE.compare(a3 , a[e5])>0) { a[e3] = a[e4]; a[e4] = a[e5]; a[e5] = a3; @@ -305,7 +273,7 @@ public final class DualPivotQuicksort { /* * Partitioning with 2 pivots in case of different elements. */ - if (a[e1] < a[e2] && a[e2] < a[e3] && a[e3] < a[e4] && a[e4] < a[e5]) { + if (NaturalOrder.INSTANCE.compare(a[e1] , a[e2])<0 && NaturalOrder.INSTANCE.compare(a[e2] , a[e3])<0 && NaturalOrder.INSTANCE.compare(a[e3] , a[e4])<0 && NaturalOrder.INSTANCE.compare(a[e4] , a[e5])<0) { /* * Use the first and fifth of the five sorted elements as * the pivots. These values are inexpensive approximation @@ -353,15 +321,15 @@ public final class DualPivotQuicksort { * @param pivotIndex1 the index of pivot1, the first pivot * @param pivotIndex2 the index of pivot2, the second pivot */ - private static int[] partitionDualPivot(int[] a, int low, int high, int pivotIndex1, int pivotIndex2) { + private static int[] partitionDualPivot(Object[] a, int low, int high, int pivotIndex1, int pivotIndex2) { int end = high - 1; int lower = low; int upper = end; int e1 = pivotIndex1; int e5 = pivotIndex2; - int pivot1 = a[e1]; - int pivot2 = a[e5]; + Object pivot1 = a[e1]; + Object pivot2 = a[e5]; /* * The first and the last elements to be sorted are moved @@ -376,8 +344,8 @@ public final class DualPivotQuicksort { /* * Skip elements, which are less or greater than the pivots. */ - while (a[++lower] < pivot1) ; - while (a[--upper] > pivot2) ; + while (NaturalOrder.INSTANCE.compare(a[++lower] , pivot1)<0) ; + while (NaturalOrder.INSTANCE.compare(a[--upper] , pivot2)>0) ; /* * Backward 3-interval partitioning @@ -399,12 +367,12 @@ public final class DualPivotQuicksort { * Pointer k is the last index of ?-part */ for (int unused = --lower, k = ++upper; --k > lower; ) { - int ak = a[k]; + Object ak = a[k]; - if (ak < pivot1) { // Move a[k] to the left side + if (NaturalOrder.INSTANCE.compare(ak , pivot1)<0) { // Move a[k] to the left side while (lower < k) { - if (a[++lower] >= pivot1) { - if (a[lower] > pivot2) { + if (NaturalOrder.INSTANCE.compare(a[++lower] , pivot1)>=0) { + if (NaturalOrder.INSTANCE.compare(a[lower] , pivot2)>0) { a[k] = a[--upper]; a[upper] = a[lower]; } else { @@ -414,7 +382,7 @@ public final class DualPivotQuicksort { break; } } - } else if (ak > pivot2) { // Move a[k] to the right side + } else if (NaturalOrder.INSTANCE.compare(ak , pivot2)>0) { // Move a[k] to the right side a[k] = a[--upper]; a[upper] = ak; } @@ -440,13 +408,13 @@ public final class DualPivotQuicksort { * @param pivotIndex1 the index of pivot1, the first pivot * @param pivotIndex2 the index of pivot2, the second pivot */ - private static int[] partitionSinglePivot(int[] a, int low, int high, int pivotIndex1, int pivotIndex2) { + private static int[] partitionSinglePivot(Object[] a, int low, int high, int pivotIndex1, int pivotIndex2) { int end = high - 1; int lower = low; int upper = end; int e3 = pivotIndex1; - int pivot = a[e3]; + Object pivot = a[e3]; /* * The first element to be sorted is moved to the @@ -477,15 +445,15 @@ public final class DualPivotQuicksort { * Pointer k is the last index of ?-part */ for (int k = ++upper; --k > lower; ) { - int ak = a[k]; + Object ak = a[k]; - if (ak != pivot) { + if (NaturalOrder.INSTANCE.compare(ak , pivot)!=0) { a[k] = pivot; - if (ak < pivot) { // Move a[k] to the left side - while (a[++lower] < pivot) ; + if (NaturalOrder.INSTANCE.compare(ak , pivot)<0) { // Move a[k] to the left side + while (NaturalOrder.INSTANCE.compare(a[++lower] , pivot)<0) ; - if (a[lower] > pivot) { + if (NaturalOrder.INSTANCE.compare(a[lower] , pivot)>0) { a[--upper] = a[lower]; } a[lower] = ak; @@ -519,7 +487,7 @@ public final class DualPivotQuicksort { * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - private static void mixedInsertionSort(int[] a, int low, int high) { + private static void mixedInsertionSort(Object[] a, int low, int high) { int size = high - low; int end = high - 3 * ((size >> 5) << 3); if (end == high) { @@ -528,9 +496,9 @@ public final class DualPivotQuicksort { * Invoke simple insertion sort on tiny array. */ for (int i; ++low < end; ) { - int ai = a[i = low]; + Object ai = a[i = low]; - while (ai < a[--i]) { + while (NaturalOrder.INSTANCE.compare(ai,a[--i])<0) { a[i + 1] = a[i]; } a[i + 1] = ai; @@ -546,29 +514,29 @@ public final class DualPivotQuicksort { * proper area for such elements). It avoids expensive * movements of these elements through the whole array. */ - int pin = a[end]; + Object pin = a[end]; for (int i, p = high; ++low < end; ) { - int ai = a[i = low]; + Object ai = a[i = low]; - if (ai < a[i - 1]) { // Small element + if (NaturalOrder.INSTANCE.compare(ai,a[i - 1])<0) { // Small element /* * Insert small element into sorted part. */ a[i] = a[--i]; - while (ai < a[--i]) { + while (NaturalOrder.INSTANCE.compare(ai,a[--i])<0) { a[i + 1] = a[i]; } a[i + 1] = ai; - } else if (p > i && ai > pin) { // Large element + } else if (p > i && NaturalOrder.INSTANCE.compare(ai,pin)>0) { // Large element /* * Find element smaller than pin. */ - while (a[--p] > pin) ; + while (NaturalOrder.INSTANCE.compare(a[--p] , pin)>0) ; /* * Swap it with large element. @@ -581,7 +549,7 @@ public final class DualPivotQuicksort { /* * Insert small element into sorted part. */ - while (ai < a[--i]) { + while (NaturalOrder.INSTANCE.compare(ai , a[--i])<0) { a[i + 1] = a[i]; } a[i + 1] = ai; @@ -592,33 +560,33 @@ public final class DualPivotQuicksort { * Continue with pair insertion sort on remain part. */ for (int i; low < high; ++low) { - int a1 = a[i = low], a2 = a[++low]; + Object a1 = a[i = low], a2 = a[++low]; /* * Insert two elements per iteration: at first, insert the * larger element and then insert the smaller element, but * from the position where the larger element was inserted. */ - if (a1 > a2) { + if (NaturalOrder.INSTANCE.compare(a1 , a2)>0) { - while (a1 < a[--i]) { + while (NaturalOrder.INSTANCE.compare(a1 , a[--i])<0) { a[i + 2] = a[i]; } a[++i + 1] = a1; - while (a2 < a[--i]) { + while (NaturalOrder.INSTANCE.compare(a2 , a[--i])<0) { a[i + 1] = a[i]; } a[i + 1] = a2; - } else if (a1 < a[i - 1]) { + } else if (NaturalOrder.INSTANCE.compare(a1 , a[i - 1])<0) { - while (a2 < a[--i]) { + while (NaturalOrder.INSTANCE.compare(a2 , a[--i])<0) { a[i + 2] = a[i]; } a[++i + 1] = a2; - while (a1 < a[--i]) { + while (NaturalOrder.INSTANCE.compare(a1 , a[--i])<0) { a[i + 1] = a[i]; } a[i + 1] = a1; @@ -634,12 +602,12 @@ public final class DualPivotQuicksort { * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - private static void insertionSort(int[] a, int low, int high) { + private static void insertionSort(Object[] a, int low, int high) { for (int i, k = low; ++k < high; ) { - int ai = a[i = k]; + Object ai = a[i = k]; - if (ai < a[i - 1]) { - while (--i >= low && ai < a[i]) { + if (NaturalOrder.INSTANCE.compare(ai , a[i - 1])<0) { + while (--i >= low && NaturalOrder.INSTANCE.compare(ai , a[i])<0) { a[i + 1] = a[i]; } a[i + 1] = ai; @@ -654,12 +622,12 @@ public final class DualPivotQuicksort { * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - private static void heapSort(int[] a, int low, int high) { + private static void heapSort(Object[] a, int low, int high) { for (int k = (low + high) >>> 1; k > low; ) { pushDown(a, --k, a[k], low, high); } while (--high > low) { - int max = a[low]; + Object max = a[low]; pushDown(a, low, a[high], low, high); a[high] = max; } @@ -674,17 +642,17 @@ public final class DualPivotQuicksort { * @param low the index of the first element, inclusive, to be sorted * @param high the index of the last element, exclusive, to be sorted */ - private static void pushDown(int[] a, int p, int value, int low, int high) { + private static void pushDown(Object[] a, int p, Object value, int low, int high) { for (int k; ; a[p] = a[p = k]) { k = (p << 1) - low + 2; // Index of the right child if (k > high) { break; } - if (k == high || a[k] < a[k - 1]) { + if (k == high || NaturalOrder.INSTANCE.compare(a[k] , a[k - 1])<0) { --k; } - if (a[k] <= value) { + if (NaturalOrder.INSTANCE.compare(a[k] , value)<=0) { break; } } @@ -699,7 +667,7 @@ public final class DualPivotQuicksort { * @param size the array size * @return true if finally sorted, false otherwise */ - private static boolean tryMergeRuns(int[] a, int low, int size) { + private static boolean tryMergeRuns(Object[] a, int low, int size) { /* * The run array is constructed only if initial runs are @@ -718,24 +686,24 @@ public final class DualPivotQuicksort { /* * Find the end index of the current run. */ - if (a[k - 1] < a[k]) { + if (NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])<0) { // Identify ascending sequence - while (++k < high && a[k - 1] <= a[k]) ; + while (++k < high && NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])<=0) ; - } else if (a[k - 1] > a[k]) { + } else if (NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])>0) { // Identify descending sequence - while (++k < high && a[k - 1] >= a[k]) ; + while (++k < high && NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])>=0) ; // Reverse into ascending order - for (int i = last - 1, j = k; ++i < --j && a[i] > a[j]; ) { - int ai = a[i]; + for (int i = last - 1, j = k; ++i < --j && NaturalOrder.INSTANCE.compare(a[i] , a[j])>0; ) { + Object ai = a[i]; a[i] = a[j]; a[j] = ai; } } else { // Identify constant sequence - for (int ak = a[k]; ++k < high && ak == a[k]; ) ; + for (Object ak = a[k]; ++k < high && NaturalOrder.INSTANCE.compare(ak , a[k])==0; ) ; if (k < high) { continue; @@ -767,7 +735,7 @@ public final class DualPivotQuicksort { run = new int[((size >> 10) | 0x7F) & 0x3FF]; run[0] = low; - } else if (a[last - 1] > a[last]) { + } else if (NaturalOrder.INSTANCE.compare(a[last - 1] , a[last])>0) { if (count > (k - low) >> MIN_FIRST_RUNS_FACTOR) { @@ -801,10 +769,10 @@ public final class DualPivotQuicksort { * Merge runs of highly structured array. */ if (count > 1) { - int[] b; + Object[] b; int offset = low; - b = new int[size]; + b = new Object[size]; mergeRuns(a, b, offset, 1, run, 0, count); } return true; @@ -822,7 +790,7 @@ public final class DualPivotQuicksort { * @param hi the start index of the last run, inclusive * @return the destination where runs are merged */ - private static int[] mergeRuns(int[] a, int[] b, int offset, + private static Object[] mergeRuns(Object[] a, Object[] b, int offset, int aim, int[] run, int lo, int hi) { if (hi - lo == 1) { @@ -845,18 +813,18 @@ public final class DualPivotQuicksort { /* * Merge the left and right parts. */ - int[] a1, a2; + Object[] a1, a2; a1 = mergeRuns(a, b, offset, -aim, run, lo, mi); a2 = mergeRuns(a, b, offset, 0, run, mi, hi); - int[] dst = a1 == a ? b : a; + Object[] dst = NaturalOrder.INSTANCE.compare(a1, a) == 0 ? b : a; - int k = a1 == a ? run[lo] - offset : run[lo]; - int lo1 = a1 == b ? run[lo] - offset : run[lo]; - int hi1 = a1 == b ? run[mi] - offset : run[mi]; - int lo2 = a2 == b ? run[mi] - offset : run[mi]; - int hi2 = a2 == b ? run[hi] - offset : run[hi]; + int k = NaturalOrder.INSTANCE.compare(a1 , a)==0 ? run[lo] - offset : run[lo]; + int lo1 = NaturalOrder.INSTANCE.compare(a1 , b)==0 ? run[lo] - offset : run[lo]; + int hi1 = NaturalOrder.INSTANCE.compare(a1 , b)==0 ? run[mi] - offset : run[mi]; + int lo2 = NaturalOrder.INSTANCE.compare(a2 , b)==0 ? run[mi] - offset : run[mi]; + int hi2 = NaturalOrder.INSTANCE.compare(a2 , b)==0 ? run[hi] - offset : run[hi]; mergeParts(dst, k, a1, lo1, hi1, a2, lo2, hi2); return dst; @@ -874,15 +842,15 @@ public final class DualPivotQuicksort { * @param lo2 the start index of the second part, inclusive * @param hi2 the end index of the second part, exclusive */ - private static void mergeParts(int[] dst, int k, - int[] a1, int lo1, int hi1, int[] a2, int lo2, int hi2) { + private static void mergeParts(Object[] dst, int k, + Object[] a1, int lo1, int hi1, Object[] a2, int lo2, int hi2) { /* * Merge small parts sequentially. */ while (lo1 < hi1 && lo2 < hi2) { - dst[k++] = a1[lo1] < a2[lo2] ? a1[lo1++] : a2[lo2++]; + dst[k++] = NaturalOrder.INSTANCE.compare(a1[lo1] , a2[lo2])<0 ? a1[lo1++] : a2[lo2++]; } if (dst != a1 || k < lo1) { while (lo1 < hi1) { diff --git a/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/Unsafe.java b/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/Unsafe.java deleted file mode 100644 index 2395c0b..0000000 --- a/app/src/main/java/de/uni_marburg/powersort/sort/dpqs/Unsafe.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.uni_marburg.powersort.sort.dpqs; - -public final class Unsafe { - private Unsafe() { - } - public static final int ARRAY_INT_BASE_OFFSET - = 16; // Taken from debugging JDK 23 Unsafe.ARRAY_INT_BASE_OFFSET -} diff --git a/app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java b/app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java index 2c0e5a7..99bbf0c 100644 --- a/app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java +++ b/app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java @@ -30,6 +30,8 @@ public abstract class AbstractSortTest { @CsvSource({ "3,7,-13", "3,7,-3", + "10,10,-5", + "17,17,-17", }) void test2(int numOfRuns, int runLength, int decreaseBetweenRuns) { Integer[] array = AscendingRuns.newAscendingRuns(numOfRuns, runLength, decreaseBetweenRuns).getCopy(); @@ -42,7 +44,7 @@ public abstract class AbstractSortTest { "13", "1337", }) - void test2(int size) { + void test3(int size) { Integer[] array = new DescendingIntegers(size).getCopy(); sortAndCheckResult(array); } @@ -52,6 +54,6 @@ public abstract class AbstractSortTest { Arrays.sort(expected); sortAlg.getSortImpl().sort(array); - assertArrayEquals(expected, array); + assertArrayEquals(expected, array, Arrays.toString(array) + "\n\n"); } } diff --git a/app/src/test/java/de/uni_marburg/powersort/sort/DualPivotQuicksort.java b/app/src/test/java/de/uni_marburg/powersort/sort/DualPivotQuicksort.java new file mode 100644 index 0000000..7824ad6 --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/sort/DualPivotQuicksort.java @@ -0,0 +1,7 @@ +package de.uni_marburg.powersort.sort; + +public class DualPivotQuicksort extends AbstractSortTest { + DualPivotQuicksort() { + sortAlg = SortEnum.DPQS; + } +}