Permalink
Browse files

Reducing Sylvester to just the e() and x() functions that I was using.

  • Loading branch information...
heygrady committed May 21, 2010
1 parent 0cae931 commit a8783a5bd506a5f97fe88dbea3709acd05a4c62e
Showing with 1 addition and 274 deletions.
  1. +0 −273 lib/sylvester-matrix-0.1.3.js
  2. +1 −1 lib/sylvester-matrix-0.1.3.min.js
@@ -27,51 +27,12 @@ var Sylvester = {
function Matrix() {}
Matrix.prototype = {
-
// Returns element (i,j) of the matrix
e: function(i,j) {
if (i < 1 || i > this.elements.length || j < 1 || j > this.elements[0].length) { return null; }
return this.elements[i-1][j-1];
},
- // Returns the number of rows/columns the matrix has
- dimensions: function() {
- return {rows: this.elements.length, cols: this.elements[0].length};
- },
-
- // Returns the number of rows in the matrix
- rows: function() {
- return this.elements.length;
- },
-
- // Returns the number of columns in the matrix
- cols: function() {
- return this.elements[0].length;
- },
-
- // Returns true iff the matrix is equal to the argument. You can supply
- // a vector as the argument, in which case the receiver must be a
- // one-column matrix equal to the vector.
- eql: function(matrix) {
- var M = matrix.elements || matrix;
- if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
- if (this.elements.length != M.length ||
- this.elements[0].length != M[0].length) { return false; }
- var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
- do { i = ki - ni;
- nj = kj;
- do { j = kj - nj;
- if (Math.abs(this.elements[i][j] - M[i][j]) > Sylvester.precision) { return false; }
- } while (--nj);
- } while (--ni);
- return true;
- },
-
- // Returns a copy of the matrix
- dup: function() {
- return Matrix.create(this.elements);
- },
-
// Maps the matrix to another matrix (of the same dimensions) according to the given function
map: function(fn) {
var els = [], ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
@@ -85,30 +46,6 @@ Matrix.prototype = {
return Matrix.create(els);
},
- // Returns true iff the argument has the same dimensions as the matrix
- isSameSizeAs: function(matrix) {
- var M = matrix.elements || matrix;
- if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
- return (this.elements.length == M.length &&
- this.elements[0].length == M[0].length);
- },
-
- // Returns the result of adding the argument to the matrix
- add: function(matrix) {
- var M = matrix.elements || matrix;
- if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
- if (!this.isSameSizeAs(M)) { return null; }
- return this.map(function(x, i, j) { return x + M[i-1][j-1]; });
- },
-
- // Returns the result of subtracting the argument from the matrix
- subtract: function(matrix) {
- var M = matrix.elements || matrix;
- if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
- if (!this.isSameSizeAs(M)) { return null; }
- return this.map(function(x, i, j) { return x - M[i-1][j-1]; });
- },
-
// Returns true iff the matrix can multiply the argument from the left
canMultiplyFromLeft: function(matrix) {
var M = matrix.elements || matrix;
@@ -149,216 +86,6 @@ Matrix.prototype = {
x: function(matrix) { return this.multiply(matrix); },
- // Returns a submatrix taken from the matrix
- // Argument order is: start row, start col, nrows, ncols
- // Element selection wraps if the required index is outside the matrix's bounds, so you could
- // use this to perform row/column cycling or copy-augmenting.
- minor: function(a, b, c, d) {
- var elements = [], ni = c, i, nj, j;
- var rows = this.elements.length, cols = this.elements[0].length;
- do { i = c - ni;
- elements[i] = [];
- nj = d;
- do { j = d - nj;
- elements[i][j] = this.elements[(a+i-1)%rows][(b+j-1)%cols];
- } while (--nj);
- } while (--ni);
- return Matrix.create(elements);
- },
-
- // Returns the transpose of the matrix
- transpose: function() {
- var rows = this.elements.length, cols = this.elements[0].length;
- var elements = [], ni = cols, i, nj, j;
- do { i = cols - ni;
- elements[i] = [];
- nj = rows;
- do { j = rows - nj;
- elements[i][j] = this.elements[j][i];
- } while (--nj);
- } while (--ni);
- return Matrix.create(elements);
- },
-
- // Returns true iff the matrix is square
- isSquare: function() {
- return (this.elements.length == this.elements[0].length);
- },
-
- // Returns the (absolute) largest element of the matrix
- max: function() {
- var m = 0, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
- do { i = ki - ni;
- nj = kj;
- do { j = kj - nj;
- if (Math.abs(this.elements[i][j]) > Math.abs(m)) { m = this.elements[i][j]; }
- } while (--nj);
- } while (--ni);
- return m;
- },
-
- // Returns the indeces of the first match found by reading row-by-row from left to right
- indexOf: function(x) {
- var index = null, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
- do { i = ki - ni;
- nj = kj;
- do { j = kj - nj;
- if (this.elements[i][j] == x) { return {i: i+1, j: j+1}; }
- } while (--nj);
- } while (--ni);
- return null;
- },
-
- // Make the matrix upper (right) triangular by Gaussian elimination.
- // This method only adds multiples of rows to other rows. No rows are
- // scaled up or switched, and the determinant is preserved.
- toRightTriangular: function() {
- var M = this.dup(), els;
- var n = this.elements.length, k = n, i, np, kp = this.elements[0].length, p;
- do { i = k - n;
- if (M.elements[i][i] == 0) {
- for (j = i + 1; j < k; j++) {
- if (M.elements[j][i] != 0) {
- els = []; np = kp;
- do { p = kp - np;
- els.push(M.elements[i][p] + M.elements[j][p]);
- } while (--np);
- M.elements[i] = els;
- break;
- }
- }
- }
- if (M.elements[i][i] != 0) {
- for (j = i + 1; j < k; j++) {
- var multiplier = M.elements[j][i] / M.elements[i][i];
- els = []; np = kp;
- do { p = kp - np;
- // Elements with column numbers up to an including the number
- // of the row that we're subtracting can safely be set straight to
- // zero, since that's the point of this routine and it avoids having
- // to loop over and correct rounding errors later
- els.push(p <= i ? 0 : M.elements[j][p] - M.elements[i][p] * multiplier);
- } while (--np);
- M.elements[j] = els;
- }
- }
- } while (--n);
- return M;
- },
-
- toUpperTriangular: function() { return this.toRightTriangular(); },
-
- // Returns the determinant for square matrices
- determinant: function() {
- if (!this.isSquare()) { return null; }
- var M = this.toRightTriangular();
- var det = M.elements[0][0], n = M.elements.length - 1, k = n, i;
- do { i = k - n + 1;
- det = det * M.elements[i][i];
- } while (--n);
- return det;
- },
-
- det: function() { return this.determinant(); },
-
- // Returns true iff the matrix is singular
- isSingular: function() {
- return (this.isSquare() && this.determinant() === 0);
- },
-
- // Returns the trace for square matrices
- trace: function() {
- if (!this.isSquare()) { return null; }
- var tr = this.elements[0][0], n = this.elements.length - 1, k = n, i;
- do { i = k - n + 1;
- tr += this.elements[i][i];
- } while (--n);
- return tr;
- },
-
- tr: function() { return this.trace(); },
-
- // Returns the rank of the matrix
- rank: function() {
- var M = this.toRightTriangular(), rank = 0;
- var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
- do { i = ki - ni;
- nj = kj;
- do { j = kj - nj;
- if (Math.abs(M.elements[i][j]) > Sylvester.precision) { rank++; break; }
- } while (--nj);
- } while (--ni);
- return rank;
- },
-
- rk: function() { return this.rank(); },
-
- // Returns the result of attaching the given argument to the right-hand side of the matrix
- augment: function(matrix) {
- var M = matrix.elements || matrix;
- if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
- var T = this.dup(), cols = T.elements[0].length;
- var ni = T.elements.length, ki = ni, i, nj, kj = M[0].length, j;
- if (ni != M.length) { return null; }
- do { i = ki - ni;
- nj = kj;
- do { j = kj - nj;
- T.elements[i][cols + j] = M[i][j];
- } while (--nj);
- } while (--ni);
- return T;
- },
-
- // Returns the inverse (if one exists) using Gauss-Jordan
- inverse: function() {
- if (!this.isSquare() || this.isSingular()) { return null; }
- var ni = this.elements.length, ki = ni, i, j;
- var M = this.augment(Matrix.I(ni)).toRightTriangular();
- var np, kp = M.elements[0].length, p, els, divisor;
- var inverse_elements = [], new_element;
- // Matrix is non-singular so there will be no zeros on the diagonal
- // Cycle through rows from last to first
- do { i = ni - 1;
- // First, normalise diagonal elements to 1
- els = []; np = kp;
- inverse_elements[i] = [];
- divisor = M.elements[i][i];
- do { p = kp - np;
- new_element = M.elements[i][p] / divisor;
- els.push(new_element);
- // Shuffle of the current row of the right hand side into the results
- // array as it will not be modified by later runs through this loop
- if (p >= ki) { inverse_elements[i].push(new_element); }
- } while (--np);
- M.elements[i] = els;
- // Then, subtract this row from those above it to
- // give the identity matrix on the left hand side
- for (j = 0; j < i; j++) {
- els = []; np = kp;
- do { p = kp - np;
- els.push(M.elements[j][p] - M.elements[i][p] * M.elements[j][i]);
- } while (--np);
- M.elements[j] = els;
- }
- } while (--ni);
- return Matrix.create(inverse_elements);
- },
-
- inv: function() { return this.inverse(); },
-
- // Returns the result of rounding all the elements
- round: function() {
- return this.map(function(x) { return Math.round(x); });
- },
-
- // Returns a copy of the matrix with elements set to the given value if they
- // differ from it by less than Sylvester.precision
- snapTo: function(x) {
- return this.map(function(p) {
- return (Math.abs(p - x) <= Sylvester.precision) ? x : p;
- });
- },
-
// Set the matrix's elements from an array. If the argument passed
// is a vector, the resulting matrix will be a single column.
setElements: function(els) {

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

0 comments on commit a8783a5

Please sign in to comment.