Created
May 10, 2022 17:23
-
-
Save Animesh-Ghosh/a47243d27028617f06c5fe38b01cac6a to your computer and use it in GitHub Desktop.
JavaScript Matrix class with usage examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @classdesc a class for doing common Matrix operations | |
| * | |
| */ | |
| class Matrix { | |
| /** | |
| * @param {Array} array a 2d array | |
| */ | |
| constructor(array) { | |
| let numberOfColumns = array[0].length | |
| // verify all rows have equal number of elements | |
| for (const row of array.slice(1)) { | |
| if (row.length != numberOfColumns) { | |
| throw new Error('Array provided does not have equal number of elements within sub-Arrays!') | |
| } | |
| } | |
| this.array = array | |
| this.order = [this.array.length, this.array[0].length] | |
| } | |
| /** | |
| * @param {Number} order the order of the Identity Matrix | |
| * | |
| * @return {Matrix} the Identity Matrix of the specified order | |
| */ | |
| static identity(order) { | |
| if (order < 2) { | |
| throw new Error('Invalid Matrix order specified!') | |
| } | |
| let array = [] | |
| for (let i = 0; i < order; ++i) { | |
| let subArray = [] | |
| for (let j = 0; j < order; ++j) { | |
| if (i == j) { | |
| subArray.push(1) | |
| } else { | |
| subArray.push(0) | |
| } | |
| } | |
| array.push(subArray) | |
| } | |
| return new Matrix(array) | |
| } | |
| /** | |
| * @param {Matrix} another Matrix | |
| * | |
| * @return {Matrix} the sum of both Matrices | |
| */ | |
| add(matrix) { | |
| // check if Matrices are compatible | |
| if ( | |
| !( | |
| this.order[0] == matrix.order[0] && this.order[1] == matrix.order[1] | |
| ) | |
| ) { | |
| throw new Error('Matrices are NOT of the same order!') | |
| } | |
| let array = [] | |
| for (let i = 0; i < this.order[0]; ++i) { | |
| let subArray = [] | |
| for (let j = 0; j < this.order[1]; ++j) { | |
| subArray.push(0) | |
| } | |
| array.push(subArray) | |
| } | |
| for (let i = 0; i < this.order[0]; ++i) { | |
| for (let j = 0; j < this.order[1]; ++j) { | |
| array[i][j] = this.array[i][j] + matrix.array[i][j] | |
| } | |
| } | |
| return new Matrix(array) | |
| } | |
| /** | |
| * @param {Matrix} another Matrix | |
| * | |
| * @return {Matrix} the difference between the Matrices | |
| */ | |
| subtract(matrix) { | |
| return this.add(matrix.multiply(-1)) | |
| } | |
| /** | |
| * @param {Number|Matrix} scalarOrMatrix a scalar value or another Matrix | |
| * | |
| * | |
| * @return {Matrix} the product of the multiplication | |
| */ | |
| multiply(scalarOrMatrix) { | |
| if (typeof scalarOrMatrix == 'number') { | |
| return this.scalarMultiply(scalarOrMatrix) | |
| } else if (scalarOrMatrix instanceof Matrix) { | |
| return this.matrixMultiply(scalarOrMatrix) | |
| } else { | |
| throw new TypeError('Unknown type specified!') | |
| } | |
| } | |
| /** | |
| * @param {Number} a scalar | |
| * | |
| * @return {Matrix} the result of the product | |
| */ | |
| scalarMultiply(scalar) { | |
| return new Matrix(this.array.map(row => { | |
| row = row.map(column => column * scalar) | |
| return row | |
| })) | |
| } | |
| /** | |
| * @param {Matrix} another Matrix | |
| * | |
| * @return {Matrix} the result of the Matrix multiplication | |
| */ | |
| matrixMultiply(matrix) { | |
| // check if Matrices are compatible | |
| if (!this.order[1] == matrix.order[0]) { | |
| throw new Error('Matrices are NOT of the same order!') | |
| } | |
| let array = [] | |
| for (let i = 0; i < this.order[0]; ++i) { | |
| let subArray = [] | |
| for (let j = 0; j < matrix.order[1]; ++j) { | |
| subArray.push(0) | |
| } | |
| array.push(subArray) | |
| } | |
| for (let i = 0; i < this.order[0]; ++i) { | |
| let row = this.array[i] | |
| for (let j = 0; j < matrix.order[1]; ++j) { | |
| let column = Array.from(matrix.array, v => v[j]) | |
| const sum = row.map((el, idx) => [el, column[idx]]) | |
| .reduce((sum, zip) => sum + zip.reduce((product, el) => product * el, 1), 0) | |
| array[i][j] = sum | |
| } | |
| } | |
| return new Matrix(array) | |
| } | |
| toArray() { | |
| return this.array | |
| } | |
| } | |
| const m1 = new Matrix([ | |
| [1, 2], | |
| [3, 4], | |
| ]) | |
| const m2 = new Matrix([ | |
| [2, 2], | |
| [1, 4], | |
| ]) | |
| const sum = m1.add(m2) | |
| const difference = m1.subtract(m2) | |
| const scaledMatrix = m1.multiply(2) | |
| const identity = Matrix.identity(3) | |
| const m3 = new Matrix([ | |
| [1, 2, 3], | |
| [2, 3, 4], | |
| [3, 4, 5], | |
| ]) | |
| const product = m3.multiply(identity) | |
| const m4 = new Matrix([ | |
| [1, 2], | |
| [5, 5], | |
| [0, 0], | |
| ]) | |
| const anotherProduct = product.multiply(m4) | |
| console.log(m1) | |
| console.log(m2) | |
| console.log('Sum:', sum) | |
| console.log('Difference:', difference) | |
| console.log('Scalar Product:', scaledMatrix) | |
| console.log('Identity:', identity) | |
| console.log(m3) | |
| console.log('Product with Indentity:', product) | |
| console.log(m4) | |
| console.log('Product:', anotherProduct) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment