<!doctype html>

<html>
  <head>
    <link rel="stylesheet" href="lib/style.css">
    <script src="lib/script.js"></script>
  </head>

  <body>
    <h1>matrix multiplication performance test!</h1>
    <h2>Long running script, 400000 matrix multiplications per method.</h2>
    </h3>results in msec returned below:</h3>
    <p><span id="state-msg"></span></p>
  </body>
</html>
{
  "plnkr": {
    "runtime": "system"
  }
}
/* Add your styles here */

var numberOfMatrices = 400000;
var arrayMatrix = [];
var baseMatrix = [];
var msg = document.getElementById('state-msg');
msg.setAttribute('style', 'white-space: pre;');

var matrixIdentity = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];

//------------------------------------------------------------------------------

var buildRandomMatrices = function(amount){

  for(var i = 0; i < amount; i++){
    var tempMatrix = [];
    copyVertexArray(tempMatrix, matrixIdentity);
    randomizeMatrix(tempMatrix);
    arrayMatrix.push(tempMatrix);
  }
};

var randomizeMatrix = function(matrixDestination){
	matrixDestination[0][0] = Math.random(); matrixDestination[0][1] = Math.random(); matrixDestination[0][2] = Math.random(); matrixDestination[0][3] = Math.random();
	matrixDestination[1][0] = Math.random(); matrixDestination[1][1] = Math.random(); matrixDestination[1][2] = Math.random(); matrixDestination[1][3] = Math.random();
  matrixDestination[2][0] = Math.random(); matrixDestination[2][1] = Math.random(); matrixDestination[2][2] = Math.random(); matrixDestination[2][3] = Math.random();
  matrixDestination[3][0] = Math.random(); matrixDestination[3][1] = Math.random(); matrixDestination[3][2] = Math.random(); matrixDestination[3][3] = Math.random();
};

var copyVertexArray = function(arrayDest, arraySrc){
  //For each element of the source array
  for(var i = 0; i < arraySrc.length; i++){
  	var temp = new Array();
    //Copy the inner array values.
    for(var j = 0; j < arraySrc[i].length; j++){
    	temp.push(arraySrc[i][j]);
    }
    arrayDest.push(temp);
  }
}

var multMatrixMatrixLoop = function(matrixSol, matrixA, matrixB){
  for(var i = 0; i < 4; i++){
    for(var j = 0; j < 4; j++){
      matrixSol[i][j] = (matrixA[i][0] * matrixB[0][j]) + (matrixA[i][1] * matrixB[1][j]) + (matrixA[i][2] * matrixB[2][j]) + (matrixA[i][3] * matrixB[3][j]);
    }
  }
};

