you end instantiating many times the same template, inflating the binary with little purpose (because you are not very interested in the optimizations performed on the compile-time-known values).

I know you want a simple example:


import std.stdio, std.string, std.conv, std.numeric,
       std.array, std.algorithm, std.traits;

template TMMul(M1, M2) { // helper
alias Unqual!(typeof(M1[0][0]))[M2[0].length][M1.length] TMMul;
}

void matrixMul(T, T2, size_t k, size_t m, size_t n)
              (const ref T[m][k] A, const ref T[n][m] B,
               /*out*/ ref T2[n][k] result) pure nothrow
if (is(T2 == Unqual!T)) {
    T2[m] aux;
    foreach (j; 0 .. n) {
        foreach (k, row; B)
            aux[k] = row[j];
        foreach (i, ai; A)
            result[i][j] = dotProduct(ai, aux);
    }
}

void main() {
    immutable int[2][3] a = [[1, 2], [3, 4], [3, 6]];
    immutable int[3][2] b = [[-3, -8, 3,], [-2, 1, 4]];

    enum form = "[%([%(%d, %)],\n %)]]";
    writefln("A = \n" ~ form ~ "\n", a);
    writefln("B = \n" ~ form ~ "\n", b);
    TMMul!(typeof(a), typeof(b)) result = void;
    matrixMul(a, b, result);
    writefln("A * B = \n" ~ form, result);
}



Here a new matrixMul is instantiated for each size of the input matrices, but this avoids that:

void matrixMul(T, T2, @generic size_t k, @generic size_t m, @generic size_t n)
              (const ref T[m][k] A, const ref T[n][m] B,
               /*out*/ ref T2[n][k] result) pure nothrow

Bye,
bearophile

Reply via email to