faster splitter
qznc via Digitalmars-d
digitalmars-d at puremagic.com
Sat May 28 10:07:37 PDT 2016
On Saturday, 28 May 2016 at 12:47:59 UTC, Andrei Alexandrescu
wrote:
> On 5/28/16 6:56 AM, qznc wrote:
>> The sentinel value is `needleBack+1`, but range elements need
>> not
>> support addition. Finding a sentinel is hard and most
>> certainly requires
>> more assumptions about the ranges.
>
> No need for a sentinel really so long as you first search for
> the last element of the needle, in the haystack.
>
> Allow me to put on the table a simple brute force routine,
> specialized for arrays with copyable elements, no custom
> predicate etc. Far as I can tell it does no redundant work:
A nice one. Here are the numbers I got:
LDC:
std find: 156 ±33
manual find: 117 ±24
qznc find: 114 ±14
Chris find: 135 ±24
Andrei find: 112 ±27
DMD:
std find: 177 ±31
manual find: 140 ±28
qznc find: 102 ±4
Chris find: 165 ±31
Andrei find: 130 ±25
My sentinel idea is to have only one condition branch in the
inner loop. Andrei find still has to `if` in the inner loop. My
inner loop looks like this:
haystack[scout] = cast(typeof(needleBack)) (needleBack+1); //
place sentinel
for (size_t j = scout + 1 - needleLength, k = 0;; ++j, ++k) {
// no condition
if (!binaryFun!pred(haystack[j], needle[k])) { // only
condition
// ... ok in here comes another, but this not as costly
}
}
As long as you are matching the needle, there is only one
condition to check. There is no check for k < needleLength,
because the check always fails for needle[$] aka haystack[scout]
due to the sentinel.
I thought it might be slower, since we need to write to memory
twice instead of only reading. Turns out it is faster.
More information about the Digitalmars-d
mailing list