# Matrix

#####

declaration
Matrix

The matrix implementation of MathLib makes calculations with matrices of
arbitrary size possible. The entries of a matrix can be numbers and complex
numbers.

It is as easy as

    new MathLib.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

to create the following matrix:
⎛ 1 2 3 ⎞
⎜ 4 5 6 ⎟
⎝ 7 8 9 ⎠

    var Matrix = (function () {
    		function Matrix (matrix) {
    			var _this = this;
    			this.type = 'matrix';
    			if (typeof matrix === 'string') {
    				// If there is a < in the string we assume it's MathML
    				if (matrix.indexOf('<') > -1) {
    					return MathLib.Expression.parseContentMathML(matrix).evaluate();
    				}
    				else {
    					matrix = matrix.trim().replace(/;?\n/g, '],[');
    					matrix = JSON.parse('[[' + matrix + ']]');
    				}
    			}
    			matrix.forEach(function (x, i) {
    				_this[i] = x;
    			});
    			this.length = matrix.length;
    			this.cols = matrix[0].length;
    			this.rows = matrix.length;
    		}

# LU

#####

method
Matrix.prototype.LU() → Matrix

Calculates the LU decomposition of a matrix
The result is cached.

    Matrix.prototype.LU = function () {
    			var i, j, k, t, p, LU = this.toArray(), m = this.rows, n = this.cols, permutation = [];

    			for (k = 0; k < n; k++) {
    				// Find the pivot
    				p = k;
    				for (i = k + 1; i < m; i++) {
    					if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
    						p = i;
    					}
    				}

    				// Exchange if necessary
    				if (p !== k) {
    					permutation.unshift([p, k]);
    					t = LU[p];
    					LU[p] = LU[k];
    					LU[k] = t;
    				}

    				// The elimination
    				if (LU[k][k] !== 0) {
    					for (i = k + 1; i < m; i++) {
    						LU[i][k] = MathLib.divide(LU[i][k], LU[k][k]);
    						for (j = k + 1; j < n; j++) {
    							LU[i][j] = MathLib.minus(LU[i][j], MathLib.times(LU[i][k], LU[k][j]));
    						}
    					}
    				}
    			}
    			LU = new MathLib.Matrix(LU);
    			this.LU = function () {
    				return LU;
    			};
    			this.LUpermutation = new MathLib.Permutation(permutation);
    			return LU;
    		};

# adjoint

#####

method
Matrix.prototype.adjoint() → Matrix

Calculates the adjoint matrix

    Matrix.prototype.adjoint = function () {
    			return this.map(function (entry) {
    				return MathLib.conjugate(entry);
    			}).transpose();
    		};

# adjugate

#####

method
Matrix.prototype.adjugate() → Matrix

Calculates the adjugate matrix

    Matrix.prototype.adjugate = function () {
    			return this.map(function (x, r, c, m) {
    				return MathLib.times(m.remove(c, r).determinant(), 1 - ((r + c) % 2) * 2);
    			});
    		};

# cholesky

#####

method
Matrix.prototype.cholesky() → Matrix

The cholesky decomposition of a matrix
using the Cholesky–Banachiewicz algorithm.
Does not change the current matrix, but returns a new one.
The result is cached.

    Matrix.prototype.cholesky = function () {
    			var i, ii, j, jj, k, kk, sum, choleskyMatrix, cholesky = [];

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				cholesky.push([]);
    			}

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				for (j = 0; j < i; j++) {
    					sum = 0;
    					for (k = 0, kk = j; k < kk; k++) {
    						sum = MathLib.plus(sum, MathLib.times(cholesky[i][k], cholesky[j][k]));
    					}
    					cholesky[i][j] = (this[i][j] - sum) / cholesky[j][j];
    				}

    				sum = 0;
    				for (k = 0, kk = j; k < kk; k++) {
    					sum = MathLib.plus(sum, MathLib.times(cholesky[i][k], cholesky[i][k]));
    				}
    				cholesky[i][j] = Math.sqrt(this[j][j] - sum);

    				for (j++, jj = this.cols; j < jj; j++) {
    					cholesky[i][j] = 0;
    				}
    			}
    			choleskyMatrix = new MathLib.Matrix(cholesky);

    			this.cholesky = function () {
    				return choleskyMatrix;
    			};
    			return choleskyMatrix;
    		};

# compare

#####

method
Matrix.prototype.compare() → number

Option name | Type | Description
--- | --- | ---
m | Matrix | The matrix to compare.

