D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6514 - dotProduct at compile-time too
Summary: dotProduct at compile-time too
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-08-16 14:00 UTC by bearophile_hugs
Modified: 2011-08-17 11:36 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2011-08-16 14:00:14 UTC
Currently (DMD 2.054) I can't run dotProduct() at compile-time, but small changes allow it too. Not much tested:


/// Ditto
Unqual!(CommonType!(F1, F2))
dotProduct(F1, F2)(in F1[] avector, in F2[] bvector) pure nothrow @system {
    enum size_t big_block_size = 16;
    enum size_t small_block_size = 4;
    //static assert(isPow2(big_block_size)); // isPow2 missing in std.math
    //static assert(isPow2(small_block_size));

    immutable n = avector.length;
    assert(n == bvector.length);
    auto avec = avector.ptr, bvec = bvector.ptr;
    typeof(return) sum0 = 0, sum1 = 0;

    const all_endp = avec + n;
    const smallblock_endp = avec + (n & ~(small_block_size - 1));
    const bigblock_endp = avec + (n & ~(big_block_size - 1));

    for (; avec != bigblock_endp; avec += big_block_size, bvec += big_block_size) {
        sum0 += avec[0] * bvec[0];
        sum1 += avec[1] * bvec[1];
        sum0 += avec[2] * bvec[2];
        sum1 += avec[3] * bvec[3];
        sum0 += avec[4] * bvec[4];
        sum1 += avec[5] * bvec[5];
        sum0 += avec[6] * bvec[6];
        sum1 += avec[7] * bvec[7];
        sum0 += avec[8] * bvec[8];
        sum1 += avec[9] * bvec[9];
        sum0 += avec[10] * bvec[10];
        sum1 += avec[11] * bvec[11];
        sum0 += avec[12] * bvec[12];
        sum1 += avec[13] * bvec[13];
        sum0 += avec[14] * bvec[14];
        sum1 += avec[15] * bvec[15];
    }

    for (; avec != smallblock_endp; avec += small_block_size, bvec += small_block_size) {
        sum0 += avec[0] * bvec[0];
        sum1 += avec[1] * bvec[1];
        sum0 += avec[2] * bvec[2];
        sum1 += avec[3] * bvec[3];
    }

    sum0 += sum1;

    // Do trailing portion in naive loop.
    if (__ctfe) {
        const size_t left = (n % big_block_size) % small_block_size;
        for (size_t i = n - left; i < n; i++)
            sum0 += avec[i] * bvec[i];
    } else {
        while (avec != all_endp)
            sum0 += (*avec++) * (*bvec++);
    }

    return sum0;
}

----------------------------


Note that this block of code:

sum0 += avec[0] * bvec[0];
sum1 += avec[1] * bvec[1];
sum0 += avec[2] * bvec[2];
sum1 += avec[3] * bvec[3];
sum0 += avec[4] * bvec[4];
sum1 += avec[5] * bvec[5];
sum0 += avec[6] * bvec[6];
sum1 += avec[7] * bvec[7];
sum0 += avec[8] * bvec[8];
sum1 += avec[9] * bvec[9];
sum0 += avec[10] * bvec[10];
sum1 += avec[11] * bvec[11];
sum0 += avec[12] * bvec[12];
sum1 += avec[13] * bvec[13];
sum0 += avec[14] * bvec[14];
sum1 += avec[15] * bvec[15];


Equals to something like:

foreach (i; Iota!(big_block_size / 2)) {
    sum0 += avec[2 * i] * bvec[2 * i];
    sum1 += avec[2 * i + 1] * bvec[2 * i + 1];
}

Where Iota is defined in Issue 4085
Comment 1 David Simcha 2011-08-17 05:04:09 UTC
https://github.com/D-Programming-Language/phobos/pull/200

I was curious why dotProduct didn't already work at compile time.  With Don's recent CTFE improvements that allow pointers, the only reason is bug 6517, so I put the trivial workaround in dotProduct.
Comment 2 bearophile_hugs 2011-08-17 05:36:32 UTC
(In reply to comment #1)

> With Don's recent CTFE improvements that allow pointers, the only reason
> is bug 6517, so I put the trivial workaround in dotProduct.

Thank you.