//unrolled
var multMatrixMatrixUnrolled = function(matrixSol, matrixA, matrixB){
  //0
  matrixSol[0][0] = (matrixA[0][0] * matrixB[0][0]) + (matrixA[0][1] * matrixB[1][0]) + (matrixA[0][2] * matrixB[2][0]) + (matrixA[0][3] * matrixB[3][0]);
  matrixSol[0][1] = (matrixA[0][0] * matrixB[0][1]) + (matrixA[0][1] * matrixB[1][1]) + (matrixA[0][2] * matrixB[2][1]) + (matrixA[0][3] * matrixB[3][1]);
  matrixSol[0][2] = (matrixA[0][0] * matrixB[0][2]) + (matrixA[0][1] * matrixB[1][2]) + (matrixA[0][2] * matrixB[2][2]) + (matrixA[0][3] * matrixB[3][2]);
  matrixSol[0][3] = (matrixA[0][0] * matrixB[0][3]) + (matrixA[0][1] * matrixB[1][3]) + (matrixA[0][2] * matrixB[2][3]) + (matrixA[0][3] * matrixB[3][3]);
  //1
  matrixSol[1][0] = (matrixA[1][0] * matrixB[0][0]) + (matrixA[1][1] * matrixB[1][0]) + (matrixA[1][2] * matrixB[2][0]) + (matrixA[1][3] * matrixB[3][0]);
  matrixSol[1][1] = (matrixA[1][0] * matrixB[0][1]) + (matrixA[1][1] * matrixB[1][1]) + (matrixA[1][2] * matrixB[2][1]) + (matrixA[1][3] * matrixB[3][1]);
  matrixSol[1][2] = (matrixA[1][0] * matrixB[0][2]) + (matrixA[1][1] * matrixB[1][2]) + (matrixA[1][2] * matrixB[2][2]) + (matrixA[1][3] * matrixB[3][2]);
  matrixSol[1][3] = (matrixA[1][0] * matrixB[0][3]) + (matrixA[1][1] * matrixB[1][3]) + (matrixA[1][2] * matrixB[2][3]) + (matrixA[1][3] * matrixB[3][3]);
  //2
  matrixSol[2][0] = (matrixA[2][0] * matrixB[0][0]) + (matrixA[2][1] * matrixB[1][0]) + (matrixA[2][2] * matrixB[2][0]) + (matrixA[2][3] * matrixB[3][0]);
  matrixSol[2][1] = (matrixA[2][0] * matrixB[0][1]) + (matrixA[2][1] * matrixB[1][1]) + (matrixA[2][2] * matrixB[2][1]) + (matrixA[2][3] * matrixB[3][1]);
  matrixSol[2][2] = (matrixA[2][0] * matrixB[0][2]) + (matrixA[2][1] * matrixB[1][2]) + (matrixA[2][2] * matrixB[2][2]) + (matrixA[2][3] * matrixB[3][2]);
  matrixSol[2][3] = (matrixA[2][0] * matrixB[0][3]) + (matrixA[2][1] * matrixB[1][3]) + (matrixA[2][2] * matrixB[2][3]) + (matrixA[2][3] * matrixB[3][3]);
  //3
  matrixSol[3][0] = (matrixA[3][0] * matrixB[0][0]) + (matrixA[3][1] * matrixB[1][0]) + (matrixA[3][2] * matrixB[2][0]) + (matrixA[3][3] * matrixB[3][0]);
  matrixSol[3][1] = (matrixA[3][0] * matrixB[0][1]) + (matrixA[3][1] * matrixB[1][1]) + (matrixA[3][2] * matrixB[2][1]) + (matrixA[3][3] * matrixB[3][1]);
  matrixSol[3][2] = (matrixA[3][0] * matrixB[0][2]) + (matrixA[3][1] * matrixB[1][2]) + (matrixA[3][2] * matrixB[2][2]) + (matrixA[3][3] * matrixB[3][2]);
  matrixSol[3][3] = (matrixA[3][0] * matrixB[0][3]) + (matrixA[3][1] * matrixB[1][3]) + (matrixA[3][2] * matrixB[2][3]) + (matrixA[3][3] * matrixB[3][3]);
};