Compares the matrix to an other matrix.

    Matrix.prototype.compare = function (m) {
    			var i, ii, j, jj;

    			if (this.rows !== m.rows) {
    				return MathLib.sign(this.rows - m.rows);
    			}

    			if (this.cols !== m.cols) {
    				return MathLib.sign(this.cols - m.cols);
    			}

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				for (j = 0, jj = this.cols; j < jj; j++) {
    					if (this[i][j] - m[i][j]) {
    						return MathLib.sign(this[i][j] - m[i][j]);
    					}
    				}
    			}

    			return 0;
    		};

# copy

#####

method
Matrix.prototype.copy() → Matrix

Copies the matrix

    Matrix.prototype.copy = function () {
    			return this.map(function (entry) {
    				return MathLib.copy(entry);
    			});
    		};

# determinant

#####

method
Matrix.prototype.determinant() → number Complex

Calculates the determinant of the matrix via the LU decomposition.
The result is cached.

    Matrix.prototype.determinant = function () {
    			var LU, determinant;

    			if (!this.isSquare()) {
    				MathLib.error({message: 'Determinant of non square matrix', method: 'Matrix#determinant'});
    				return;
    			}

    			if (this.rank() < this.rows) {
    				determinant = 0;
    			}
    			else {
    				LU = this.LU();
    				determinant = MathLib.times(this.LUpermutation.sgn(), MathLib.times.apply(null, LU.diag()));
    			}

    			this.determinant = function () {
    				return determinant;
    			};
    			return determinant;
    		};

# diag

#####

method
Matrix.prototype.diag() → array

Returns the entries on the diagonal in an array

    Matrix.prototype.diag = function () {
    			var diagonal = [], i, ii;
    			for (i = 0, ii = Math.min(this.rows, this.cols); i < ii; i++) {
    				diagonal.push(this[i][i]);
    			}
    			return diagonal;
    		};

# divide

#####

method
Matrix.prototype.divide() → Matrix number

Multiplies the matrix by the inverse of a number or a matrix

    Matrix.prototype.divide = function (n) {
    			return this.times(MathLib.inverse(n));
    		};

# evaluate

#####

method
Matrix.prototype.evaluate() → Matrix

Evaluates the entries of the matrix

    Matrix.prototype.evaluate = function () {
    			return this.map(MathLib.evaluate);
    		};

# every

#####

method
Matrix.prototype.every() → boolean

Option name | Type | Description
--- | --- | ---
f | function | The function which is called on every argument

This function works like the Array.prototype.every function.
The matrix is processed row by row.
The function is called with the following arguments:
the entry at the current position, the number of the row,
the number of the column and the complete matrix

    Matrix.prototype.every = function (f) {
    			return Array.prototype.every.call(this, function (x, i) {
    				return Array.prototype.every.call(x, function (y, j) {
    					return f(y, i, j, this);
    				});
    			});
    		};

# forEach

#####

method
Matrix.prototype.forEach()

Option name | Type | Description
--- | --- | ---
f | function | The function which is called on every argument

This function works like the Array.prototype.forEach function.
The matrix is processed row by row.
The function is called with the following arguments:
the entry at the current position, the number of the row,
the number of the column and the complete matrix

    Matrix.prototype.forEach = function (f) {
    			Array.prototype.forEach.call(this, function (x, i) {
    				return Array.prototype.forEach.call(x, function (y, j) {
    					return f(y, i, j, this);
    				});
    			});
    		};

# gershgorin

#####

method
Matrix.prototype.gershgorin() → array

Returns the Gershgorin circles of the matrix.

    Matrix.prototype.gershgorin = function () {
    			var c = [], rc = [], rr = [], circles = [], i, ii;

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				rc.push(0);
    				rr.push(0);
    			}

    			this.forEach(function (x, i, j) {
    				if (i === j) {
    					if (MathLib.is(x, 'complex')) {
    						c.push(x.toPoint());
    					}
    					else {
    						c.push(new MathLib.Point([x, 0, 1]));
    					}
    				}
    				else {
    					rc[j] += MathLib.abs(x);
    					rr[i] += MathLib.abs(x);
    				}
    			});

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				circles.push(new MathLib.Circle(c[i], Math.min(rc[i], rr[i])));
    			}

    			return circles;
    		};

# givens

#####

