Permalink
Browse files

added inverse and equals

  • Loading branch information...
1 parent 5f57b79 commit 0bc953600f7396795adf3b253f33831fba21cba2 @angusgibbs committed Mar 2, 2013
Showing with 182 additions and 0 deletions.
  1. +29 −0 docs/equals.md
  2. +2 −0 docs/getting_started.md
  3. +18 −0 docs/inverse.md
  4. +69 −0 lib/matrix.js
  5. +64 −0 test/test.js
View
@@ -0,0 +1,29 @@
+# Matrix#equals(*n*)
+
+`Matrix#equals()` accepts one parameter, a Matrix object or a two dimensional array that will converted into a Matrix object. It will return true if the matrix passed has the same dimensions and contents as the current matrix, and false otherwise.
+
+## Errors
+
+None.
+
+## Examples
+
+```javascript
+var a = new Matrix([[2, 2], [1, 1]]);
+var b = new Matrix([[3, 3], [2, 2]]);
+var c = new Matrix([[3, 3], [2, 2]]);
+var d = new Matrix([[3], [2]]);
+
+a.equals(b);
+// => false
+
+b.equals(c);
+// => true
+
+// #equals() also accepts a two-dimensional array
+b.equals([[3, 3], [2, 2]]);
+// => true
+
+c.equals(d);
+// => false
+```
View
@@ -77,6 +77,8 @@ Once you have created your Matrix object, these methods are available to you:
* [raise](raise.md): Raises the current matrix to the *x<sup>th</sup>* power
* `raise` comes with a couple helper functions&mdash;calling `square()` is the same thing as calling `raise(2)`, and calling `cube()` is the same thing as calling `raise(3)`
* [scalar](scalar.md): Multiplies each element in the matrix by a scalar
+* [inverse](inverse.md): Inverts an *n* by *n* matrix
+* [equals](equals.md): Compares against another matrix
### Important note about all Matrix methods
View
@@ -0,0 +1,18 @@
+# Matrix#inverse()
+
+`Matrix#inverse()` does not take any parameters.
+
+## Errors
+
+`#inverse()` will throw an error if the matrix is not square (i.e., does not have the same number of rows and columns), or if the matrix is a 1x1.
+
+## Examples
+
+```javascript
+new Matrix([
+ [2, 0, -1],
+ [2, 1, 1],
+ [3, 4, 4]
+]).inverse().toArray();
+// => [[ 0, .8, -.2], [ 1, -2.2, .8], [-1, 1.6, -.4]]
+```
View
@@ -328,9 +328,78 @@
throwError('The matrix must be a square matrix with a size of at least 2x2');
}
+ // Declare variables
+ var ratio;
+ var a;
+ var n = this.rows;
+
+ // Put an identity matrix to the right of matrix
+ this.cols = 2 * n;
+ for (var i = 0; i < n; i++) {
+ for (var j = n; j < 2 * n; j++) {
+ if (i === (j - n)) {
+ this[i][j] = 1;
+ }
+ else {
+ this[i][j] = 0;
+ }
+ }
+ }
+
+ for (var i = 0; i < n; i++) {
+ for (var j = 0; j < n; j++) {
+ if (i !== j) {
+ ratio = this[j][i] / this[i][i];
+ for (var k = 0; k < 2 * n; k++) {
+ this[j][k] -= ratio * this[i][k];
+ }
+ }
+ }
+ }
+
+ for (var i = 0; i < n; i++) {
+ a = this[i][i];
+ for (var j = 0; j < 2 * n; j++) {
+ this[i][j] /= a;
+ }
+ }
+
+ // Rmove the left-hand identity matrix
+ for (var i = 0; i < n; i++) {
+ this[i].splice(0, n);
+ }
+ this.cols = n;
+
return this;
};
+ // Public: Returns whether or not the current matrix equals
+ // the passed matrix.
+ //
+ // Returns a boolean.
+ Matrix.prototype.equals = function(m) {
+ // Convert the argument to a Matrix object if it was an array
+ if (Array.isArray(m)) {
+ m = new Matrix(m);
+ }
+
+ // Return false if the dimensions do not match
+ if (this.rows !== m.rows || this.cols !== m.cols) {
+ return false;
+ }
+
+ // Check each location
+ for (var row = 0; row < this.rows; row++) {
+ for (var col = 0; col < this.cols; col++) {
+ if (this[row][col] !== m[row][col]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
// Public: Decides whether or not the matrix is square.
//
// Returns a boolean of whether or not the matrix is square.
View
@@ -210,6 +210,39 @@ describe('Matrix', function() {
});
});
+ describe('#inverse()', function() {
+ it('should invert a matrix', function() {
+ expect(new Matrix([
+ [2, 0, -1],
+ [2, 1, 1],
+ [3, 4, 4]
+ ]).inverse().toArray()).to.eql([
+ [ 0, .8, -.2],
+ [ 1, -2.2, .8],
+ [-1, 1.6, -.4]
+ ]);
+ });
+ });
+
+ describe('#equals()', function() {
+ it('should return true if the two matrices are equal', function() {
+ expect(m1.equals(m1.clone())).to.be(true);
+ });
+
+ it('should return false if the two matrices are not equal', function() {
+ expect(m1.equals(m3.clone())).to.be(false);
+ });
+
+ it('should return false if the dimensions are not the same', function() {
+ expect(m1.equals(m2.clone())).to.be(false);
+ });
+
+ it('should accept an array', function() {
+ expect(m1.equals(m1.toArray())).to.be(true);
+ expect(m1.equals(m3.toArray())).to.be(false);
+ });
+ });
+
describe('Matrix.identity', function() {
it('should create an identity matrix of any size', function() {
expect(new Matrix.identity(2).toArray()).to.eql([
@@ -242,4 +275,35 @@ describe('Matrix', function() {
}).to.not.throwError();
});
});
+
+ describe('#_setData()', function() {
+ it('should accept a two dimensional array', function() {
+ expect(m1._setData([[1,2], [3,4]]).toArray()).to.eql([[1,2], [3,4]]);
+ });
+
+ it('should accept a matrix object', function() {
+ expect(m1._setData(m2).toArray()).to.eql([
+ [2, 1],
+ [1, 1],
+ [3, 1]
+ ]);
+ });
+
+ it('should accept a function that takes the row and column numbers as parameters', function() {
+ expect(m1._setData(function(row, col) {
+ return row * col;
+ }).toArray()).to.eql([
+ [0, 0, 0],
+ [0, 1, 2],
+ [0, 2, 4]
+ ]);
+ });
+
+ it('should update the row and column count of the matrix', function() {
+ m1._setData([[1,2], [3,4]]);
+
+ expect(m1.rows).to.equal(2);
+ expect(m1.cols).to.equal(2);
+ });
+ });
});

0 comments on commit 0bc9536

Please sign in to comment.