function Matrix(m, n) {
	if (n == undefined) {
		if (m instanceof Matrix) {
			this.m = m.m; this.n = m.n;
			for (var x = 1; x <= m.m; x++) {
				this[x] = new Object();
				for (var y = 1; y <= m.n; y++)
					this[x][y] = m[x][y];
			}
		} else {
			if (m.length == 0) return;
			this.m = m.length;
			this.n = m[0].length;
			for (var x = 0; x < this.m; x++) {
				this[x + 1] = new Object();
				for (var y = 0; y < this.n; y++)
					this[x + 1][y + 1] = m[x][y];
			}
		}
	} else {
		if (m <= 0 || n <= 0) return;
		this.m = m; this.n = n;
		for (var x = 1; x <= m; x++) {
			this[x] = new Object();
			for (var y = 1; y <= n; y++)
				this[x][y] = 0;
		}
	}
}

Matrix.prototype.col = function col(m) {
	for (var y = 1; y <= this.n; y++)
		k[1][y] = this[m][y];
	return k;
};

Matrix.prototype.row = function row(n) {
	var k = new Matrix(this.m, 1);
	for (var x = 1; x <= this.m; y++)
		k[x][1] = this[x][n];
	return k;
};

Matrix.prototype.plus = function plus(k) {
	if (this.m != k.m || this.n != k.n) return null;
	var m = new Matrix(this.m, this.n);
	for (var x = 1; x <= this.m; x++)
		for (var y = 1; y <= this.n; y++)
			m[x][y] = this[x][y] + k[x][y];
	return m;
};

Matrix.prototype.minus = function minus(k) {
	var m = new Matrix(this.m, this.n);
	if (k == undefined)
		for (var x = 1; x <= this.m; x++)
			for (var y = 1; y <= this.n; y++)
				m[x][y] = -this[x][y];
	else {
		if (this.m != k.m || this.n != k.n) return null;
		for (var x = 1; x <= this.m; x++)
			for (var y = 1; y <= this.n; y++)
				m[x][y] = this[x][y] - k[x][y];
	}
	return m;
};

Matrix.prototype.multiply = function multiply(k) {
	if (typeof(k) == "number") {
		var m = new Matrix(this);
		for (var x = 1; x <= this.m; x++)
			for (var y = 1; y <= this.n; y++)
				m[x][y] = this[x][y] * k;
		return m;
	}
	if (this.n != k.m) return null;
	var m = new Matrix(this.m, k.n);
	for (var x = 1; x <= this.m; x++)
		for (var y = 1; y <= k.n; y++)
			for (var z = 1; z <= this.n; z++)
				m[x][y] += this[x][z] * k[z][y];
	return m;
};

Matrix.prototype.inverse = function () {
	if (this.m != this.n) return null;
	var a = Matrix.augment(new Matrix(this), Matrix.E(this.m));
	for (var y = 1; y < a.m; y++) {
		var x = y;
		while (a[x][y] == 0 && x < a.m) x++;
		if (x == a.m && a[x][y] == 0) return null;
		if (x != y) {
			var o = a[y];
			a[y] = a[x];
			a[x] = o;
		}
		for (var k = y + 1; k <= a.m; k++) {
			var c = a[k][y] / a[y][y];
			for (var z = y; z <= a.n; z++)
				a[k][z] -= a[y][z] * c;
		}
	}
	for (var y = a.m; y >= 1; y--) {
		var c = a[y][y];
		for (var z = y; z <= a.n; z++)
			a[y][z] /= c;
		for (var k = y - 1; k >= 1; k--) {
			var c = a[k][y];
			for (var z = y; z <= a.n; z++)
				a[k][z] -= c * a[y][z];
		}
	}
	var n = new Matrix(this.m, this.n);
	for (var x = 1; x <= this.m; x++)
		for (var y = 1; y <= this.n; y++)
			n[x][y] = a[x][y + this.m];
	return n;
};

Matrix.prototype.rowSwap = function rowSwap(i, j) {
	var m = new Matrix(this);
	var o = m[i];
	m[i] = m[j];
	m[j] = o;
	return m;
};

Matrix.prototype.rowAdd = function rowAdd(i, j) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.n; x++)
		m[i][x] += m[j][x];
	return m;
};

Matrix.prototype.rowMultiply = function rowMultiply(i, k) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.n; x++)
		m[i][x] *= k;
	return m;
};

Matrix.prototype.rowAddMultiply = function rowAddMultiply(i, k, j) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.n; x++)
		m[j][x] += k * m[i][x];
	return m;
};

Matrix.prototype.colSwap = function colSwap(i, j) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.m; x++) {
		var v = m[x][j];
		m[x][j] = m[x][i];
		m[x][i] = v;
	}
	return m;
};

Matrix.prototype.colAdd = function colAdd(i, j) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.m; x++)
		m[x][i] += m[x][j];
	return m;
};

Matrix.prototype.colMultiply = function colMultiply(i, k) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.m; x++)
		m[x][i] *= k;
	return m;
};

Matrix.prototype.colAddMultiply = function colAddMultiply(i, k, j) {
	var m = new Matrix(this);
	for (var x = 1; x <= this.m; x++)
		m[x][j] += k * m[x][i];
	return m;
};

Matrix.prototype.toString = function () {
	var s = "[[" + this[1][1];
	for (var y = 2; y <= this.n; y++)
		s += ", " + this[1][y];
	s += "]";
	for (var x = 2; x <= this.m; x++) {
		s += ", [" + this[x][1];
		for (var y = 2; y <= this.n; y++)
			s += ", " + this[x][y];
		s += "]";
	}
	return s + "]";
};

Matrix.E = function E(n) {
	var e = new Matrix(n, n);
	for (var x = 1; x <= n; x++)
		e[x][x] = 1;
	return e;
};

Matrix.det = function det(A) {
	if (A.m != A.n) return null;
	var a = new Matrix(A), r = 1;
	for (var y = 1; y < a.m; y++) {
		var x = y;
		while (a[x][y] == 0 && x < a.m) x++;
		if (x == a.m && a[x][y] == 0) return 0;
		if (x != y) {
			var o = a[y];
			a[y] = a[x];
			a[x] = o;
			r *= -1;
		}
		r *= a[y][y];
		for (var k = y + 1; k <= a.m; k++) {
			var c = a[k][y] / a[y][y];
			for (var z = y; z <= a.m; z++)
				a[k][z] -= a[y][z] * c;
		}
	}
	return r * a[a.m][a.m];	
};

Matrix.t = function t(A) {
	var m = new Matrix(A.n, A.m);
	for (var x = 1; x <= m.m; x++) {
		this[x] = new Object();
		for (var y = 1; y <= m.n; y++)
			m[x][y] = A[y][x];
	}
	return m;
};

Matrix.augment = function augment(A, B) {
	if (A.m != B.m) return null;
	var m = new Matrix(A);
	for (var x = 1; x <= A.m; x++)
		for (var y = 1; y <= B.n; y++)
			m[x][y + A.n] = B[x][y];
	m.n += B.n;
	return m;
};