method
Matrix.prototype.givens() → [Matrix

QR decomposition with the givens method.

    Matrix.prototype.givens = function () {
    			var rows = this.rows, cols = this.cols, R = this.copy(), Q = MathLib.Matrix.identity(rows), c, s, rho, i, j, k, ri, rj, qi, qj;

    			for (i = 0; i < cols; i++) {
    				for (j = i + 1; j < rows; j++) {
    					if (!MathLib.isZero(R[j][i])) {
    						// We can't use the sign function here, because we want the factor
    						// to be 1 if A[i][i] is zero.
    						rho = (R[i][i] < 0 ? -1 : 1) * MathLib.hypot(R[i][i], R[j][i]);
    						c = R[i][i] / rho;
    						s = R[j][i] / rho;

    						// Apply the rotation
    						ri = [];
    						rj = [];
    						qi = [];
    						qj = [];

    						for (k = 0; k < cols; k++) {
    							ri.push(R[i][k]);
    							rj.push(R[j][k]);
    						}
    						for (k = 0; k < cols; k++) {
    							R[i][k] = rj[k] * s + ri[k] * c;
    							R[j][k] = rj[k] * c - ri[k] * s;
    						}

    						for (k = 0; k < rows; k++) {
    							qi.push(Q[k][i]);
    							qj.push(Q[k][j]);
    						}
    						for (k = 0; k < rows; k++) {
    							Q[k][i] = qi[k] * c + qj[k] * s;
    							Q[k][j] = -qi[k] * s + qj[k] * c;
    						}
    					}
    				}
    			}

    			return [Q, R];
    		};

# inverse

#####

method
Matrix.prototype.inverse() → Matrix

Calculates the inverse matrix.

    Matrix.prototype.inverse = function () {
    			var i, ii, res, inverse, col = [], matrix = [], n = this.rows;

    			if (!this.isSquare()) {
    				MathLib.error({message: 'Inverse of non square matrix', method: 'Matrix#inverse'});
    				return;
    			}

    			for (i = 0, ii = n - 1; i < ii; i++) {
    				matrix.push([]);
    				col.push(0);
    			}

    			matrix.push([]);

    			col.push(1);
    			col = col.concat(col).slice(0, -1);

    			for (i = 0, ii = n; i < ii; i++) {
    				res = this.solve(col.slice(n - i - 1, 2 * n - i - 1));

    				if (res === undefined) {
    					return;
    				}

    				res.forEach(function (x, i) {
    					matrix[i].push(x);
    				});
    			}

    			inverse = new MathLib.Matrix(matrix);
    			this.inverse = function () {
    				return inverse;
    			};
    			return inverse;
    		};

# isBandMatrix

#####

method
Matrix.prototype.isBandMatrix() → boolean

Option name | Type | Description
--- | --- | ---
l | number | The wished lower bandwidth
u | number | The wished upper bandwidth

Determines if the matrix is a band matrix.

    Matrix.prototype.isBandMatrix = function (l, u) {
    			// var i, j, ii, jj;
    			if (arguments.length === 1) {
    				u = l;
    			}

    			return this.every(function (x, i, j) {
    				return (i - l <= j && i + u >= j) || MathLib.isZero(x);
    			});
    			// for (i = 0, ii = this.rows; i < ii; i++) {
    			//   for (j = 0, jj = this.cols; j < jj; j++) {
    			//     if (i - j < l && this[i][j] !== 0) {
    			//       return false;
    			//     }
    			//   }
    			// }
    			// return true;
    		};

# isDiag

#####

method
Matrix.prototype.isDiag() → boolean

Determines if the matrix is a diagonal matrix.

    Matrix.prototype.isDiag = function () {
    			var i, j, ii, jj;
    			if (Number(this.hasOwnProperty('isUpper') && this.isUpper()) + Number(this.hasOwnProperty('isLower') && this.isLower()) + Number(this.hasOwnProperty('isSymmetric') && this.isSymmetric()) > 1) {
    				return true;
    			}
    			for (i = 0, ii = this.rows; i < ii; i++) {
    				for (j = 0, jj = this.cols; j < jj; j++) {
    					if (i !== j && !MathLib.isZero(this[i][j])) {
    						return false;
    					}
    				}
    			}
    			return true;
    		};

# isEqual

#####

method
Matrix.prototype.isEqual() → boolean

Option name | Type | Description
--- | --- | ---
matrix | Matrix | The matrix to compare with

Determines if the matrix is equal to an other matrix.

    Matrix.prototype.isEqual = function (matrix) {
    			var i, j, ii, jj;
    			if (this === matrix) {
    				return true;
    			}
    			if (this.rows === matrix.rows && this.cols === matrix.cols) {
    				for (i = 0, ii = this.rows; i < ii; i++) {
    					for (j = 0, jj = this.cols; j < jj; j++) {
    						if (!MathLib.isEqual(this[i][j], matrix[i][j])) {
    							return false;
    						}
    					}
    				}
    				return true;
    			}
    			return false;
    		};

# isIdentity

#####

method
Matrix.prototype.isIdentity() → boolean

Determines if the matrix is a identity matrix.

    Matrix.prototype.isIdentity = function () {
    			if (!this.isSquare()) {
    				return false;
    			}

    			var isIdentity = this.every(function (x, r, c) {
    				return r === c ? MathLib.isOne(x) : MathLib.isZero(x);
    			});

    			this.isIdentity = function () {
    				return isIdentity;
    			};
    			return isIdentity;
    		};

# isInvertible

#####

method
Matrix.prototype.isInvertible() → boolean

Determines if the matrix is invertible.

    Matrix.prototype.isInvertible = function () {
    			return this.isSquare() && this.rank() === this.rows;
    		};

# isLower

#####

method
Matrix.prototype.isLower() → boolean

Determines if the matrix is a lower triangular matrix.

    Matrix.prototype.isLower = function () {
    			return this.slice(0, -1).every(function (x, i) {
    				return x.slice(i + 1).every(MathLib.isZero);
    			});
    		};

# isNegDefinite

#####

method
Matrix.prototype.isNegDefinite() → boolean

Determines if the matrix is negative definite

    Matrix.prototype.isNegDefinite = function () {
    			if (!this.isSquare()) {
    				return;
    			}
    			if (this.rows === 1) {
    				return this[0][0] < 0;
    			}

    			// Sylvester's criterion
    			if (this.rows % 2 === 0) {
    				return this.determinant() > 0 && this.remove(this.rows - 1, this.cols - 1).isNegDefinite();
    			}
    			else {
    				return this.determinant() < 0 && this.remove(this.rows - 1, this.cols - 1).isNegDefinite();
    			}
    		};

# isOrthogonal

#####

method
Matrix.prototype.isOrthogonal() → boolean

Determines if the matrix is a orthogonal.

    Matrix.prototype.isOrthogonal = function () {
    			return this.transpose().times(this).isIdentity();
    		};

# isPermutation

#####

method
Matrix.prototype.isPermutation() → boolean

Determines if the matrix is a permutation matrix

    Matrix.prototype.isPermutation = function () {
    			var rows = [], cols = [];

    			return this.every(function (x, r, c) {
    				if (MathLib.isOne(x)) {
    					if (rows[r] || cols[c]) {
    						return false;
    					}
    					else {
    						rows[r] = true;
    						cols[c] = true;
    						return true;
    					}
    				}
    				else if (MathLib.isZero(x)) {
    					return true;
    				}
    				return false;
    			}) && rows.length === this.rows && cols.length === this.cols;
    		};

# isPosDefinite

#####

method
Matrix.prototype.isPosDefinite() → boolean

Determines if the matrix is positive definite

    Matrix.prototype.isPosDefinite = function () {
    			if (!this.isSquare()) {
    				return;
    			}
    			if (this.rows === 1) {
    				return this[0][0] > 0;
    			}

    			// Sylvester's criterion
    			return this.determinant() > 0 && this.remove(this.rows - 1, this.cols - 1).isPosDefinite();
    		};

# isReal

#####

method
Matrix.prototype.isReal() → boolean

Determines if the matrix has only real entries

    Matrix.prototype.isReal = function () {
    			return this.every(MathLib.isReal);
    		};

# isScalar

#####

method
Matrix.prototype.isScalar() → boolean

Determines if the matrix is a scalar matrix
(that is a multiple of the identity matrix)

    Matrix.prototype.isScalar = function () {
    			var i, ii, diag = this.diag;
    			if (this.hasOwnProperty('isIdentity') && this.hasOwnProperty('isZero')) {
    				if (this.isIdentity() || this.isZero()) {
    					return true;
    				}
    				else {
    					return false;
    				}
    			}
    			if (this.isDiag()) {
    				for (i = 1, ii = this.rows; i < ii; i++) {
    					if (!MathLib.isEqual(diag[0], diag[i])) {
    						return false;
    					}
    				}
    				return true;
    			}
    			return false;
    		};

# isSquare

#####

method
Matrix.prototype.isSquare() → boolean

Determines if the matrix is a square matrix

    Matrix.prototype.isSquare = function () {
    			return this.cols === this.rows;
    		};

# isSymmetric

#####

method
Matrix.prototype.isSymmetric() → boolean

Determines if the matrix is symmetric

    Matrix.prototype.isSymmetric = function () {
    			var i, ii, j, jj, isSymmetric = true;

    			if (!this.isSquare()) {
    				isSymmetric = false;
    			}
    			else {
    				lp:
    				for (i = 0, ii = this.rows; i < ii; i++) {
    					for (j = i + 1, jj = this.cols; j < jj; j++) {
    						if (!MathLib.isEqual(this[i][j], this[j][i])) {
    							isSymmetric = false;
    							break lp;
    						}
    					}
    				}
    			}

    			this.isSymmetric = function () {
    				return isSymmetric;
    			};
    			return isSymmetric;
    		};

# isUpper

#####

method
Matrix.prototype.isUpper() → boolean

Determines if the matrix is a upper triangular matrix

    Matrix.prototype.isUpper = function () {
    			return this.slice(1).every(function (x, i) {
    				return x.slice(0, i + 1).every(MathLib.isZero);
    			});
    		};

# isVector

#####

method
Matrix.prototype.isVector() → boolean

Determines if the matrix is a vector
(only one row or one column)

    Matrix.prototype.isVector = function () {
    			return (this.rows === 1) || (this.cols === 1);
    		};

# isZero

#####

method
Matrix.prototype.isZero() → boolean

Determines if the matrix the zero matrix
The result is cached.

    Matrix.prototype.isZero = function () {
    			var isZero = this.every(MathLib.isZero);

    			this.isZero = function () {
    				return isZero;
    			};
    			return isZero;
    		};

# map

#####

method
Matrix.prototype.map() → Matrix

Option name | Type | Description
--- | --- | ---
f | function | The function which is called on every argument

This function works like the Array.prototype.map function.
The matrix is processed row by row.
The function is called with the following arguments:
the entry at the current position, the number of the row,
the number of the column and the complete matrix

    Matrix.prototype.map = function (f) {
    			var m = this;
    			return new MathLib.Matrix(Array.prototype.map.call(this, function (x, i) {
    				return Array.prototype.map.call(x, function (y, j) {
    					return f(y, i, j, m);
    				});
    			}));
    		};

# minor

#####

method
Matrix.prototype.minor() → Matrix

Option name | Type | Description
--- | --- | ---
r | number | The row to be removed.
c | number | The column to be removed.

Calculates a minor

    Matrix.prototype.minor = function (r, c) {
    			return this.remove(r, c).determinant();
    		};

# minus

#####

method
Matrix.prototype.minus() → Matrix

Option name | Type | Description
--- | --- | ---
subtrahend | Matrix | The matrix to be subtracted.

Calculates the difference of two matrices

    Matrix.prototype.minus = function (subtrahend) {
    			if (this.rows === subtrahend.rows && this.cols === subtrahend.cols) {
    				return this.plus(subtrahend.negative());
    			}
    			else {
    				MathLib.error({message: 'Matrix sizes not matching', method: 'Matrix#minus'});
    				return;
    			}
    		};

# negative

#####

method
Matrix.prototype.negative() → Matrix

Returns the negative matrix

    Matrix.prototype.negative = function () {
    			var i, ii, negative = [];

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				negative.push(this[i].map(function (entry) {
    					return MathLib.negative(entry);
    				}));
    			}
    			return new MathLib.Matrix(negative);
    		};

