Skip to content

Commit

Permalink
much improved key sorting
Browse files Browse the repository at this point in the history
special thanks to Control (https://github.com/Control55)
  • Loading branch information
MusicTheorist committed Oct 20, 2021
1 parent f56b9d1 commit 04d4626
Showing 1 changed file with 33 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,29 @@ private void mergeBlocksBackwardsOutOfPlace(T[] array, int firstKey, T medianKey
System.arraycopy(array, start, array, start + blockLen, this.currBlockLen);
}

// a novel, elegant, and incredibly efficient 1.5 sqrt n key sort, courtesy of Control
// only works if a) median key is known and b) keys were permutated by "sortBlocks"
// (keys < medianKey and >= medianKey are each in relative sorted order, resembling a final radix sort pass)
private static <T> void sortKeys(T[] array, int firstKey, T medianKey, int keyCount, int buffer, Comparator<T> cmp) {
int currKey = firstKey;
int bufferSwaps = 0;

while(currKey < firstKey + keyCount) {
if(cmp.compare(array[currKey], medianKey) < 0) {
if(bufferSwaps != 0) {
swap(array, currKey, currKey - bufferSwaps);
}
}
else {
swap(array, currKey, buffer + bufferSwaps);
bufferSwaps++;
}
currKey++;
}

swapBlocksBackwards(array, currKey - bufferSwaps, buffer, bufferSwaps);
}

private void combineForwards(T[] array, int firstKey, int start, int length, int subarrayLen, int blockLen) {
Comparator<T> cmp = this.cmp; // local variable for performance à la Timsort

Expand Down Expand Up @@ -1347,7 +1370,8 @@ private void combineForwards(T[] array, int firstKey, int start, int length, int
this.mergeBlocksForwards(array, firstKey, medianKey, offset, blockCount, blockLen, 0, 0, cmp);

// TODO: Replace with Control's key sort
insertSort(array, firstKey, blockCount, cmp);
sortKeys(array, firstKey, medianKey, blockCount, offset + mergeLen - blockLen, cmp);
//insertSort(array, firstKey, blockCount, cmp);
}

int offset = start + (fullMerges * mergeLen);
Expand Down Expand Up @@ -1375,7 +1399,8 @@ private void combineForwards(T[] array, int firstKey, int start, int length, int
}

//TODO: Why is this 'blockCount + 1'???
insertSort(array, firstKey, blockCount, cmp);
sortKeys(array, firstKey, medianKey, blockCount, offset + lastSubarrays - blockLen, cmp);
//insertSort(array, firstKey, blockCount, cmp);

if(fullMerges % 2 == 0 && fullMerges != 0) {
swapBlocksBackwards(array, offset - blockLen, offset, lastSubarrays);
Expand Down Expand Up @@ -1503,7 +1528,8 @@ private void combineBackwards(T[] array, int firstKey, int start, int length, in
//TODO: Why is this 'blockCount + 1'???
// We believe this '+ 1' is unnecessary and
// possibly has a *hilarious* origin story
insertSort(array, firstKey, blockCount, cmp);
sortKeys(array, firstKey, medianKey, blockCount, offset, cmp);
//insertSort(array, firstKey, blockCount, cmp);
}
}

Expand All @@ -1515,7 +1541,8 @@ private void combineBackwards(T[] array, int firstKey, int start, int length, in
sortBlocks(array, firstKey, offset, blockCount, leftBlocks, blockLen, true, cmp);
this.mergeBlocksBackwards(array, firstKey, medianKey, offset, blockCount, blockLen, 0, cmp);

insertSort(array, firstKey, blockCount, cmp);
sortKeys(array, firstKey, medianKey, blockCount, offset, cmp);
//insertSort(array, firstKey, blockCount, cmp);
}
}

Expand Down Expand Up @@ -1698,7 +1725,7 @@ private LocalMerge combineBlocks(T[] array, int start, int length, int bufferLen
}
else {
int keyBuffer = keyLen / 2;
insertSort(array, start, keyBuffer, this.cmp);
shellSort(array, start, keyBuffer, this.cmp);

if(extBuffer == null) {
while(keyBuffer >= ((2 * subarrayLen) / keyBuffer)) {
Expand Down Expand Up @@ -1737,7 +1764,7 @@ private LocalMerge combineBlocks(T[] array, int start, int length, int bufferLen
direction = LocalMerge.FORWARDS;
}

insertSort(array, start, keyLen, this.cmp);
shellSort(array, start, keyLen, this.cmp);

while((length - keyLen) > subarrayLen) {
this.lazyCombine(array, start, start + keyLen, length - keyLen,
Expand Down

0 comments on commit 04d4626

Please sign in to comment.