fix issue_15421 [reloaded] - The behaviours of the topNs differ with the bottom#4928
fix issue_15421 [reloaded] - The behaviours of the topNs differ with the bottom#4928andralex merged 1 commit intodlang:masterfrom
Conversation
|
Actually, there already is an issue for what is happening with the DummyRange test: This code example here produces the exact same errors as the DummyRange test: |
|
|
Requires #4929 for tests to pass (fixes dup errors) |
andralex
left a comment
There was a problem hiding this comment.
Thanks for doing this. A few adjustments and we should be good to go.
std/algorithm/sorting.d
Outdated
| if (heap.conditionalInsert(e)) | ||
| { | ||
| e = hf; | ||
| } |
There was a problem hiding this comment.
OK I see what you're doing here. This works but it's inefficient because it does a bunch of assignments, many of which are unnecessary. The root cause seems to be the API conditionalInsert. How about we do this - add this method to BinaryHeap:
bool conditionalSwap(ref ElementType!Store value);
The ref is important here. The method will conditionally swap value into the heap, and will swap the "lost" element of the heap into value. Then this loop only needs to run
foreach (ref e; r2)
{
heap.conditionalSwap(e);
}
std/container/binaryheap.d
Outdated
| { | ||
| auto t1 = store[].moveFront(); | ||
| auto t2 = store[].moveBack(); | ||
| } |
There was a problem hiding this comment.
There's a lot of subtle duplication here and in the similar code that follows. Why is there a need to use store if the range is random access and store[] otherwise? Is it concerning a statically-sized array thing?
Anyhow, to fix this without duplication, put the conditional in a method:
auto storeRange()
{
static if(isRandomAccessRange!Store)
return store[];
else
return store;
}
Then use storeRange throughout (and get used to write calls without parens, regardless of all answers you'll see to this comment :o)).
std/container/binaryheap.d
Outdated
| if (store.length == 1) return; | ||
| auto t1 = store[].moveFront(); | ||
| auto t2 = store[].moveBack(); | ||
| static if(isRandomAccessRange!Store) |
There was a problem hiding this comment.
space after if. @CyberShadow do we catch that automatically yet?
There was a problem hiding this comment.
space after if. @CyberShadow do we catch that automatically yet?
@wilzbach would know, ping
We do, but our automatic style checking got disabled this autumn -> #4850
std/container/binaryheap.d
Outdated
| auto frontCopy = _store.front; | ||
| if (!comp(value, _store.front)) return false; // value >= largest | ||
| _store.front = value; | ||
| value = frontCopy; |
There was a problem hiding this comment.
The point here is to use the swap primitive instead of assignment (it's cheap and nothrow). So the code would go:
if (!comp(value, _store.front)) return false; // value >= largest
swap(_store.front, value);
std/container/binaryheap.d
Outdated
| _payload.refCountedStore.ensureInitialized(); | ||
| if (_length < _store.length) | ||
| { | ||
| insert(value); |
There was a problem hiding this comment.
I have no idea what the behavior should be if the heap has room to grow. The problem here is we collapse together the case when the heap is full and we swap an element with another, with the case when the heap is still growing.
Let's do this for now: assert(_length == _store.length) in the code, and mention that it is a precondition that the heap is fully occupied. The advantage of this is that we later get to define this behavior if needed; whereas if we define it the wrong way now, we cannot change it later.
There was a problem hiding this comment.
Sounds goods, thanks!
|
OK, very nice. Could you please squash all your commits into one? Then it's ready for merging. Thanks! |
|
@somzzz please rebase |
a989630 to
aa0f713
Compare
|
@somzzz you have a typo in the Git commit message. That's why the Dlang bot can't link the issue and thus automatically close it (and do other stuff with it like including it within the release log). |
|
@wilzbach is it the issue number? Is there anything I can do to change it now that the PR was merged? |
|
@somzzz that's for the future, for now I closed the issue so everything's in order. |
I rebased #3865 which seems abandoned.
The test for ranges still fails unless I use the cheat to transform the range to an array before passing it to topN and sort (which defeats the purpose of the test actually). It might be a problem with DummyRange, I'm still looking into it, but ideas are welcome.
https://issues.dlang.org/show_bug.cgi?id=15421