# plus

#####

method
Matrix.prototype.plus() → Matrix

Option name | Type | Description
--- | --- | ---
summand | Matrix | The matrix to be added.

This function adds a matrix to the current matrix
and returns the result as a new matrix.

    Matrix.prototype.plus = function (summand) {
    			var i, ii, j, jj, sum = [];

    			if (this.rows === summand.rows && this.cols === summand.cols) {
    				for (i = 0, ii = this.rows; i < ii; i++) {
    					sum[i] = [];
    					for (j = 0, jj = this.cols; j < jj; j++) {
    						sum[i][j] = MathLib.plus(this[i][j], summand[i][j]);
    					}
    				}
    				return new MathLib.Matrix(sum);
    			}
    			else {
    				MathLib.error({message: 'Matrix sizes not matching', method: 'Matrix#plus'});
    				return;
    			}
    		};

# rank

#####

method
Matrix.prototype.rank() → number

Determines the rank of the matrix

    Matrix.prototype.rank = function () {
    			var i, j, rank = 0, mat = this.rref();

    			rankloop:
    			for (i = Math.min(this.rows, this.cols) - 1; i >= 0; i--) {
    				for (j = this.cols - 1; j >= i; j--) {
    					if (!MathLib.isZero(mat[i][j])) {
    						rank = i + 1;
    						break rankloop;
    					}
    				}
    			}

    			this.rank = function () {
    				return rank;
    			};
    			return rank;
    		};