var multMatrixMatrixLocalVars1 = function(matrixSol, matrixA, matrixB){
  //0
  var tempA00 = matrixA[0][0]; var tempA01 = matrixA[0][1]; var tempA02 = matrixA[0][2]; var tempA03 = matrixA[0][3]; 
  matrixSol[0][0] = (tempA00 * matrixB[0][0]) + (tempA01 * matrixB[1][0]) + (tempA02 * matrixB[2][0]) + (tempA03 * matrixB[3][0]);
  matrixSol[0][1] = (tempA00 * matrixB[0][1]) + (tempA01 * matrixB[1][1]) + (tempA02 * matrixB[2][1]) + (tempA03 * matrixB[3][1]);
  matrixSol[0][2] = (tempA00 * matrixB[0][2]) + (tempA01 * matrixB[1][2]) + (tempA02 * matrixB[2][2]) + (tempA03 * matrixB[3][2]);
  matrixSol[0][3] = (tempA00 * matrixB[0][3]) + (tempA01 * matrixB[1][3]) + (tempA02 * matrixB[2][3]) + (tempA03 * matrixB[3][3]);
  //1
  var tempA10 = matrixA[1][0]; var tempA11 = matrixA[1][1]; var tempA12 = matrixA[1][2]; var tempA13 = matrixA[1][3]; 
  matrixSol[1][0] = (tempA10 * matrixB[0][0]) + (tempA11 * matrixB[1][0]) + (tempA12 * matrixB[2][0]) + (tempA13 * matrixB[3][0]);
  matrixSol[1][1] = (tempA10 * matrixB[0][1]) + (tempA11 * matrixB[1][1]) + (tempA12 * matrixB[2][1]) + (tempA13 * matrixB[3][1]);
  matrixSol[1][2] = (tempA10 * matrixB[0][2]) + (tempA11 * matrixB[1][2]) + (tempA12 * matrixB[2][2]) + (tempA13 * matrixB[3][2]);
  matrixSol[1][3] = (tempA10 * matrixB[0][3]) + (tempA11 * matrixB[1][3]) + (tempA12 * matrixB[2][3]) + (tempA13 * matrixB[3][3]);
  //2
  var tempA20 = matrixA[2][0]; var tempA21 = matrixA[2][1]; var tempA22 = matrixA[2][2]; var tempA23 = matrixA[2][3]; 
  matrixSol[2][0] = (tempA20 * matrixB[0][0]) + (tempA21 * matrixB[1][0]) + (tempA22 * matrixB[2][0]) + (tempA23 * matrixB[3][0]);
  matrixSol[2][1] = (tempA20 * matrixB[0][1]) + (tempA21 * matrixB[1][1]) + (tempA22 * matrixB[2][1]) + (tempA23 * matrixB[3][1]);
  matrixSol[2][2] = (tempA20 * matrixB[0][2]) + (tempA21 * matrixB[1][2]) + (tempA22 * matrixB[2][2]) + (tempA23 * matrixB[3][2]);
  matrixSol[2][3] = (tempA20 * matrixB[0][3]) + (tempA21 * matrixB[1][3]) + (tempA22 * matrixB[2][3]) + (tempA23 * matrixB[3][3]);
  //3
  var tempA30 = matrixA[3][0]; var tempA31 = matrixA[3][1]; var tempA32 = matrixA[3][2]; var tempA33 = matrixA[3][3]; 
  matrixSol[3][0] = (tempA30 * matrixB[0][0]) + (tempA31 * matrixB[1][0]) + (tempA32 * matrixB[2][0]) + (tempA33 * matrixB[3][0]);
  matrixSol[3][1] = (tempA30 * matrixB[0][1]) + (tempA31 * matrixB[1][1]) + (tempA32 * matrixB[2][1]) + (tempA33 * matrixB[3][1]);
  matrixSol[3][2] = (tempA30 * matrixB[0][2]) + (tempA31 * matrixB[1][2]) + (tempA32 * matrixB[2][2]) + (tempA33 * matrixB[3][2]);
  matrixSol[3][3] = (tempA30 * matrixB[0][3]) + (tempA31 * matrixB[1][3]) + (tempA32 * matrixB[2][3]) + (tempA33 * matrixB[3][3]);
};

