module strassens_matmul;
debug {
static import std;
}
package {
ulong getRowSize(T)(T[][] mat) {
return mat[0].length;
}
ulong getColumnSize(T)(T[][] mat) {
return mat.length;
}
T[][] createMatrix(T)(const ulong rowSize, const ulong columnSize) {
return new T[][](rowSize, columnSize);
}
/// row and column are 0 index-based
T* getPointPtr(T)(T[][] mat, const ulong row, const ulong column) {
return &mat[row][column];
}
T getPointCopy(T)(T[][] mat, const ulong row, const ulong column) {
return mat[row][column];
}
T[][] mulIterative(T)(scope const T[][] mat1, scope const T[][] mat2) {
auto result = createMatrix!T(mat1.getRowSize, mat2.getColumnSize);
foreach (row; 0 .. mat1.getRowSize()) {
foreach (column; 0 .. mat2.getColumnSize()) {
T value;
foreach (i; 0 .. mat1.getRowSize()) {
value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column);
}
*result.getPointPtr(row, column) = value;
}
}
return result;
}
}
void main() {
const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]];
const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]];
const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]];
assert(matA.mulIterative(matB) == matC);
}
bW9kdWxlIHN0cmFzc2Vuc19tYXRtdWw7CgpkZWJ1ZyB7CiAgICBzdGF0aWMgaW1wb3J0IHN0ZDsKfQoKcGFja2FnZSB7CiAgICB1bG9uZyBnZXRSb3dTaXplKFQpKFRbXVtdIG1hdCkgewogICAgICAgIHJldHVybiBtYXRbMF0ubGVuZ3RoOwogICAgfQoKICAgIHVsb25nIGdldENvbHVtblNpemUoVCkoVFtdW10gbWF0KSB7CiAgICAgICAgcmV0dXJuIG1hdC5sZW5ndGg7CiAgICB9CgogICAgVFtdW10gY3JlYXRlTWF0cml4KFQpKGNvbnN0IHVsb25nIHJvd1NpemUsIGNvbnN0IHVsb25nIGNvbHVtblNpemUpIHsKICAgICAgICByZXR1cm4gbmV3IFRbXVtdKHJvd1NpemUsIGNvbHVtblNpemUpOwogICAgfQoKICAgIC8vLyByb3cgYW5kIGNvbHVtbiBhcmUgMCBpbmRleC1iYXNlZAogICAgVCogZ2V0UG9pbnRQdHIoVCkoVFtdW10gbWF0LCBjb25zdCB1bG9uZyByb3csIGNvbnN0IHVsb25nIGNvbHVtbikgewogICAgICAgIHJldHVybiAmbWF0W3Jvd11bY29sdW1uXTsKICAgIH0KCiAgICBUIGdldFBvaW50Q29weShUKShUW11bXSBtYXQsIGNvbnN0IHVsb25nIHJvdywgY29uc3QgdWxvbmcgY29sdW1uKSB7CiAgICAgICAgcmV0dXJuIG1hdFtyb3ddW2NvbHVtbl07CiAgICB9CgogICAgVFtdW10gbXVsSXRlcmF0aXZlKFQpKHNjb3BlIGNvbnN0IFRbXVtdIG1hdDEsIHNjb3BlIGNvbnN0IFRbXVtdIG1hdDIpIHsKICAgICAgICBhdXRvIHJlc3VsdCA9IGNyZWF0ZU1hdHJpeCFUKG1hdDEuZ2V0Um93U2l6ZSwgbWF0Mi5nZXRDb2x1bW5TaXplKTsKICAgICAgICBmb3JlYWNoIChyb3c7IDAgLi4gbWF0MS5nZXRSb3dTaXplKCkpIHsKICAgICAgICAgICAgZm9yZWFjaCAoY29sdW1uOyAwIC4uIG1hdDIuZ2V0Q29sdW1uU2l6ZSgpKSB7CiAgICAgICAgICAgICAgICBUIHZhbHVlOwogICAgICAgICAgICAgICAgZm9yZWFjaCAoaTsgMCAuLiBtYXQxLmdldFJvd1NpemUoKSkgewogICAgICAgICAgICAgICAgICAgIHZhbHVlICs9IG1hdDEuZ2V0UG9pbnRDb3B5KHJvdywgaSkgKiBtYXQyLmdldFBvaW50Q29weShpLCBjb2x1bW4pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKnJlc3VsdC5nZXRQb2ludFB0cihyb3csIGNvbHVtbikgPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQp9Cgp2b2lkIG1haW4oKSB7CiAgICBjb25zdCB1aW50W11bXSBtYXRBID0gW1sxMCwgMjAsIDEwXSwgWzQsIDUsIDZdLCBbMiwgMywgNV1dOwogICAgY29uc3QgdWludFtdW10gbWF0QiA9IFtbMywgMiwgNF0sIFszLCAzLCA5XSwgWzQsIDQsIDJdXTsKICAgIGNvbnN0IHVpbnRbXVtdIG1hdEMgPSBbWzEzMCwgMTIwLCAyNDBdLCBbNTEsIDQ3LCA3M10sIFszNSwgMzMsIDQ1XV07CiAgICBhc3NlcnQobWF0QS5tdWxJdGVyYXRpdmUobWF0QikgPT0gbWF0Qyk7Cn0K
prog.d:30:42: error: template strassens_matmul.getRowSize cannot deduce function from argument types !()(const(uint[][])), candidates are:
auto result = createMatrix!T(mat1.getRowSize, mat2.getColumnSize);
^
prog.d:8:11: note: strassens_matmul.getRowSize(T)(T[][] mat)
ulong getRowSize(T)(T[][] mat) {
^
prog.d:30:59: error: template strassens_matmul.getColumnSize cannot deduce function from argument types !()(const(uint[][])), candidates are:
auto result = createMatrix!T(mat1.getRowSize, mat2.getColumnSize);
^
prog.d:12:11: note: strassens_matmul.getColumnSize(T)(T[][] mat)
ulong getColumnSize(T)(T[][] mat) {
^
prog.d:31:43: error: template strassens_matmul.getRowSize cannot deduce function from argument types !()(const(uint[][])), candidates are:
foreach (row; 0 .. mat1.getRowSize()) {
^
prog.d:8:11: note: strassens_matmul.getRowSize(T)(T[][] mat)
ulong getRowSize(T)(T[][] mat) {
^
prog.d:48:29: error: template instance strassens_matmul.mulIterative!uint error instantiating
assert(matA.mulIterative(matB) == matC);
^
prog.d:48:29: error: function strassens_matmul.mulIterative!uint.mulIterative is not accessible from module strassens_matmul
assert(matA.mulIterative(matB) == matC);
^