Combsort comparison

Lutger lutger.blijdestijn at gmail.com
Sun Jun 20 13:25:28 PDT 2010


> // D #3 version
> import std.array: empty, popFront, popFrontN, front;
> import std.range: walkLength, isForwardRange, hasSwappableElements;
> import std.algorithm: swap, binaryFun;
> import std.c.stdlib: malloc;
> import std.c.stdio: printf;
> debug {
>     import std.contracts: enforce;
>     import std.algorithm: sort, equal;
>     import std.array: array;
> }
> 
> void combsort(alias less="a < b", Range)(Range data)
>   if (isForwardRange!Range && hasSwappableElements!Range) {
> 
>     static void combsort_impl(Range data) {
>         enum double SHRINK_FACTOR = 1.247330950103979;
>         int gap = walkLength(data);
>         bool swapped = true;
> 
>         while (gap > 1 || swapped) {
>             if (gap > 1)
>                 gap /= SHRINK_FACTOR;
> 
>             swapped = false;
>             auto right = data;
>             popFrontN(right, gap);
> 
>             for (auto left = data; !right.empty; left.popFront,
>             right.popFront) {
>                 if (binaryFun!less(right.front, left.front)) {
>                     swap(left.front, right.front);
>                     swapped = true;
>                 }
>             }
>         }
>     }

I get about 30% improvement if the inner loop is rewritten to:

foreach (i; 0 .. total - gap) // total was already computed by walkLength
{
    left.popFront;
    right.popFront;
    if (binaryFun!less(right.front, left.front)) {
	swap(left.front, right.front);
	swapped = true;
    }
}

Quite surprising. i don't understand asm well enough to analyse this further.


More information about the Digitalmars-d mailing list