var multMatrixMatrixLocalVars2 = function(matrixSol, matrixA, matrixB){
  var tempB00 = matrixB[0][0]; var tempB01 = matrixB[0][1]; var tempB02 = matrixB[0][2]; var tempB03 = matrixB[0][3];
	var tempB10 = matrixB[1][0]; var tempB11 = matrixB[1][1]; var tempB12 = matrixB[1][2]; var tempB13 = matrixB[1][3];
  var tempB20 = matrixB[2][0]; var tempB21 = matrixB[2][1]; var tempB22 = matrixB[2][2]; var tempB23 = matrixB[2][3];
  var tempB30 = matrixB[3][0]; var tempB31 = matrixB[3][1]; var tempB32 = matrixB[3][2]; var tempB33 = matrixB[3][3];
  //0
  var tempA00 = matrixA[0][0]; var tempA01 = matrixA[0][1]; var tempA02 = matrixA[0][2]; var tempA03 = matrixA[0][3]; 
  matrixSol[0][0] = (tempA00 * tempB00) + (tempA01 * tempB10) + (tempA02 * tempB20) + (tempA03 * tempB30);
  matrixSol[0][1] = (tempA00 * tempB01) + (tempA01 * tempB11) + (tempA02 * tempB21) + (tempA03 * tempB31);
  matrixSol[0][2] = (tempA00 * tempB02) + (tempA01 * tempB12) + (tempA02 * tempB22) + (tempA03 * tempB32);
  matrixSol[0][3] = (tempA00 * tempB03) + (tempA01 * tempB13) + (tempA02 * tempB23) + (tempA03 * tempB33);
  //1
  var tempA10 = matrixA[1][0]; var tempA11 = matrixA[1][1]; var tempA12 = matrixA[1][2]; var tempA13 = matrixA[1][3]; 
  matrixSol[1][0] = (tempA10 * tempB00) + (tempA11 * tempB10) + (tempA12 * tempB20) + (tempA13 * tempB30);
  matrixSol[1][1] = (tempA10 * tempB01) + (tempA11 * tempB11) + (tempA12 * tempB21) + (tempA13 * tempB31);
  matrixSol[1][2] = (tempA10 * tempB02) + (tempA11 * tempB12) + (tempA12 * tempB22) + (tempA13 * tempB32);
  matrixSol[1][3] = (tempA10 * tempB03) + (tempA11 * tempB13) + (tempA12 * tempB23) + (tempA13 * tempB33);
  //2
  var tempA20 = matrixA[2][0]; var tempA21 = matrixA[2][1]; var tempA22 = matrixA[2][2]; var tempA23 = matrixA[2][3]; 
  matrixSol[2][0] = (tempA20 * tempB00) + (tempA21 * tempB10) + (tempA22 * tempB20) + (tempA23 * tempB30);
  matrixSol[2][1] = (tempA20 * tempB01) + (tempA21 * tempB11) + (tempA22 * tempB21) + (tempA23 * tempB31);
  matrixSol[2][2] = (tempA20 * tempB02) + (tempA21 * tempB12) + (tempA22 * tempB22) + (tempA23 * tempB32);
  matrixSol[2][3] = (tempA20 * tempB03) + (tempA21 * tempB13) + (tempA22 * tempB23) + (tempA23 * tempB33);
  //3
  var tempA30 = matrixA[3][0]; var tempA31 = matrixA[3][1]; var tempA32 = matrixA[3][2]; var tempA33 = matrixA[3][3]; 
  matrixSol[3][0] = (tempA30 * tempB00) + (tempA31 * tempB10) + (tempA32 * tempB20) + (tempA33 * tempB30);
  matrixSol[3][1] = (tempA30 * tempB01) + (tempA31 * tempB11) + (tempA32 * tempB21) + (tempA33 * tempB31);
  matrixSol[3][2] = (tempA30 * tempB02) + (tempA31 * tempB12) + (tempA32 * tempB22) + (tempA33 * tempB32);
  matrixSol[3][3] = (tempA30 * tempB03) + (tempA31 * tempB13) + (tempA32 * tempB23) + (tempA33 * tempB33);
};

copyVertexArray(baseMatrix, matrixIdentity);
//randomizeMatrix(tempMatrix);

buildRandomMatrices(numberOfMatrices);

msg.textContent = "\r\nloop\r\n";
for(var j = 0; j < 10; j++){
  var startTime = Date.now();

  for(var i = 0; i < numberOfMatrices; i++){
    multMatrixMatrixLoop(baseMatrix, arrayMatrix[0], arrayMatrix[i])
  }

  var endTime = Date.now();

  msg.textContent += (endTime - startTime).toString() + ", ";
}

msg.textContent += "\r\nunrolled\r\n";
for(var j = 0; j < 10; j++){
  var startTime = Date.now();

  for(var i = 0; i < numberOfMatrices; i++){
    multMatrixMatrixUnrolled(baseMatrix, arrayMatrix[0], arrayMatrix[i])
  }

  var endTime = Date.now();

  msg.textContent += (endTime - startTime).toString() + ", ";
}

msg.textContent += "\r\nlocal1\r\n";
for(var j = 0; j < 10; j++){
  var startTime = Date.now();

  for(var i = 0; i < numberOfMatrices; i++){
    multMatrixMatrixLocalVars1(baseMatrix, arrayMatrix[0], arrayMatrix[i])
  }

  var endTime = Date.now();

  msg.textContent += (endTime - startTime).toString() + ", ";
}

msg.textContent += "\r\nlocal2\r\n";
for(var j = 0; j < 10; j++){
  var startTime = Date.now();

  for(var i = 0; i < numberOfMatrices; i++){
    multMatrixMatrixLocalVars2(baseMatrix, arrayMatrix[0], arrayMatrix[i])
  }

  var endTime = Date.now();

  msg.textContent += (endTime - startTime).toString() + ", ";
}