diff --git a/app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_1.java b/app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_1.java new file mode 100644 index 0000000..bcfecb9 --- /dev/null +++ b/app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_1.java @@ -0,0 +1,221 @@ +package de.uni_marburg.powersort.MSort; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +public class IMPL_M_1 > { + + private IMPL_M_1() { + } + + /** + * Sorts the given range, using the given workspace array slice + * for temp storage when possible. This method is designed to be + * invoked from public methods (in class Arrays) after performing + * any necessary array bounds checks and expanding parameters into + * the required forms. + * + * @param a the array to be sorted + * @param lo the index of the first element, inclusive, to be sorted + * @param hi the index of the last element, exclusive, to be sorted + * @param c the comparator to use + * @param work a workspace array (slice) + * @param workBase origin of usable space in work array + * @param workLen usable size of work array + * @since 1.8 + */ + protected static int MERGE_COST = 0; + + + public static void fillWithAscRunsHighToLow(List A, int[] runLengths, int runLenFactor) { + //A has a fixed size, but it doesn't have any meaningful values + int n = A.size(); + //This ensures that the sum of runLengths multiplied by runLenFactor equals the list size n. If not, an AssertionError is thrown. + assert IntStream.of(runLengths).sum() * runLenFactor == n; + + //System.out.println("IntStream Of run length output: "+IntStream.of(runLengths).sum()); + //IntStream.of(runLengths).forEach(System.out::println); + for (int i = 0; i < n; i++) { + //putting i in set a, while a is always the last index of n + A.set(i, n - i); + } + + int i = 0; + //For each value l in the array runLengths, do the following + // runLengths = {2, 3, 5}, the loop will run three times, with l taking values 2, 3, and 5 respectively. + for (int l : runLengths) { + int L = l * runLenFactor; + List sublist = A.subList(i, i + L); + Collections.sort(sublist); + i += L; + } + } + + + static > List merge(List run1, List run2) { + List result = new ArrayList<>(); + while (!run1.isEmpty() && !run2.isEmpty()) { + //This comparison only works if the lists are sorted + if (run1.get(0).compareTo(run2.get(0)) < 0) { + result.add(run1.remove(0)); + } else { + result.add(run2.remove(0)); + } + } + /// can be improved by finding out which one is empty and only add the other one + result.addAll(run1); + result.addAll(run2); + return result; + } + + static > void mergeInplace(List a, int i, int m, int j) { + // System.out.printf("Merge(%d, %d, %d)%n", i, m, j); + MERGE_COST += j - i; + List sublist = merge( + new ArrayList<>(a.subList(i, m)), + new ArrayList<>(a.subList(m, j)) + ); + for (int k = 0; k < sublist.size(); k++) { + a.set(i + k, sublist.get(k)); + } + } + + static > int extendRun(List a, int i) { + // if i was the element before end so just return the last element + if (i == a.size() - 1) { + return i + 1; + } + //we're looking at the element next to a[i] + int j = i + 1; + if (a.get(i).compareTo( a.get(j)) <=0) { + while (j < a.size() && a.get(j - 1).compareTo( a.get(j)) <= 0) { + j++; + } + } else { + while (j < a.size() && a.get(j - 1).compareTo(a.get(j)) > 0) { + j++; + } + List sublist = a.subList(i, j); + Collections.reverse(sublist); + } + return j; + } + + public static int power(int[] run1, int[] run2, int n) { + int i1 = run1[0], n1 = run1[1]; + int i2 = run2[0], n2 = run2[1]; + + assert i1 >= 0; + assert i2 == i1 + n1; + assert n1 >= 1 && n2 >= 1; + assert i2 + n2 <= n; + + double a = ((i1 + n1 / 2.0d) / n); + double b = ((i2 + n2 / 2.0d) / n); + + int l = 0; + while (Math.floor(a * Math.pow(2, l)) == Math.floor(b * Math.pow(2, l))) { + l++; + } + return l; + } + + public static > void mergeTopmost2(List a, List runs) { + assert runs.size() >= 2; + + int[] Y = runs.get(runs.size() - 2); + int[] Z = runs.get(runs.size() - 1); + + assert Z[0] == Y[0] + Y[1]; + + mergeInplace(a, Y[0], Z[0], Z[0] + Z[1]); + + runs.set(runs.size() - 2, new int[] {Y[0], Y[1] + Z[1], Y[2]}); + runs.removeLast(); + } + + public static > void powerSort(List a) { + int n = a.size(); + int i = 0; + List runs = new ArrayList<>(); + + int j = extendRun(a, i); + runs.add(new int[] {i, j - i, 0}); + i = j; + + while (i < n) { + j = extendRun(a, i); + int p = power(runs.get(runs.size() - 1), new int[] {i, j - i}, n); + + while (p <= runs.getLast()[2]) { + mergeTopmost2(a, runs); + } + + runs.add(new int[] {i, j - i, p}); + i = j; + } + + while (runs.size() >= 2) { + mergeTopmost2(a, runs); + } + } + + public static int extendRunIncreasingOnly(List a, int i) { + if (i == a.size() - 1) { + return i + 1; + } + int j = i + 1; + while (j < a.size() && a.get(j - 1) <= a.get(j)) { + j++; + } + return j; + } + + public static int powerFast(int[] run1, int[] run2, int n) { + int i1 = run1[0], n1 = run1[1]; + int i2 = run2[0], n2 = run2[1]; + + int a = 2 * i1 + n1; + int b = a + n1 + n2; + + int l = 0; + while (true) { + l++; + if (a >= n) { + assert b >= a; + a -= n; + b -= n; + } else if (b >= n) { + break; + } + assert a < b && b < n; + a <<= 1; + b <<= 1; + } + return l; + } +// +// , +// new SortImpl("MSort") { +// @Override +// @SuppressWarnings("unchecked") +// public void sort(Object[] a) { +// // Create a list of type that matches powerSort's requirements +// List> list = new ArrayList<>(); +// for (Object obj : a) { +// // Since we know the input will be Integer objects in the benchmark +// list.add((Comparable) obj); +// } +// +// // Call powerSort with the proper type +// IMPL_M_1.>powerSort(list); +// +// // Copy back to array +// for (int i = 0; i < a.length; i++) { +// a[i] = list.get(i); +// } +// } +// } +} \ No newline at end of file diff --git a/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java b/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java deleted file mode 100644 index 0d0f25d..0000000 --- a/app/src/main/java/de/uni_marburg/powersort/msort/IMPL_M_1.java +++ /dev/null @@ -1,298 +0,0 @@ -package de.uni_marburg.powersort.msort; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.IntStream; - -public class IMPL_M_1 { - - - - private IMPL_M_1() {} - - /** - * Sorts the given range, using the given workspace array slice - * for temp storage when possible. This method is designed to be - * invoked from public methods (in class Arrays) after performing - * any necessary array bounds checks and expanding parameters into - * the required forms. - * - * @param a the array to be sorted - * @param lo the index of the first element, inclusive, to be sorted - * @param hi the index of the last element, exclusive, to be sorted - * @param c the comparator to use - * @param work a workspace array (slice) - * @param workBase origin of usable space in work array - * @param workLen usable size of work array - * @since 1.8 - */ - protected static int MERGE_COST = 0; - - // Example usage -// int[] runs = new int[] {5, 3, 3, 14, 1, 2}; // example from slides -// //runs = new int[]{9, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; -// -// ArrayList a = new ArrayList<>(IntStream.range(0, Arrays.stream(runs).sum()).boxed().collect(Collectors.toList())); -// -// System.out.println(); -// fillWithAscRunsHighToLow(a, runs); -// MERGE_COST = 0; -// System.out.println("Sorting with Powersort:"); -// powersort(a, this::extendRunIncreasingOnly); -// System.out.println("Merge cost: " + MERGE_COST); - -// runs = [5,3,3,14,1,2]; -// runs = [9,16,7,7,7,7,7,7,7,7,7,7]; -// -// a = list(range(sum(runs))); -// fill_with_asc_runs_high_to_low(a, runs); -// MERGE_COST = 0; -// System.out.println("Sorting with Powersort:"); -// powersort(a, extendRunIncreasingOnly); -// System.out.println("Merge cost: " + MERGE_COST); - - - public static void fillWithAscRunsHighToLow(List A, int[] runLengths, int runLenFactor) { - int n = A.size(); - assert IntStream.of(runLengths).sum() * runLenFactor == n; - - for (int i = 0; i < n; i++) { - A.set(i, n - i); - } - - int i = 0; - for (int l : runLengths) { - int L = l * runLenFactor; - List sublist = A.subList(i, i + L); - Collections.sort(sublist); - i += L; - } - } - - private static List merge(List run1, List run2) { - List result = new ArrayList<>(); - while (!run1.isEmpty() && !run2.isEmpty()) { - if (run1.get(0) < run2.get(0)) { - result.add(run1.remove(0)); - } else { - result.add(run2.remove(0)); - } - } - result.addAll(run1); - result.addAll(run2); - return result; - } - - private static void mergeInplace(List a, int i, int m, int j) { - System.out.printf("Merge(%d, %d, %d)%n", i, m, j); - MERGE_COST += j - i; - List sublist = merge( - new ArrayList<>(a.subList(i, m)), - new ArrayList<>(a.subList(m, j)) - ); - for (int k = 0; k < sublist.size(); k++) { - a.set(i + k, sublist.get(k)); - } - } - - static int extendRun(List a, int i) { - if (i == a.size() - 1) { - return i + 1; - } - int j = i + 1; - if (a.get(i) <= a.get(j)) { - while (j < a.size() && a.get(j - 1) <= a.get(j)) { - j++; - } - } else { - while (j < a.size() && a.get(j - 1) > a.get(j)) { - j++; - } - List sublist = a.subList(i, j); - Collections.reverse(sublist); - } - return j; - } - - private static int extendRunIncreasingOnly(List a, int i) { - if (i == a.size() - 1) { - return i + 1; - } - int j = i + 1; - while (j < a.size() && a.get(j - 1) <= a.get(j)) { - j++; - } - return j; - } - - public static int power(int[] run1, int[] run2, int n) { - int i1 = run1[0], n1 = run1[1]; - int i2 = run2[0], n2 = run2[1]; - - assert i1 >= 0; - assert i2 == i1 + n1; - assert n1 >= 1 && n2 >= 1; - assert i2 + n2 <= n; - - double a = ((i1 + n1 / 2.0d) / n); - double b = ((i2 + n2 / 2.0d) / n); - - int l = 0; - while (Math.floor(a * Math.pow(2, l)) == Math.floor(b * Math.pow(2, l))) { - l++; - } - return l; - } - - public static int powerFast(int[] run1, int[] run2, int n) { - int i1 = run1[0], n1 = run1[1]; - int i2 = run2[0], n2 = run2[1]; - - int a = 2 * i1 + n1; - int b = a + n1 + n2; - - int l = 0; - while (true) { - l++; - if (a >= n) { - assert b >= a; - a -= n; - b -= n; - } else if (b >= n) { - break; - } - assert a < b && b < n; - a <<= 1; - b <<= 1; - } - return l; - } - - public static void mergeTopmost2(List a, List runs) { - assert runs.size() >= 2; - - int[] Y = runs.get(runs.size() - 2); - int[] Z = runs.get(runs.size() - 1); - - assert Z[0] == Y[0] + Y[1]; - - mergeInplace(a, Y[0], Z[0], Z[0] + Z[1]); - - runs.set(runs.size() - 2, new int[] {Y[0], Y[1] + Z[1], Y[2]}); - runs.remove(runs.size() - 1); - } - - public static void powerSort(List a) { - int n = a.size(); - int i = 0; - List runs = new ArrayList<>(); - - int j = extendRun(a, i); - runs.add(new int[] {i, j - i, 0}); - i = j; - - while (i < n) { - j = extendRun(a, i); - int p = power(runs.get(runs.size() - 1), new int[] {i, j - i}, n); - - while (p <= runs.get(runs.size() - 1)[2]) { - mergeTopmost2(a, runs); - } - - runs.add(new int[] {i, j - i, p}); - i = j; - } - - while (runs.size() >= 2) { - mergeTopmost2(a, runs); - } - } - - /* """Fills the given array A with ascending runs of the given list of run - lengths. - More precisely, the array is first filled n, n-1, ..., 1 - and then for i=0..l-1 segments of runLengths.get(i) * runLenFactor - are sorted ascending. - The sum of all lengths in runLengths times runLenFactor should be equal to the - length of A. - """*/ - - - /* static void sort(T[] a, int lo, int hi, Comparator c, - T[] work, int workBase, int workLen) { - assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; - }*/ -/* - public static final int MIN_MERGE=24; - public int mergeCost=0; - private final T []sortedArray; - - public PowerSort(T[] sortedArray) { - super(); - this.sortedArray = sortedArray; - } - - ArrayList run1 = new ArrayList<>(); - ArrayList run2 = new ArrayList<>(); - - private AbstractList merge(ArrayList run1, ArrayList run2) { - ArrayList result = new ArrayList<>(); - - while(run1.size() > 0 && run2.size() >0) { - if (run1.getFirst()