I\'m doing a function that multiplies 2 matrices. The matrices will always have the same number of rows and columns. (2x2, 5x5, 23x23, ...)
When I print it, it doesn
You can solve this problem with dynamic programming using Memoization. It is a term describing an optimization technique where you cache previously computed results, and return the cached result when the same computation is needed again.
let mat1 = [[1, 2, 3], [2, 1, 2]];
let mat2 = [[1, 2], [1, 2], [1, 2]];
function matrixMulti(x, y) {
let saveComputation = {};
let finalMat = [],
length=x.length,
length1 = y[0].length,
length2 = y.length;
for (let i = 0; i < length; i++) {
finalMat.push([]);
for (let j = 0; j < length1; j++) {
finalMat[i][j] = 0;
for (let k = 0; k < length2; k++) {
// check if we already computed this calculation or not
if (saveComputation[y[k][j] + '*' + x[i][k]] || saveComputation[x[i][k] + '*' + y[k][j]]) {
finalMat[i][j] = finalMat[i][j] + saveComputation[y[k][j] + '*' + x[i][k]];
} else {
// save if not computed
saveComputation[x[i][k] + '*' + y[k][j]] = x[i][k] * y[k][j]; // check format below how it is saved.
saveComputation[y[k][j] + '*' + x[i][k]] = x[i][k] * y[k][j];
finalMat[i][j] = finalMat[i][j] + saveComputation[y[k][j] + '*' + x[i][k]];
}
}
}
}
console.log(finalMat);
}
matrixMulti(mat1, mat2);
For the above input value of saveComputation will be
{ '1*1': 1,
'2*1': 2,
'1*2': 2,
'3*1': 3,
'1*3': 3,
'2*2': 4,
'3*2': 6,
'2*3': 6 }
Here's my ES6 soulution with math error handling:
const matrixDot = (A, B) => {
// Math error handling
const matrices = [A, B];
const cols = matrices.map((item) => item[0].length);
if (!matrices.every((item, i) => item.every((row) => row.length === cols[i])))
return console.error('All rows in a matrix must have equal amount of columns');
else if (cols[0] !== B.length)
return console.error(
'Amount of columns in the 1st matrix must match amount of rows in the 2nd matrix'
);
// Calculations
return A.map((rowA) =>
B[0].map((_, colBIndex) =>
rowA.reduce((acc, itemA, rowBIndex) => acc + itemA * B[rowBIndex][colBIndex], 0)
)
);
};
// Example
const A = [
[3, 2, 5],
[6, 4, 1],
];
const B = [
[2, 6],
[5, 3],
[1, 4],
];
console.log(matrixDot(A, B));
// [ [21, 44],
// [33, 52] ]
Here's gist if you want to bookmark it
Hope it helps somebody ;)
If you wanted to go the bonkers route, you could also possibly do something with the vertices transformation in WebGL facilities now available in some modern browsers.
Not really sure if this would work in the same way as one might approach vector transformation in OpenCL (**in fact they're type-equivalent / interoperable), but the general idea is:
adding your values to a buffer
"pretending" it's an array of vertices
transforming en-mass using the GPU engine
retrieving the revised values from the vector
(see demo here) http://www.html5rocks.com/en/tutorials/webgl/webgl_transforms/
Just an alternative to the usual loop-in-loop approach. And to be honest, a bit of a fiddle, given that OpenCL was designed for this kind of thing
Within the OpenCL 1.2 spec vertex buffers from OpenGL can be loaded and transformed using OpenCL (see. https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial)