mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
More timsort bugfixes (seems to work much better now)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35583 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
be1f5c5c15
commit
679dc66bbf
2 changed files with 43 additions and 28 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2012-09-20 Niels Grewe <niels.grewe@halbordnung.de>
|
||||||
|
|
||||||
|
* Source/GSTimSort.m: A few more timsort bugfixes.
|
||||||
|
|
||||||
2012-09-20 Niels Grewe <niels.grewe@halbordnung.de>
|
2012-09-20 Niels Grewe <niels.grewe@halbordnung.de>
|
||||||
|
|
||||||
* Source/GSTimSort.m: Fix bugs in the timsort implementation.
|
* Source/GSTimSort.m: Fix bugs in the timsort implementation.
|
||||||
|
|
|
@ -234,7 +234,7 @@ gallopLeft(id key, id *buf, NSRange r, NSUInteger hint, id descOrComp,
|
||||||
/* In an ascending order, we gallop to the right until the key
|
/* In an ascending order, we gallop to the right until the key
|
||||||
* is no longer greater than the element from the range
|
* is no longer greater than the element from the range
|
||||||
*/
|
*/
|
||||||
NSInteger maxOffset = r.length - hint;
|
NSInteger maxOffset = (r.length - hint);
|
||||||
while (offset < maxOffset)
|
while (offset < maxOffset)
|
||||||
{
|
{
|
||||||
if (NSOrderedAscending
|
if (NSOrderedAscending
|
||||||
|
@ -274,7 +274,6 @@ gallopLeft(id key, id *buf, NSRange r, NSUInteger hint, id descOrComp,
|
||||||
* until the key is no longer less than the element from the range
|
* until the key is no longer less than the element from the range
|
||||||
*/
|
*/
|
||||||
NSInteger maxOffset = hint + 1;
|
NSInteger maxOffset = hint + 1;
|
||||||
|
|
||||||
while (offset < maxOffset)
|
while (offset < maxOffset)
|
||||||
{
|
{
|
||||||
if (NSOrderedAscending
|
if (NSOrderedAscending
|
||||||
|
@ -298,11 +297,16 @@ gallopLeft(id key, id *buf, NSRange r, NSUInteger hint, id descOrComp,
|
||||||
// Restore base address:
|
// Restore base address:
|
||||||
buf -= (hint + r.location);
|
buf -= (hint + r.location);
|
||||||
|
|
||||||
/* We are now sure that we need to insert key somewhere between offset and
|
/*
|
||||||
* lastOffset. So do a binary search with a vastly diminished search space.
|
* We are now sure that we need to insert key somewhere between offset and
|
||||||
|
* lastOffset, though the stride might have been to large for the range.
|
||||||
|
* Fix the range and do a binary search with a vastly diminished search space.
|
||||||
*/
|
*/
|
||||||
|
offset = MIN(offset, NSMaxRange(r));
|
||||||
lastOffset++;
|
if (lastOffset < (NSInteger)r.location)
|
||||||
|
{
|
||||||
|
lastOffset = (NSInteger)r.location;
|
||||||
|
}
|
||||||
while (lastOffset < offset)
|
while (lastOffset < offset)
|
||||||
{
|
{
|
||||||
NSInteger midPoint = lastOffset + ((offset - lastOffset) >> 1);
|
NSInteger midPoint = lastOffset + ((offset - lastOffset) >> 1);
|
||||||
|
@ -363,10 +367,6 @@ gallopRight(id key, id *buf, NSRange r, NSUInteger hint,
|
||||||
{
|
{
|
||||||
offset = maxOffset;
|
offset = maxOffset;
|
||||||
}
|
}
|
||||||
else if (offset < r.location)
|
|
||||||
{
|
|
||||||
offset = r.location;
|
|
||||||
}
|
|
||||||
// Translation to positive offsets against the base address.
|
// Translation to positive offsets against the base address.
|
||||||
k = lastOffset;
|
k = lastOffset;
|
||||||
lastOffset = (r.location + hint) - offset;
|
lastOffset = (r.location + hint) - offset;
|
||||||
|
@ -376,7 +376,7 @@ gallopRight(id key, id *buf, NSRange r, NSUInteger hint,
|
||||||
{
|
{
|
||||||
// In descending (or equal) order, we gallop to the right
|
// In descending (or equal) order, we gallop to the right
|
||||||
|
|
||||||
NSInteger maxOffset = r.length - hint;
|
NSInteger maxOffset = (r.length - hint);
|
||||||
while (offset < maxOffset)
|
while (offset < maxOffset)
|
||||||
{
|
{
|
||||||
if (NSOrderedAscending
|
if (NSOrderedAscending
|
||||||
|
@ -399,14 +399,21 @@ gallopRight(id key, id *buf, NSRange r, NSUInteger hint,
|
||||||
// Restore base address:
|
// Restore base address:
|
||||||
buf -= (hint + r.location);
|
buf -= (hint + r.location);
|
||||||
|
|
||||||
/* We are now sure that we need to insert key somewhere between offset and
|
/*
|
||||||
* lastOffset. So do a binary search with a vastly diminished search space.
|
* We are now sure that we need to insert key somewhere between offset and
|
||||||
|
* lastOffset, though the stride might have been to large for the range.
|
||||||
|
* Fix the range and do a binary search with a vastly diminished search space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lastOffset++;
|
lastOffset++;
|
||||||
|
offset = MIN(offset, NSMaxRange(r));
|
||||||
|
if (lastOffset < (NSInteger)r.location)
|
||||||
|
{
|
||||||
|
lastOffset = (NSInteger)r.location;
|
||||||
|
}
|
||||||
while (lastOffset < offset)
|
while (lastOffset < offset)
|
||||||
{
|
{
|
||||||
NSInteger midPoint = lastOffset + ((offset - lastOffset) >> 1);
|
NSInteger midPoint = lastOffset + ((offset - lastOffset) >> 1);
|
||||||
|
|
||||||
if (NSOrderedAscending
|
if (NSOrderedAscending
|
||||||
== GSCompareUsingDescriptorOrComparator(key, buf[midPoint],
|
== GSCompareUsingDescriptorOrComparator(key, buf[midPoint],
|
||||||
descOrComp, type, context))
|
descOrComp, type, context))
|
||||||
|
@ -606,7 +613,7 @@ descriptorOrComparator: (id)descriptorOrComparator
|
||||||
{
|
{
|
||||||
runStack[stackSize] = r;
|
runStack[stackSize] = r;
|
||||||
stackSize++;
|
stackSize++;
|
||||||
NSDebugMLLog(@"GSTimSort", @"Pushing run: %@\n", NSStringFromRange(r));
|
NSDebugMLLog(@"GSTimSort", @"Pushing run: %@", NSStringFromRange(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) suggestMerge
|
- (void) suggestMerge
|
||||||
|
@ -632,11 +639,15 @@ descriptorOrComparator: (id)descriptorOrComparator
|
||||||
{
|
{
|
||||||
GS_TIMSORT_MERGE_AT_INDEX(self, n);
|
GS_TIMSORT_MERGE_AT_INDEX(self, n);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,7 +1026,7 @@ descriptorOrComparator: (id)descriptorOrComparator
|
||||||
|
|
||||||
r1 = runStack[i];
|
r1 = runStack[i];
|
||||||
r2 = runStack[i+1];
|
r2 = runStack[i+1];
|
||||||
NSDebugMLLog(@"GSTimSort", @"Merging from stack location %lu of %lu (%@ with %@)\n", i,
|
NSDebugMLLog(@"GSTimSort", @"Merging stack location %lu (stack size: %lu, run %@ with %@)", i,
|
||||||
stackSize, NSStringFromRange(r1), NSStringFromRange(r2));
|
stackSize, NSStringFromRange(r1), NSStringFromRange(r2));
|
||||||
|
|
||||||
/* Do some housekeeping on the stack: We combine the two runs
|
/* Do some housekeeping on the stack: We combine the two runs
|
||||||
|
@ -1036,19 +1047,19 @@ descriptorOrComparator: (id)descriptorOrComparator
|
||||||
sortDescriptorOrComparator, comparisonType, functionContext);
|
sortDescriptorOrComparator, comparisonType, functionContext);
|
||||||
r1.length = r1.length - (insert - r1.location);
|
r1.length = r1.length - (insert - r1.location);
|
||||||
r1.location = insert;
|
r1.location = insert;
|
||||||
NSDebugMLLog(@"GSTimSort", @"Insertion point for r2 in r1: %lu.\nr1 for the merge is now %@.\n",
|
|
||||||
insert, NSStringFromRange(r1));
|
|
||||||
if (r1.length == 0)
|
if (r1.length == 0)
|
||||||
{
|
{
|
||||||
// The entire run r2 lies after r1, just return.
|
// The entire run r2 lies after r1, just return.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
NSDebugMLLog(@"GSTimSort", @"Insertion point for r2 in r1: %lu, r1 for the merge is now %@.",
|
||||||
|
insert, NSStringFromRange(r1));
|
||||||
|
|
||||||
// Find an insertion point for the last element of r1 into r2. Subtracting the
|
// Find an insertion point for the last element of r1 into r2. Subtracting the
|
||||||
// location from that point gives us the length of the subrange we need to
|
// location from that point gives us the length of the subrange we need to
|
||||||
// merge.
|
// merge.
|
||||||
r2.length = (gallopLeft(objects[NSMaxRange(r1) - 1], objects, r2,
|
r2.length = (gallopLeft(objects[NSMaxRange(r1) - 1], objects, r2,
|
||||||
(r2.length - 1),
|
(r2.length - 2),
|
||||||
sortDescriptorOrComparator, comparisonType, functionContext)
|
sortDescriptorOrComparator, comparisonType, functionContext)
|
||||||
- r2.location);
|
- r2.location);
|
||||||
if (r2.length == 0)
|
if (r2.length == 0)
|
||||||
|
@ -1131,7 +1142,7 @@ _GSTimSort(id *objects,
|
||||||
/* If the run is too short, coerce it up to minimalRunLen
|
/* If the run is too short, coerce it up to minimalRunLen
|
||||||
* or the end of the sortRange.
|
* or the end of the sortRange.
|
||||||
*/
|
*/
|
||||||
if (runLen < MAX(sortLen, minimalRunLen))
|
if (runLen < MIN(sortLen, minimalRunLen))
|
||||||
{
|
{
|
||||||
NSUInteger coercionLen;
|
NSUInteger coercionLen;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue