blob: dfa7b9bef643c3e0a4757b46a9bb85d4c93550c5 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {ParallaxError} from '@parallax/common/error';
/**
* Contains a matrix
*/
export class Matrix<T> {
readonly numRows: number;
readonly numCols: number;
readonly array: T[][];
/**
* Creates new Matrix from an array of arrays.
*
* @param array Input matrix
*/
constructor(array: ReadonlyArray<ReadonlyArray<T>>) {
if (!Array.isArray(array)) {
throw new ParallaxError('Input be a 2D-array', {'array': array});
}
this.numRows = array.length;
this.numCols = array[0].length;
for (const column of array) {
if (!Array.isArray(column)) {
throw new ParallaxError('Columns must be arrays', {'column': column});
}
if (column.length !== this.cols) {
throw new ParallaxError(
'Columns must be the same length',
{'column.length': column.length, 'this.cols': this.cols});
}
}
this.array = array;
}
/**
* @return The number of rows
*/
get rows() {
return this.numRows;
}
/**
* @return The number of columns
*/
get cols() {
return this.numCols;
}
/**
* Creates a new Matrix as a transpose of the current matrix with the
* rows and columns swapped.
*
* @return New Matrix with the same elements transposed.
*/
transpose() {
const array: T[][] = Array(this.cols);
for (let i = 0; i < this.cols; i++) {
array[i] = Array(this.rows);
for (let j = 0; j < this.rows; j++) {
array[i][j] = this.array[j][i];
}
}
return new Matrix<T>(array);
}
/**
* Get the value at a specific index.
*
* @param row Row number
* @param col Column number
* @return Value at the specific row and column number.
*/
get(row: number, col: number) {
return this.array[row][col];
}
/**
* @return The raw array content.
*/
asArray(): ReadonlyArray<ReadonlyArray<T>> {
return this.array;
}
/**
* @return The data in a JSON serializable format.
*/
toJSON(): ReadonlyArray<ReadonlyArray<T>> {
return this.array;
}
}