# reduce

#####

method
Matrix.prototype.reduce() → any

This function works like the Array.prototype.reduce function.

    Matrix.prototype.reduce = function () {
    			var args = [];
    			for (var _i = 0; _i < (arguments.length - 0); _i++) {
    				args[_i] = arguments[_i + 0];
    			}
    			return Array.prototype.reduce.apply(this, args);
    		};

# remove

#####

method
Matrix.prototype.remove() → Matrix

Option name | Type | Description
--- | --- | ---
row | number array | The row(s) to be removed.
col | number array | The column(s) to be removed.

This function removes the specified rows and/or columns for the matrix.

    Matrix.prototype.remove = function (row, col) {
    			var rest = this.toArray();

    			if (row || row === 0) {
    				if (typeof row === 'number') {
    					row = [row];
    				}
    				rest = rest.filter(function (x, i) {
    					return row.indexOf(i) === -1;
    				});
    			}

    			if (col || col === 0) {
    				if (typeof col === 'number') {
    					col = [col];
    				}
    				col = col.sort().reverse();
    				col.forEach(function (n) {
    					rest = rest.map(function (x) {
    						x.splice(n, 1);
    						return x;
    					});
    				});
    			}

    			return new MathLib.Matrix(rest);
    		};

# rref

#####

method
Matrix.prototype.rref() → Matrix

