Update: The following code is now part of the jMath library. The implementation has changed into a structure more like the one described for vectors here. Download
Things have gotten serious for Javascript, too serious for this simple language it seems, but nevertheless it still amazes me what people use it for. One of my next projects need a bit of matrix manipulation, and since I couldn’t find any framework for this, I made a few simple functions:
// A 2d matrix with dim [n,m] with undefined values
function empty(dim) {
var a = new Array(dim[0]);
for (var i=0; i < a.length; i++) {
a[i] = new Array(dim[1]);
};
return new matrix(a);
}
// a 2d matrix with dim [n,m] with zeros on all places
function zeros(dim) {
var a = new empty(dim);
for (var i=0; i < a.rowlength; i++) {
for (var j=0; j < a.columnlength; j++) {
a.mat[i][j] = 0.0;
};
};
return a;
}
// a 2d matrix with ones on all places [n,m]
function ones(dim) {
var a = new empty(dim);
for (var i=0; i < a.rowlength; i++) {
for (var j=0; j < a.columnlength; j++) {
a.mat[i][j] = 1.0;
};
};
return a;
}
// The square identity matrix of rank dim
function eye(dim) {
var a = new zeros([dim, dim]);
for (var i=0; i < a.rowlength; i++) {
a.mat[i][i] = 1
};
return a;
}
function matrix (m) {
// console.log(m.constructor);
if (m.constructor == Array) {
// Get row dimension
this.rowlength = m.length;
// Get column dimension
this.columnlength = m[0].length;
for (var i = m.length - 1; i >= 0; i--){
if (!(m[i].constructor == Array) || !(this.columnlength == m[i].length)) {
console.log("fail");
return "Fail, row: " + i + " not valid.";
};
};
// console.log("The matix has the form: " + this.rowlength + "x" + this.columnlength);
// isSquare?
if (this.rowlength == this.columnlength) this.isSquare = true;
this.mat = m;
// Get Transpose matrix
this.transpose = function() {
var ta = new empty([this.columnlength, this.rowlength]);
for (var i=0; i < this.rowlength; i++) {
for (var j=0; j < this.columnlength; j++) {
ta.mat[j][i] = this.mat[i][j];
};
};
return ta;
};
// Row exchange
this.rowex = function(i,j) {
var tmp = this.mat[i];
this.mat[i] = this.mat[j];
this.mat[j] = tmp;
};
// Row multiplication
this.rowmul = function(row,scalar) {
for (var i=0; i < this.mat[row].length; i++) {
this.mat[row][i] = scalar * this.mat[row][i];
};
};
// Row addition
this.rowadd = function(row,other,scalar) {
for (var i=0; i < this.mat[row].length; i++) {
this.mat[row][i] = this.mat[row][i] + scalar*this.mat[other][i];
};
};
};
}
function print (matrix) {
var html = "|table|";
for (var i=0; i < matrix.rowlength; i++) {
html+= "|tr|";
for (var j=0; j < matrix.columnlength; j++) {
html+= "|td|" + matrix.mat[i][j] + "|/td|";
};
html+="|tr|";
};
html += "|table|";
return html;
}
// Matrix multiplication
function mul (A,B) {
if (B.constructor == matrix && A.constructor == matrix)
if (A.columnlength == B.rowlength) {
var C = new zeros([A.rowlength, B.columnlength]);
// naive alg.
for (var i=0; i < C.rowlength; i++) {
for (var j=0; j < C.columnlength; j++) {
for (var k=0; k < A.columnlength; k++) {
C.mat[i][j] = C.mat[i][j] + A.mat[i][k] * B.mat[k][j];
};
};
};
return C;
} else if (A.constructor == matrix && B.constructor == Number) {
console.log("Warning doing scalar multiplication of A*b");
return scalar(A,B);
} else {
return -1;
}
}
function scalar (A,b) {
var B = new empty([A.rowlength, A.columnlength]);
for (var i=0; i < A.rowlength; i++) {
for (var j=0; j < A.columnlength; j++) {
B.mat[i][j] = A.mat[i][j]*b;
};
};
return B;
}
function add (A,B) {
if (A.columnlength == B.columnlength && A.rowlength == B.rowlength) {
// Add A + B
var C = new empty([A.rowlength, B.columnlength]);
for (var i=0; i < C.rowlength; i++) {
for (var j=0; j < C.columnlength; j++) {
C.mat[i][j] = A.mat[i][j] + B.mat[i][j];
};
};
return C;
} else {
return -1;
}
}
function sub (A,B) {
if (A.columnlength == B.columnlength && A.rowlength == B.rowlength) {
// Add A + B
var C = new empty([A.rowlength, B.columnlength]);
for (var i=0; i < C.rowlength; i++) {
for (var j=0; j < C.columnlength; j++) {
C.mat[i][j] = A.mat[i][j] - B.mat[i][j];
};
};
return C;
} else {
return -1;
}
}
////////// Examples ////////////////
// 2 x 2 Matrix
var A = new matrix([[1,2],
[3,4]]);
console.log(A.mat);
//// Elementary Matrix operations ////
// Exchange row 0 and 1
A.rowex(0,1);
console.log(A.mat);
// Scalar multiply row 0 with 2
A.rowmul(0,2);
console.log(A.mat);
// Add row 1 times -4 to row 0
A.rowadd(0,1,-4);
console.log(A.mat);
// Matrix operations
var B = new matrix([[2,6],
[4,3]]);
// Matrix multiply A and B
var C = mul(A,B)
console.log(C.mat);
// Identity matrix 2x2
var D = eye(2);
console.log(D.mat);
// Transpose A
var B = A.transpose();
console.log(B.mat);
// Matrix multiply A times 2*B
var k = mul(A,scalar(D,2));
console.log(k.mat);
// Html table of A
console.log(print(A));