From 8379570f9aa5b86dd9815dcc83cceb16840df689 Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:06:11 +0000 Subject: [PATCH 1/6] benchmark: more input lists --- .../powersort/data/AscendingIntegers.java | 6 ++---- .../powersort/data/DataArraySizes.java | 7 ------- .../de/uni_marburg/powersort/data/DataEnum.java | 15 ++++++++++----- .../powersort/data/DescendingIntegers.java | 6 ++---- .../powersort/data/RandomIntegers.java | 6 ++---- .../de/uni_marburg/powersort/sort/SortEnum.java | 5 ++++- 6 files changed, 20 insertions(+), 25 deletions(-) delete mode 100644 app/src/main/java/de/uni_marburg/powersort/data/DataArraySizes.java diff --git a/app/src/main/java/de/uni_marburg/powersort/data/AscendingIntegers.java b/app/src/main/java/de/uni_marburg/powersort/data/AscendingIntegers.java index c660f84..8050a21 100644 --- a/app/src/main/java/de/uni_marburg/powersort/data/AscendingIntegers.java +++ b/app/src/main/java/de/uni_marburg/powersort/data/AscendingIntegers.java @@ -3,11 +3,9 @@ package de.uni_marburg.powersort.data; import de.uni_marburg.powersort.benchmark.IntegerArray; import de.uni_marburg.powersort.benchmark.LongFormatter; -import static de.uni_marburg.powersort.data.DataArraySizes.SIZE_ASC; - public class AscendingIntegers extends IntegerSupplier { - public AscendingIntegers() { - super(IntegerArray.ascending( 1, SIZE_ASC)); + public AscendingIntegers(int size) { + super(IntegerArray.ascending( 1, size)); } @Override diff --git a/app/src/main/java/de/uni_marburg/powersort/data/DataArraySizes.java b/app/src/main/java/de/uni_marburg/powersort/data/DataArraySizes.java deleted file mode 100644 index 627a63e..0000000 --- a/app/src/main/java/de/uni_marburg/powersort/data/DataArraySizes.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.uni_marburg.powersort.data; - -public interface DataArraySizes { - int SIZE_RAND = 50_000_000; - int SIZE_ASC = 50_000_000; - int SIZE_DESC = 50_000_000; -} diff --git a/app/src/main/java/de/uni_marburg/powersort/data/DataEnum.java b/app/src/main/java/de/uni_marburg/powersort/data/DataEnum.java index af0fa35..ff9de0a 100644 --- a/app/src/main/java/de/uni_marburg/powersort/data/DataEnum.java +++ b/app/src/main/java/de/uni_marburg/powersort/data/DataEnum.java @@ -4,18 +4,23 @@ public enum DataEnum { RANDOM_INTEGERS, ASCENDING_INTEGERS, DESCENDING_INTEGERS, - ASCENDING_RUNS; + ASCENDING_RUNS, + ASCENDING_RUNS_WITH_OVERLAP; public ObjectSupplier get() { // We use a seed to get the same random list every time -> Repeatable benchmarks on same input data! // final long seed = 3651660232967549736L; // System.nanoTime() ++ Math.random() final long seed = 140506881906827520L; // (long) 'P' * (long) 'O' *(long) 'W' * (long) 'E' * (long) 'R' * (long) 'S' * (long) 'O' * (long) 'R' * (long) 'T'; + int longListSize = 50_000_000; + return switch (this) { - case RANDOM_INTEGERS -> new RandomIntegers(seed); - case ASCENDING_INTEGERS -> new AscendingIntegers(); - case DESCENDING_INTEGERS -> new DescendingIntegers(); - case ASCENDING_RUNS -> AscendingRuns.newAscendingRuns(10000, 10000, -10000); + case RANDOM_INTEGERS -> new RandomIntegers(longListSize, seed); + case ASCENDING_INTEGERS -> new AscendingIntegers(longListSize); + case DESCENDING_INTEGERS -> new DescendingIntegers(longListSize); + + case ASCENDING_RUNS -> AscendingRuns.newAscendingRuns(10_000, 10_000, -10_000); + case ASCENDING_RUNS_WITH_OVERLAP -> AscendingRuns.newAscendingRuns(10_000, 10_000, -5_000); }; } } diff --git a/app/src/main/java/de/uni_marburg/powersort/data/DescendingIntegers.java b/app/src/main/java/de/uni_marburg/powersort/data/DescendingIntegers.java index 901b08b..70a8f15 100644 --- a/app/src/main/java/de/uni_marburg/powersort/data/DescendingIntegers.java +++ b/app/src/main/java/de/uni_marburg/powersort/data/DescendingIntegers.java @@ -3,11 +3,9 @@ package de.uni_marburg.powersort.data; import de.uni_marburg.powersort.benchmark.IntegerArray; import de.uni_marburg.powersort.benchmark.LongFormatter; -import static de.uni_marburg.powersort.data.DataArraySizes.SIZE_DESC; - public class DescendingIntegers extends IntegerSupplier { - public DescendingIntegers() { - super(IntegerArray.descending(SIZE_DESC, 1)); + public DescendingIntegers(int size) { + super(IntegerArray.descending(size, 1)); } @Override diff --git a/app/src/main/java/de/uni_marburg/powersort/data/RandomIntegers.java b/app/src/main/java/de/uni_marburg/powersort/data/RandomIntegers.java index 40c46f6..f7b85ee 100644 --- a/app/src/main/java/de/uni_marburg/powersort/data/RandomIntegers.java +++ b/app/src/main/java/de/uni_marburg/powersort/data/RandomIntegers.java @@ -3,11 +3,9 @@ package de.uni_marburg.powersort.data; import de.uni_marburg.powersort.benchmark.IntegerArray; import de.uni_marburg.powersort.benchmark.LongFormatter; -import static de.uni_marburg.powersort.data.DataArraySizes.SIZE_RAND; - public class RandomIntegers extends IntegerSupplier { - public RandomIntegers(final long seed) { - super(IntegerArray.random(SIZE_RAND, seed)); + public RandomIntegers(final int size, final long seed) { + super(IntegerArray.random(size, seed)); } @Override 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 151fb55..58b2397 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 @@ -1,17 +1,20 @@ package de.uni_marburg.powersort.sort; +import de.uni_marburg.powersort.FinnSort.FinnSort; import de.uni_marburg.powersort.benchmark.NaturalOrder; public enum SortEnum { // BUBBLE_SORT, MERGE_SORT, - TIM_SORT; + TIM_SORT, + FIN_SORT; public SimpleSort get() { return switch (this) { // case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE); 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 FIN_SORT -> array -> FinnSort.sort(array, NaturalOrder.INSTANCE); }; } } From 43dfcd987eb46cb7a3ed6135d75edaad93a72068 Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:07:18 +0000 Subject: [PATCH 2/6] add sort test --- .../de/uni_marburg/powersort/JUnitUtil.java | 41 +++++++++++++++++++ .../powersort/data/AscendingRunsTest.java | 24 +---------- .../powersort/sort/AbstractSortTest.java | 26 ++++++++++++ .../powersort/sort/FinnSortTest.java | 7 ++++ 4 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 app/src/test/java/de/uni_marburg/powersort/JUnitUtil.java create mode 100644 app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java create mode 100644 app/src/test/java/de/uni_marburg/powersort/sort/FinnSortTest.java diff --git a/app/src/test/java/de/uni_marburg/powersort/JUnitUtil.java b/app/src/test/java/de/uni_marburg/powersort/JUnitUtil.java new file mode 100644 index 0000000..372b152 --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/JUnitUtil.java @@ -0,0 +1,41 @@ +package de.uni_marburg.powersort; + +import org.junit.jupiter.params.converter.SimpleArgumentConverter; + +import java.util.Arrays; + +public class JUnitUtil { + /** + * https://stackoverflow.com/a/46850299/6334421 + */ + public static class IntArrayConverter extends SimpleArgumentConverter { + @Override + protected int[] convert(Object source, Class targetType) { + if (source instanceof String s && int[].class.isAssignableFrom(targetType)) { + if (s.isEmpty()) { + return new int[0]; + } + String[] strings = s.split("\\s*\\|\\s*"); + return Arrays.stream(strings).mapToInt(Integer::valueOf).toArray(); + } else { + throw new IllegalArgumentException("Conversion from " + source.getClass() + + " to " + targetType + " not supported."); + } + } + } + public static class IntegerArrayConverter extends SimpleArgumentConverter { + @Override + protected Integer[] convert(Object source, Class targetType) { + if (source instanceof String s && Integer[].class.isAssignableFrom(targetType)) { + if (s.isEmpty()) { + return new Integer[0]; + } + String[] strings = s.split("\\s*\\|\\s*"); + return Arrays.stream(strings).map(Integer::valueOf).toArray(Integer[]::new); + } else { + throw new IllegalArgumentException("Conversion from " + source.getClass() + + " to " + targetType + " not supported."); + } + } + } +} diff --git a/app/src/test/java/de/uni_marburg/powersort/data/AscendingRunsTest.java b/app/src/test/java/de/uni_marburg/powersort/data/AscendingRunsTest.java index 69f9b15..36e78aa 100644 --- a/app/src/test/java/de/uni_marburg/powersort/data/AscendingRunsTest.java +++ b/app/src/test/java/de/uni_marburg/powersort/data/AscendingRunsTest.java @@ -1,8 +1,8 @@ package de.uni_marburg.powersort.data; +import de.uni_marburg.powersort.JUnitUtil; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; -import org.junit.jupiter.params.converter.SimpleArgumentConverter; import org.junit.jupiter.params.provider.CsvSource; import java.util.Arrays; @@ -10,26 +10,6 @@ import java.util.Arrays; import static org.junit.jupiter.api.Assertions.*; class AscendingRunsTest { - /** - * https://stackoverflow.com/a/46850299/6334421 - */ - private static class IntArrayConverter extends SimpleArgumentConverter { - @Override - protected Object convert(Object source, Class targetType) { - if (source instanceof String s && int[].class.isAssignableFrom(targetType)) { - if (s.isEmpty()) { - return new int[0]; - } - String[] strings = s.split("\\s*\\|\\s*"); - return Arrays.stream(strings).mapToInt(Integer::valueOf).toArray(); - } else { - throw new IllegalArgumentException("Conversion from " + source.getClass() - + " to " + targetType + " not supported."); - } - } - - } - @ParameterizedTest @CsvSource({ "0,1,-1,''", @@ -38,7 +18,7 @@ class AscendingRunsTest { "2,2,-2,0|1|-2|-1", "2,4,-2,0|1|2|3|-2|-1|0|1", }) - void testAscendingRuns1(int numOfRuns, int runLength, int decreaseBetweenRuns, @ConvertWith(IntArrayConverter.class) int[] expected) { + void testAscendingRuns1(int numOfRuns, int runLength, int decreaseBetweenRuns, @ConvertWith(JUnitUtil.IntArrayConverter.class) int[] expected) { Integer[] actualIntegers = AscendingRuns.newAscendingRuns(numOfRuns, runLength, decreaseBetweenRuns).getCopy(); int[] actual = Arrays.stream(actualIntegers).mapToInt(Integer::valueOf).toArray(); assertArrayEquals(expected, actual); 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 new file mode 100644 index 0000000..7fde10e --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/sort/AbstractSortTest.java @@ -0,0 +1,26 @@ +package de.uni_marburg.powersort.sort; + +import de.uni_marburg.powersort.JUnitUtil; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +public abstract class AbstractSortTest { + SortEnum sortAlg; + + @ParameterizedTest + @CsvSource({ + "'',''", + "'1337','1337'", + "'3|2|1','1|2|3'", + "'1|1','1|1'", + "'2|1','1|2'", + "'2|1|2','1|2|2'", + }) + void test1(@ConvertWith(JUnitUtil.IntegerArrayConverter.class) Integer[] array, @ConvertWith(JUnitUtil.IntegerArrayConverter.class) Integer[] expected) { + sortAlg.get().sort(array); + assertArrayEquals(expected, array); + } +} diff --git a/app/src/test/java/de/uni_marburg/powersort/sort/FinnSortTest.java b/app/src/test/java/de/uni_marburg/powersort/sort/FinnSortTest.java new file mode 100644 index 0000000..17578ac --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/sort/FinnSortTest.java @@ -0,0 +1,7 @@ +package de.uni_marburg.powersort.sort; + +public class FinnSortTest extends AbstractSortTest { + FinnSortTest() { + sortAlg = SortEnum.FIN_SORT; + } +} From cb9ff240ea6e00c09d60480557fb4eb6c3b2280e Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:19:35 +0000 Subject: [PATCH 3/6] refactor --- .../uni_marburg/powersort/{benchmark => }/Educational.java | 5 ++++- .../de/uni_marburg/powersort/benchmark/DummyComparable1.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) rename app/src/main/java/de/uni_marburg/powersort/{benchmark => }/Educational.java (92%) diff --git a/app/src/main/java/de/uni_marburg/powersort/benchmark/Educational.java b/app/src/main/java/de/uni_marburg/powersort/Educational.java similarity index 92% rename from app/src/main/java/de/uni_marburg/powersort/benchmark/Educational.java rename to app/src/main/java/de/uni_marburg/powersort/Educational.java index 22c13b2..35bb456 100644 --- a/app/src/main/java/de/uni_marburg/powersort/benchmark/Educational.java +++ b/app/src/main/java/de/uni_marburg/powersort/Educational.java @@ -1,4 +1,7 @@ -package de.uni_marburg.powersort.benchmark; +package de.uni_marburg.powersort; + +import de.uni_marburg.powersort.benchmark.DummyComparable1; +import de.uni_marburg.powersort.benchmark.NaturalOrder; import java.util.Arrays; diff --git a/app/src/main/java/de/uni_marburg/powersort/benchmark/DummyComparable1.java b/app/src/main/java/de/uni_marburg/powersort/benchmark/DummyComparable1.java index 7cea94b..a404bbe 100644 --- a/app/src/main/java/de/uni_marburg/powersort/benchmark/DummyComparable1.java +++ b/app/src/main/java/de/uni_marburg/powersort/benchmark/DummyComparable1.java @@ -3,7 +3,7 @@ package de.uni_marburg.powersort.benchmark; /** * A class for tiny, comparable objects. */ -record DummyComparable1(int id) implements Comparable { +public record DummyComparable1(int id) implements Comparable { @Override public int compareTo(DummyComparable1 other) { return id - other.id; From e25a14f718631a60dacaeeaf80f311b8ac2bd09e Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:20:06 +0000 Subject: [PATCH 4/6] test and benchmark: add ASort --- .../main/java/de/uni_marburg/powersort/sort/SortEnum.java | 4 +++- .../test/java/de/uni_marburg/powersort/sort/ASortTest.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 app/src/test/java/de/uni_marburg/powersort/sort/ASortTest.java 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 58b2397..f2c6bfe 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 @@ -7,7 +7,8 @@ public enum SortEnum { // BUBBLE_SORT, MERGE_SORT, TIM_SORT, - FIN_SORT; + FIN_SORT, + ASORT; public SimpleSort get() { return switch (this) { @@ -15,6 +16,7 @@ public enum SortEnum { 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 FIN_SORT -> array -> FinnSort.sort(array, NaturalOrder.INSTANCE); + case ASORT -> array -> ASort.sort(array, NaturalOrder.INSTANCE); }; } } diff --git a/app/src/test/java/de/uni_marburg/powersort/sort/ASortTest.java b/app/src/test/java/de/uni_marburg/powersort/sort/ASortTest.java new file mode 100644 index 0000000..dc7acf5 --- /dev/null +++ b/app/src/test/java/de/uni_marburg/powersort/sort/ASortTest.java @@ -0,0 +1,7 @@ +package de.uni_marburg.powersort.sort; + +public class ASortTest extends AbstractSortTest { + ASortTest() { + sortAlg = SortEnum.ASORT; + } +} From ccd0fba7c2daac4b9391826efc8561d19651ded3 Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:28:43 +0000 Subject: [PATCH 5/6] docs --- README.md | 6 ------ .../de/uni_marburg/powersort/sort/ComparableTimSort.java | 4 ++++ .../main/java/de/uni_marburg/powersort/sort/TimSort.java | 4 ++++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 72131f6..7c50e36 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,3 @@ Run the task "test": ```shell ./gradlew test ``` - -## TimSort - -Imported from -- src/java.base/share/classes/java/util/TimSort.java -- src/java.base/share/classes/java/util/ComparableTimSort.java diff --git a/app/src/main/java/de/uni_marburg/powersort/sort/ComparableTimSort.java b/app/src/main/java/de/uni_marburg/powersort/sort/ComparableTimSort.java index 8396420..1d0b78b 100644 --- a/app/src/main/java/de/uni_marburg/powersort/sort/ComparableTimSort.java +++ b/app/src/main/java/de/uni_marburg/powersort/sort/ComparableTimSort.java @@ -24,6 +24,10 @@ * questions. */ +/* + * Imported from OpenJDK git repo ComparableTimSort.java + */ + package de.uni_marburg.powersort.sort; /** diff --git a/app/src/main/java/de/uni_marburg/powersort/sort/TimSort.java b/app/src/main/java/de/uni_marburg/powersort/sort/TimSort.java index 3bab3b7..0a3958f 100644 --- a/app/src/main/java/de/uni_marburg/powersort/sort/TimSort.java +++ b/app/src/main/java/de/uni_marburg/powersort/sort/TimSort.java @@ -24,6 +24,10 @@ * questions. */ +/* + * Imported from OpenJDK git repo TimSort.java + */ + package de.uni_marburg.powersort.sort; import java.util.Comparator; From d19d89006c860db05ab2333f7897f71f24fdb60c Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Mon, 16 Dec 2024 21:30:53 +0000 Subject: [PATCH 6/6] add sort test --- .../powersort/sort/AbstractSortTest.java | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) 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 7fde10e..b058a10 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 @@ -1,10 +1,13 @@ package de.uni_marburg.powersort.sort; import de.uni_marburg.powersort.JUnitUtil; +import de.uni_marburg.powersort.data.AscendingRuns; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.CsvSource; +import java.util.Arrays; + import static org.junit.jupiter.api.Assertions.assertArrayEquals; public abstract class AbstractSortTest { @@ -12,14 +15,31 @@ public abstract class AbstractSortTest { @ParameterizedTest @CsvSource({ - "'',''", - "'1337','1337'", - "'3|2|1','1|2|3'", - "'1|1','1|1'", - "'2|1','1|2'", - "'2|1|2','1|2|2'", + "''", + "1337", + "3|2|1", + "1|1", + "2|1", + "2|1|2", }) - void test1(@ConvertWith(JUnitUtil.IntegerArrayConverter.class) Integer[] array, @ConvertWith(JUnitUtil.IntegerArrayConverter.class) Integer[] expected) { + void test1(@ConvertWith(JUnitUtil.IntegerArrayConverter.class) Integer[] array) { + sortAndCheckResult(array); + } + + @ParameterizedTest + @CsvSource({ + "3,7,-13", + "3,7,-3", + }) + void test2(int numOfRuns, int runLength, int decreaseBetweenRuns) { + Integer[] array = AscendingRuns.newAscendingRuns(numOfRuns, runLength, decreaseBetweenRuns).getCopy(); + sortAndCheckResult(array); + } + + void sortAndCheckResult(Integer[] array){ + Integer[] expected = Arrays.copyOf(array, array.length); + Arrays.sort(expected); + sortAlg.get().sort(array); assertArrayEquals(expected, array); }