Calculate the reduced row echelon form (rref) of a matrix.

    Matrix.prototype.rref = function () {
    			var i, ii, j, jj, k, kk, pivot, factor, swap, lead = 0, rref = this.toArray();

    			for (i = 0, ii = this.rows; i < ii; i++) {
    				if (this.cols <= lead) {
    					return new MathLib.Matrix(rref);
    				}

    				// Find the row with the biggest pivot element
    				j = i;
    				while (rref[j][lead] === 0) {
    					j++;
    					if (this.rows === j) {
    						j = i;
    						lead++;
    						if (this.cols === lead) {
    							return new MathLib.Matrix(rref);
    						}
    					}
    				}

    				// Swap the pivot row to the top
    				if (i !== j) {
    					swap = rref[j];
    					rref[j] = rref[i];
    					rref[i] = swap;
    				}

    				pivot = rref[i][lead];

    				for (j = lead, jj = this.cols; j < jj; j++) {
    					rref[i][j] /= pivot;
    				}

    				for (j = 0, jj = this.rows; j < jj; j++) {
    					if (j === i) {
    						continue;
    					}
    					factor = rref[j][lead];
    					for (k = 0, kk = this.cols; k < kk; k++) {
    						rref[j][k] = MathLib.minus(rref[j][k], MathLib.times(factor, rref[i][k]));
    					}
    				}
    				lead++;
    			}
    			return new MathLib.Matrix(rref);
    		};

# slice

#####

method
Matrix.prototype.slice() → array

This function works like the Array.prototype.slice function.

    Matrix.prototype.slice = function () {
    			var args = [];
    			for (var _i = 0; _i < (arguments.length - 0); _i++) {
    				args[_i] = arguments[_i + 0];
    			}
    			return Array.prototype.slice.apply(this, args);
    		};

# solve

#####

method
Matrix.prototype.solve() → Vector

Option name | Type | Description
--- | --- | ---
b | Vector | The b in Ax = b

Solves the system of linear equations Ax = b
given by the matrix A and a vector or point b.

    Matrix.prototype.solve = function (b) {
    			// Ax = b -> LUx = b. Then y is defined to be Ux
    			var LU = this.LU(), i, j, n = b.length, x = [], y = [];

    			// Permutate b according to the LU decomposition
    			b = this.LUpermutation.applyTo(b);

    			for (i = 0; i < n; i++) {
    				y[i] = b[i];
    				for (j = 0; j < i; j++) {
    					y[i] = MathLib.minus(y[i], MathLib.times(LU[i][j], y[j]));
    				}
    			}

    			for (i = n - 1; i >= 0; i--) {
    				x[i] = y[i];
    				for (j = i + 1; j < n; j++) {
    					x[i] = MathLib.minus(x[i], MathLib.times(LU[i][j], x[j]));
    				}

    				if (LU[i][i] === 0) {
    					if (x[i] !== 0) {
    						return undefined;
    					}
    					else {
    						x[i] = x[i];
    					}
    				}
    				else {
    					x[i] = MathLib.divide(x[i], LU[i][i]);
    				}
    			}

    			if (MathLib.type(b) === 'array') {
    				return x;
    			}
    			else {
    				return new b.constructor(x);
    			}
    		};

