Skip to content

Commit

Permalink
Don't run Tim Sort more than necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaming32 committed Nov 2, 2021
1 parent 73d11be commit a0fe48f
Showing 1 changed file with 58 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,35 @@ public void grailSortDynamicOOP(K[] array, int start, int length) throws Reflect
}

static interface IntegerPair {
public Integer getKey();
public Integer getValue();
public int getKey();
public int getValue();
}

static class GrailPair implements IntegerPair {
private Integer key;
private Integer value;
private int key, value;

public GrailPair(Integer key, Integer value) {
public GrailPair(int key, int value) {
this.key = key;
this.value = value;
}

@Override
public Integer getKey() {
public int getKey() {
return this.key;
}

@Override
public Integer getValue() {
public int getValue() {
return this.value;
}

@Override
public boolean equals(Object o) {
if (o == null) return false;
if (!(o instanceof GrailPair)) return false;
GrailPair other = (GrailPair)o;
return this.key == other.key && this.value == other.value;
}
}

static class GrailComparator implements Comparator<GrailPair> {
Expand All @@ -102,7 +111,7 @@ public int compare(GrailPair o1, GrailPair o2) {

private GrailPair[] keyArray;
private GrailPair[] referenceArray;
private Integer[] valueArray;
private int[] valueArray;

private String failReason;
private int count, successes, failures;
Expand All @@ -116,27 +125,26 @@ public Tester(int maxLength, int maxKeyCount) {

private void initArrays() {
this.keyArray = new GrailPair[this.maxLength];
this.valueArray = new Integer[this.maxKeyCount];
this.referenceArray = new GrailPair[this.maxKeyCount];
this.valueArray = new int[this.maxKeyCount];
}

private int getRandomNumber(int key) {
this.seed = (this.seed * 1234565) + 1;
return (int) (((long) (this.seed & 0x7fffffff) * key) >> 31);
}

private void generateTestArray(int start, int length, int keyCount) {
for(int i = 0; i < keyCount; i++) {
this.valueArray[i] = 0;
}
private void generateTestArray(GrailPair[] array, int start, int length, int keyCount) {
Arrays.fill(this.valueArray, 0, keyCount, 0);

for(int i = start; i < start + length; i++) {
if(keyCount != 0) {
int key = this.getRandomNumber(keyCount);
this.keyArray[i] = new GrailPair(key, this.valueArray[key]);
array[i] = new GrailPair(key, this.valueArray[key]);
this.valueArray[key]++;
}
else {
this.keyArray[i] = new GrailPair(this.getRandomNumber(1000000000), 0);
array[i] = new GrailPair(this.getRandomNumber(1000000000), 0);
}
}
}
Expand All @@ -146,22 +154,23 @@ private boolean testArray(int start, int length, GrailComparator test) {
int compare = test.compare(this.keyArray[i - 1],
this.keyArray[i ]);
if(compare > 0) {
this.failReason = "testArray[" + (i - 1) + "] and testArray[" + i + "] are out-of-order\n";
this.failReason = "testArray[" + (i - 1) + "] and testArray[" + i + "] are out-of-order";
return false;
}
else if(compare == 0 && this.keyArray[i - 1].getValue() > this.keyArray[i].getValue()) {
this.failReason = "testArray[" + (i - 1) + "] and testArray[" + i + "] are unstable\n";
this.failReason = "testArray[" + (i - 1) + "] and testArray[" + i + "] are unstable";
return false;
}
else if(!this.keyArray[i - 1].equals(this.referenceArray[i - 1])) {
this.failReason = "testArray[" + (i - 1) + "] does not match the reference array\n";
this.failReason = "testArray[" + (i - 1) + "] does not match the reference array";
return false;
}
}
return true;
}

private void checkAlgorithm(int start, int length, int keyCount, int algorithm, int grailBufferType, String grailStrategy, GrailComparator test) {
int tempSeed = this.seed;
try {
checkAlgorithm0(start, length, keyCount, algorithm, grailBufferType, grailStrategy, test);
} catch (OutOfMemoryError e) {
Expand All @@ -170,7 +179,6 @@ private void checkAlgorithm(int start, int length, int keyCount, int algorithm,
System.err.println("Purging data...");
keyArray = null;
referenceArray = null;
valueArray = null;
System.gc();
System.err.println("Re-initializing arrays...");
initArrays();
Expand All @@ -190,11 +198,12 @@ private void checkAlgorithm(int start, int length, int keyCount, int algorithm,
this.failures++;
this.count++;
}
this.seed = tempSeed;
}

private void checkAlgorithm0(int start, int length, int keyCount, int algorithm, int grailBufferType, String grailStrategy, GrailComparator test) throws Exception {
this.generateTestArray(start, length, keyCount);
this.referenceArray = Arrays.copyOf(this.keyArray, start + length);
GrailPair[] array = algorithm == 2 ? this.referenceArray : this.keyArray;
this.generateTestArray(array, start, length, keyCount);

String grailType = "w/o External Buffer";
if(grailBufferType == 1) {
Expand All @@ -217,10 +226,10 @@ else if(grailBufferType == 2) {

GrailPair[] buffer = null;
int bufferLen = 0;
if(algorithm == 0 || algorithm == 1) {
if(algorithm != 2) {
// Holy Grail Sort with static buffer
if(grailBufferType == 1) {
buffer = (GrailPair[]) Array.newInstance(this.keyArray.getClass().getComponentType(), HolyGrailSort.STATIC_EXT_BUFFER_LEN);
buffer = (GrailPair[]) Array.newInstance(array.getClass().getComponentType(), HolyGrailSort.STATIC_EXT_BUFFER_LEN);
bufferLen = HolyGrailSort.STATIC_EXT_BUFFER_LEN;
}
// Holy Grail Sort with dynamic buffer
Expand All @@ -229,69 +238,67 @@ else if(grailBufferType == 2) {
while((bufferLen * bufferLen) < length) {
bufferLen *= 2;
}
buffer = (GrailPair[]) Array.newInstance(this.keyArray.getClass().getComponentType(), bufferLen);
buffer = (GrailPair[]) Array.newInstance(array.getClass().getComponentType(), bufferLen);
}
}

if(algorithm == 0) {
HolyGrailSort<GrailPair> grail = new HolyGrailSort<>(test);

begin = System.nanoTime();
grail.commonSort(this.keyArray, start, length, buffer, bufferLen);
grail.commonSort(array, start, length, buffer, bufferLen);
time = System.nanoTime() - begin;
} else if (algorithm == 1) {
RewrittenGrailsort<GrailPair> grail = new RewrittenGrailsort<>(test);

begin = System.nanoTime();
grail.grailCommonSort(this.keyArray, start, length, buffer, bufferLen);
grail.grailCommonSort(array, start, length, buffer, bufferLen);
time = System.nanoTime() - begin;
} else {
begin = System.nanoTime();
Arrays.sort(this.keyArray, start, start + length, test);
Arrays.sort(array, start, start + length, test);
time = System.nanoTime() - begin;
}

System.out.print("- Sorted in " + time * 1e-6d + "ms...");
Arrays.sort(this.referenceArray, start, start + length, test);

boolean success = this.testArray(start, length, test);
if(success) {
System.out.print(" and the sort was successful!\n");
this.successes++;
}
else {
System.out.print(" but the sort was NOT successful!!\nReason: " + this.failReason);
this.failures++;
if (algorithm == 2) {
System.out.println(" and the sort was successful!");
} else {
boolean success = this.testArray(start, length, test);
if(success) {
System.out.println(" and the sort was successful!");
this.successes++;
}
else {
System.out.println(" but the sort was NOT successful!!\nReason: " + this.failReason);
this.failures++;
}
this.count++;
}
this.count++;

// Sometimes the garbage collector wasn't cooperating.
Arrays.fill(this.keyArray, null);
Arrays.fill(this.valueArray, null);
Arrays.fill(this.referenceArray, null);
Arrays.fill(this.keyArray, null);
System.gc();
}

private void checkBoth(int start, int length, int keyCount, String grailStrategy, GrailComparator test) {
int tempSeed = this.seed;
this.checkAlgorithm(start, length, keyCount, 2, 0, null, test);

if(!grailStrategy.equals("Opti.Gnome")) {
for(int i = 0; i < 1; i++) {
this.checkAlgorithm(start, length, keyCount, 0, i, grailStrategy, test);
if (RewrittenGrailsort.RGS_CLASS != null) {
this.checkAlgorithm(start, length, keyCount, 1, i, grailStrategy, test);
}
this.seed = tempSeed;
}
}
else {
this.checkAlgorithm(start, length, keyCount, 0, 0, grailStrategy, test);
if (RewrittenGrailsort.RGS_CLASS != null) {
this.checkAlgorithm(start, length, keyCount, 1, 0, grailStrategy, test);
}
this.seed = tempSeed;
}

this.checkAlgorithm(start, length, keyCount, 2, 0, null, test);
Arrays.fill(this.referenceArray, null);
System.gc();
}

public static void main(String[] args) {
Expand All @@ -305,6 +312,10 @@ public static void main(String[] args) {

for(int u = 5; u <= (maxLength / 100); u *= 10) {
for(int v = 2; v <= u && v <= (maxKeyCount / 100); v *= 2) {
int tempSeed = tester.seed;
tester.generateTestArray(tester.referenceArray, 0, u, v - 1);
tester.seed = tempSeed;
Arrays.sort(tester.referenceArray, 0, u, testCompare);
for(int i = 0; i < 1; i++) {
tester.checkAlgorithm(0, u, v - 1, 0, i, "All Strategies", testCompare);
}
Expand Down

0 comments on commit a0fe48f

Please sign in to comment.