This repository has been archived on 2022-10-20. You can view files and clone it, but cannot push or open issues or pull requests.
Math/matrix.ts

180 lines
4.4 KiB
TypeScript

export type RawMatrix = number[][];
export class Matrix {
rows!: number;
cols!: number;
matrix!: RawMatrix;
static zero(rows: number, cols: number) {
let matrix: RawMatrix = [];
for(let i=0; i<rows; i++) {
matrix.push([]);
for(let j=0; j<cols; j++) {
matrix[i].push(0);
}
}
return new Matrix(...matrix);
}
constructor(...matrix: RawMatrix) {
this.set(...matrix);
}
set(...matrix: RawMatrix) {
this.matrix = matrix;
this.rows = matrix.length;
if(matrix.length == 0) throw Error("Empty matrix");
this.cols = matrix[0].length;
for(let i=0; i<matrix.length; i++) {
if(matrix[i].length !== this.cols) throw Error("Invalid matrix row " + (i+1));
}
}
add(other_matrix: Matrix) {
if(!(other_matrix.cols == this.cols && other_matrix.rows == this.rows)) throw Error("Other matrix has more or few rows or columns");
for(let i=0; i<this.matrix.length; i++) {
for(let j=0; j<this.matrix[i].length; j++) {
this.matrix[i][j] += other_matrix.matrix[i][j];
}
}
return this;
}
sub(other_matrix: Matrix) {
if(!(other_matrix.cols == this.cols && other_matrix.rows == this.cols)) throw Error("Other matrix has more or few rows or columns");
for(let i=0; i<this.matrix.length; i++) {
for(let j=0; j<this.matrix[i].length; j++) {
this.matrix[i][j] -= other_matrix.matrix[i][j];
}
}
return this;
}
mul(other: Matrix | number) {
if(other instanceof Matrix) {
if(!(this.cols == other.rows)) throw Error("These matrices cannot be multiplied");
let final_matrix: RawMatrix = [];
for(let a_row_i=0; a_row_i<this.matrix.length; a_row_i++) {
final_matrix.push([]);
for(let b_col_i=0; b_col_i<other.matrix[0].length; b_col_i++) {
let sum = 0;
for(let a_col_b_row_i=0; a_col_b_row_i<this.matrix[0].length; a_col_b_row_i++) {
sum += this.matrix[a_row_i][a_col_b_row_i] * other.matrix[a_col_b_row_i][b_col_i];
}
final_matrix[a_row_i].push(sum);
}
}
return new Matrix(...final_matrix);
} else {
for(let i=0; i<this.matrix.length; i++) {
for(let j=0; j<this.matrix[i].length; j++) {
this.matrix[i][j] = this.matrix[i][j] * other;
}
}
return this;
}
}
pow(power: number) {
for(let i=0; i<(power-1); i++)
this.set(...this.mul(this).matrix);
return this;
}
invert() {
this.matrix = this.mul(-1).matrix;
return this;
}
transpose() {
let new_matrix = Matrix.zero(this.cols, this.rows);
for(let i=0; i<this.rows; i++) {
for(let j=0; j<this.cols; j++) {
new_matrix.matrix[j][i] = this.matrix[i][j];
}
}
return new_matrix;
}
eq(other_matrix: Matrix) {
if(this.rows != other_matrix.rows || this.cols != other_matrix.cols) return false;
for(let i=0; i<this.rows; i++) {
for(let j=0; j<this.cols; j++) {
if(this.matrix[i][j] != other_matrix.matrix[i][j]) return false;
}
}
return true;
}
in_stepped_shape() {
let pivot_index = -1;
for(let i=0; i<this.rows; i++) {
for(let j=0; j<this.cols; j++) {
console.log(this.matrix[i][j], pivot_index);
if(this.matrix[i][j] == 0) {
if(j > pivot_index) pivot_index = j;
} else if(pivot_index >= j) return false;
}
pivot_index++;
}
return true;
}
pivots() {
let pivots: number[] = [];
for(let i=0; i<this.rows; i++) {
let col = 0;
for(let j=0; j<this.cols; j++) {
if(this.matrix[i][j] != 0) break;
col++;
}
pivots.push(col);
}
return pivots;
}
}
export class GaussianElimination {
matrix: Matrix;
constructor(matrix: Matrix) {
this.matrix = matrix;
}
sort() {
let matrix = this.matrix.matrix;
let new_matrix = [matrix[0]];
let pivots = this.matrix.pivots();
for(let i=1; i<pivots.length; i++) {
if(pivots[i] < pivots[i-1]) new_matrix.unshift(matrix[i]);
else new_matrix.push(matrix[i]);
}
this.matrix.set(...new_matrix);
}
solve() {
for(let v_offset=0; v_offset<this.matrix.rows; v_offset++) {
this.sort();
let matrix = this.matrix.matrix;
let h_offset = this.matrix.pivots()[v_offset];
let first_number = matrix[v_offset][h_offset];
for(let i=1+v_offset; i<matrix.length; i++) {
let n = -matrix[i][h_offset]/first_number;
this.matrix.matrix[i] = matrix[i].map((c, j) => c + n*matrix[v_offset][j]);
}
}
return this.matrix;
}
mul_row(index: number, number: number, replace: boolean = false) {
let row = this.matrix.matrix[index].map(original => number * original);
if(replace) this.matrix.matrix[index] = row;
return row;
}
}