# some

#####

method
Matrix.prototype.some() → boolean

Option name | Type | Description
--- | --- | ---
f | function | The function which is called on every argument

This function works like the Array.prototype.some function.
The matrix is processed row by row.
The function is called with the following arguments:
the entry at the current position, the number of the row,
the number of the column and the complete matrix

    Matrix.prototype.some = function (f) {
    			return Array.prototype.some.call(this, function (x, i) {
    				return Array.prototype.some.call(x, function (y, j) {
    					return f(y, i, j, this);
    				});
    			});
    		};

# times

#####

method
Matrix.prototype.times() → Matrix Point Vector

Option name | Type | Description
--- | --- | ---
a | number Matrix Point Rational Vector | The object to multiply to the current matrix

Multiplies the current matrix with a number, a matrix, a point or a vector.

    Matrix.prototype.times = function (a) {
    			var i, ii, j, jj, k, kk, product = [], entry;

    			if (a.type === 'rational') {
    				a = a.coerceTo('number');
    			}
    			if (typeof a === 'number' || a.type === 'complex') {
    				return this.map(function (x) {
    					return MathLib.times(x, a);
    				});
    			}
    			else if (a.type === 'matrix') {
    				if (this.cols === a.rows) {
    					for (i = 0, ii = this.rows; i < ii; i++) {
    						product[i] = [];
    						for (j = 0, jj = a.cols; j < jj; j++) {
    							entry = 0;

    							for (k = 0, kk = this.cols; k < kk; k++) {
    								entry = MathLib.plus(entry, MathLib.times(this[i][k], a[k][j]));
    							}
    							product[i][j] = entry;
    						}
    					}
    					return new MathLib.Matrix(product);
    				}
    				else {
    					MathLib.error({message: 'Matrix sizes not matching', method: 'Matrix#times'});
    					return;
    				}
    			}
    			else if (a.type === 'point' || a.type === 'vector') {
    				if (this.cols === a.length) {
    					for (i = 0, ii = this.rows; i < ii; i++) {
    						entry = 0;
    						for (j = 0, jj = this.cols; j < jj; j++) {
    							entry = MathLib.plus(entry, MathLib.times(this[i][j], a[j]));
    						}
    						product.push(entry);
    					}
    					return new a.constructor(product);
    				}
    			}
    		};

# toArray

#####

method
Matrix.prototype.toArray() → array

Converts the matrix to a two-dimensional array

    Matrix.prototype.toArray = function () {
    			return Array.prototype.map.call(this, function (x) {
    				return Array.prototype.map.call(x, function (y) {
    					return MathLib.copy(y);
    				});
    			});
    		};

# toColVectors

#####

method
Matrix.prototype.toColVectors() → array

Converts the columns of the matrix to vectors

    Matrix.prototype.toColVectors = function () {
    			return this.transpose().toRowVectors();
    		};

# toContentMathML

#####

method
Matrix.prototype.toContentMathML() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

converting the matrix to content MathML

    Matrix.prototype.toContentMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			if (options.strict) {
    				return this.reduce(function (str, x) {
    					return str + '<apply><csymbol cd="linalg2">matrixrow</csymbol>' + x.map(function (entry) {
    						return MathLib.toContentMathML(entry, options);
    					}).join('') + '</apply>';
    				}, '<apply><csymbol cd="linalg2">matrix</csymbol>') + '</apply>';
    			}
    			else {
    				return this.reduce(function (str, x) {
    					return str + '<matrixrow>' + x.map(function (entry) {
    						return MathLib.toContentMathML(entry, options);
    					}).join('') + '</matrixrow>';
    				}, '<matrix>') + '</matrix>';
    			}
    		};

# toLaTeX

#####

method
Matrix.prototype.toLaTeX() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Converting the matrix to LaTeX

    Matrix.prototype.toLaTeX = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var passOptions = {base: options.base, baseSubscript: options.baseSubscript};

    			return '\\begin{pmatrix}\n' + this.reduce(function (str, x) {
    				return str + x.map(function (entry) {
    					return MathLib.toLaTeX(entry, passOptions);
    				}).join(' & ') + '\\\n';
    			}, '').slice(0, -2) + '\n\\end{pmatrix}';
    		};

