Skip to content

Commit

Permalink
Fix Issue 6657 - dotProduct overload for small fixed size arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
n8sh committed May 3, 2019
1 parent 595a290 commit 7804b9c
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions std/numeric.d
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,59 @@ dotProduct(F1, F2)(in F1[] avector, in F2[] bvector)
return sum0;
}

/// ditto
F dotProduct(F, uint N)(const ref scope F[N] a, const ref scope F[N] b)
if (N <= 16)
{
static if (__traits(isIntegral, F) && N >= 4)
{
// With LDC this is much faster for `int` and `long` but slower
// for `float` and `double`. (About 1.28x speed for integers at
// N=4, about 1.81x at N=8, and about 2.65x at N=16.)
// With DMD for `int` and `long` this is about the same
// speed as the other branch.
F sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
static foreach (i; 0 .. N / 4)
{
sum0 += a[i*2] * b[i*2];
sum1 += a[i*2+1] * b[i*2+1];
sum2 += a[i*3] * b[i*3];
sum3 += a[i*3+1] * b[i*3+1];
}
static if (N % 4 == 3)
{
sum0 += a[N-3] * b[N-3];
sum1 += a[N-2] * b[N-2];
sum2 += a[N-1] * b[N-1];
}
else static if (N % 4 == 2)
{
sum0 += a[N-2] * b[N-2];
sum1 += a[N-1] * b[N-1];
}
else static if (N % 4 == 1)
{
sum0 += a[N-1] * b[N-1];
}
return sum0 + sum1 + sum2 + sum3;
}
else
{
F sum0 = 0;
F sum1 = 0;
static foreach (i; 0 .. N / 2)
{
sum0 += a[i*2] * b[i*2];
sum1 += a[i*2+1] * b[i*2+1];
}
static if (N % 2 == 1)
{
sum0 += a[N-1] * b[N-1];
}
return sum0 + sum1;
}
}

@system unittest
{
// @system due to dotProduct and assertCTFEable
Expand All @@ -1785,7 +1838,31 @@ dotProduct(F1, F2)(in F1[] avector, in F2[] bvector)
T[] b = [ 4.0, 6.0, ];
assert(dotProduct(a, b) == 16);
assert(dotProduct([1, 3, -5], [4, -2, -1]) == 3);
// Test with fixed-length arrays.
T[2] c = [ 1.0, 2.0, ];
T[2] d = [ 4.0, 6.0, ];
assert(dotProduct(c, d) == 16);
T[3] e = [1, 3, -5];
T[3] f = [4, -2, -1];
assert(dotProduct(e, f) == 3);
}}
// Test optimization for fixed-length integer arrays.
{
const int[7] a7 = [1, 2, 3, 4, 5, 6, 7];
const int[6] a6 = a[0 .. 6];
const int[5] a5 = a[0 .. 5];
const int[4] a4 = a[0 .. 4];

const int[7] b7 = [8, 9, 10, 11, 12, 13, 14];
const int[6] b6 = b[0 .. 6];
const int[5] b5 = b[0 .. 5];
const int[4] b4 = b[0 .. 4];

assert(dotProduct(a7, b7) == 336);
assert(dotProduct(a6, b6) == 238);
assert(dotProduct(a5, b5) == 160);
assert(dotProduct(a4, b4) == 100);
}

// Make sure the unrolled loop codepath gets tested.
static const x =
Expand Down

0 comments on commit 7804b9c

Please sign in to comment.