On Sunday, 11 January 2015 at 18:01:09 UTC, bearophile wrote:
Nordlöw:

Is doCopy really needed as an argument here?

Couldn't this be inferred from the mutability of T instead?

doCopy is useful, if it's true all the permutation arrays are distinct and dup-ped, otherwise they are all different. It's true by default, so casual users of that generator will avoid bugs. You can set it to false to speed up your code.


Later I have refined the idea, you can see it here, that allows true @nogc code when needed:

struct CartesianPower(bool doCopy=true, T) {
    T[] items;
    uint repeat;
    T[] row;
    uint i, maxN;

this(T[] items_, in uint repeat_, T[] buffer) pure nothrow @safe @nogc {
        this.items = items_;
        this.repeat = repeat_;
        row = buffer[0 .. repeat];
        row[] = items[0];
        maxN = items.length ^^ repeat;
    }

    static if (doCopy) {
        @property T[] front() pure nothrow @safe @nogc {
            return row.dup;
        }
    } else {
        @property T[] front() pure nothrow @safe @nogc {
            return row;
        }
    }

    @property bool empty() pure nothrow @safe @nogc {
        return i >= maxN;
    }

    void popFront() pure nothrow @safe @nogc {
        i++;
        if (empty)
            return;
        uint n = i;
        size_t count = repeat - 1;
        while (n) {
            row[count] = items[n % items.length];
            count--;
            n /= items.length;
        }
    }
}

auto cartesianPower(bool doCopy=true, T)(T[] items, in uint repeat)
pure nothrow @safe {
return CartesianPower!(doCopy, T)(items, repeat, new T[repeat]);
}

auto cartesianPower(bool doCopy=true, T)(T[] items, in uint repeat, T[] buffer)
pure nothrow @safe @nogc {
    if (buffer.length >= repeat) {
return CartesianPower!(doCopy, T)(items, repeat, buffer);
    } else {
        // Is this correct in presence of chaining?
static immutable err = new Error("buffer.length < repeat");
        throw err;
    }
}

void main() @nogc {
    import core.stdc.stdio;
    int[3] items = [10, 20, 30];
    int[4] buf;
    foreach (p; cartesianPower!false(items, 4, buf))
        printf("(%d, %d, %d, %d)\n", p[0], p[1], p[2], p[3]);
}


Bye,
bearophile

Nice! PR anyone?

Reply via email to