# toMathML

#####

method
Matrix.prototype.toMathML() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

converting the matrix to (presentation) MathML

    Matrix.prototype.toMathML = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var passOptions = {base: options.base, baseSubscript: options.baseSubscript};

    			return this.reduce(function (str, x) {
    				return str + '<mtr><mtd>' + x.map(function (entry) {
    					return MathLib.toMathML(entry, passOptions);
    				}).join('</mtd><mtd>') + '</mtd></mtr>';
    			}, '<mrow><mo> ( </mo><mtable>') + '</mtable><mo> ) </mo></mrow>';
    		};

# toRowVectors

#####

method
Matrix.prototype.toRowVectors() → array

Converts the rows of the matrix to vectors

    Matrix.prototype.toRowVectors = function () {
    			return this.toArray().map(function (v) {
    				return new MathLib.Vector(v);
    			});
    		};

# toString

#####

method
Matrix.prototype.toString() → string

Option name | Type | Description
--- | --- | ---
[options] | object | - Optional options to style the output

Creating a custom .toString() function

    Matrix.prototype.toString = function (options) {
    			if (typeof options === 'undefined') { options = {}; }
    			var passOptions = {base: options.base, baseSubscript: options.baseSubscript};

    			return this.reduce(function (str, x) {
    				return str + x.map(function (entry) {
    					return MathLib.toString(entry, passOptions);
    				}).join('\t') + '\n';
    			}, '').slice(0, -1);
    		};

# trace

#####

method
Matrix.prototype.trace() → number Complex

Calculating the trace of the matrix

    Matrix.prototype.trace = function () {
    			var trace = MathLib.plus.apply(null, this.diag());

    			this.trace = function () {
    				return trace;
    			};
    			return trace;
    		};

# transpose

#####

method
Matrix.prototype.transpose() → Matrix

Calculating the transpose of the matrix
The result is cached.

    Matrix.prototype.transpose = function () {
    			var transposedMatrix, row, i, j, ii, jj, transpose = [];

    			for (i = 0, ii = this.cols; i < ii; i++) {
    				row = [];
    				for (j = 0, jj = this.rows; j < jj; j++) {
    					row.push(this[j][i]);
    				}
    				transpose.push(row);
    			}

    			transposedMatrix = new MathLib.Matrix(transpose);
    			this.transpose = function () {
    				return transposedMatrix;
    			};
    			return transposedMatrix;
    		};
    		Matrix.givensMatrix = function (n, i, k, phi) {
    			var givens = MathLib.Matrix.identity(n);
    			givens[k][k] = givens[i][i] = Math.cos(phi);
    			givens[i][k] = Math.sin(phi);
    			givens[k][i] = -givens[i][k];
    			return givens;
    		};

    		Matrix.identity = function (n) {
    			var row = [], matrix = [], i, ii;
    			n = n || 1;

    			for (i = 0, ii = n - 1; i < ii; i++) {
    				row.push(0);
    			}
    			row.push(1);
    			row = row.concat(row);
    			row = row.slice(0, -1);

    			for (i = 0, ii = n; i < ii; i++) {
    				matrix.push(row.slice(n - i - 1, 2 * n - i - 1));
    			}

    			return new MathLib.Matrix(matrix);
    		};

    		Matrix.numbers = function (n, r, c) {
    			var i, ii, row = [], matrix = [];

    			for (i = 0, ii = c || r || 1; i < ii; i++) {
    				row.push(n);
    			}
    			for (i = 0, ii = r || 1; i < ii; i++) {
    				matrix.push(row.slice(0));
    			}
    			return new MathLib.Matrix(matrix);
    		};

    		Matrix.one = function (r, c) {
    			r = r || 1;
    			c = c || 1;
    			return MathLib.Matrix.numbers(1, r, c);
    		};

    		Matrix.random = function (r, c) {
    			var row, matrix = [], i, j, ii, jj;
    			for (i = 0, ii = r || 1; i < ii; i++) {
    				row = [];
    				for (j = 0, jj = c || r || 1; j < jj; j++) {
    					row.push(Math.random());
    				}
    				matrix.push(row);
    			}
    			return new MathLib.Matrix(matrix);
    		};

    		Matrix.zero = function (r, c) {
    			r = r || 1;
    			c = c || 1;
    			return MathLib.Matrix.numbers(0, r, c);
    		};
    		return Matrix;
    	})();
    	MathLib.Matrix = Matrix;
    })(MathLib || (MathLib = {}));