class Mat {
constructor(m, n) {
if(Number.isInteger(m)) {
if(n == undefined) n = m;
this.m = m;
this.n = n;
this.rows = [];
for(let i = 1; i<=m; ++i) {
const columns = [];
for(let j = 1; j<=n; ++j) {
columns.push(new Ex(0));
}
this.rows.push(columns);
}
}
if(Array.isArray(m)) {
this.rows = m;
this.m = m.length;
for(let i=0; i<this.m;++i) {
if(!Array.isArray(this.rows[i])) {
this.rows[i] = [this.rows[i]];
}
this.n = this.rows[i].length;
}
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=this.n; ++j) {
this.set(i, j, new Ex(this.get(i, j)));
}
}
}
}
get(i, j) {
return this.rows[i-1][j-1];
}
set(i, j, v) {
this.rows[i-1][j-1] = v;
}
copy() {
const r = new Mat(this.m, this.n);
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=this.n; ++j) {
r.set(i, j, this.get(i, j));
}
}
return r;
}
add(m) {
const r = new Mat(this.m, this.n);
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=this.n; ++j) {
r.set(i, j, this.get(i, j).add(m.get(i, j)));
}
}
return r;
}
mul(m) {
const r = new Mat(this.m, m.n);
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=m.n; ++j) {
let v = new Ex(0);
for(let k=1; k<= this.n; ++k) {
v = v.add(this.get(i,k).mul(m.get(k,j)));
}
r.set(i, j, v);
}
}
return r;
}
tex() {
let r = '';
r = r + '\\left[\\begin{matrix}';
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=this.n; ++j) {
r = r + this.get(i, j).tex();
if(j!=this.n) r = r + '&';
}
if(i!=this.m) r = r + '\\\\';
}
r = r + '\\end{matrix}\\right]';
return r;
}
del(ii, jj) {
const r = new Mat(this.m-1, this.n-1);
for(let i = 1; i<=this.m; ++i) {
if(i == ii) continue;
for(let j = 1; j<=this.n; ++j) {
if(j == jj) continue;
r.set(i-(i>ii? 1 : 0), j-(j>jj? 1 : 0), this.get(i, j));
}
}
return r;
}
det() {
if(this.m == this.n) {
if(this.m == 1) return this.get(1,1);
let r = new Ex(0);
const ra = Array.from(Array(this.m), (_, i) => i + 1);
for(let p of permutations(ra)) {
let s = new Ex(sign(p));
for(let i = 1;i<=this.m;++i) {
s = s.mul(this.get(i, p[i-1]));
}
r = r.add(s);
}
return r;
}
}
transpose() {
const r = new Mat(this.n, this.m);
for(let i = 1; i<=this.m; ++i) {
for(let j = 1; j<=this.n; ++j) {
r.set(j, i, this.get(i, j));
}
}
return r;
}
rswap(i1, i2) {
const r = this.rows[i1-1];
this.rows[i1-1] = this.rows[i2-1];
this.rows[i2-1] = r;
}
rscale(i, k) {
for(let j = 1; j<=this.n; ++j) {
this.set(i, j, k.mul(this.get(i, j)));
}
}
radd(i1, i2, k) {
for(let j = 1; j<=this.n; ++j) {
this.set(i1, j, this.get(i1, j).add(k.mul(this.get(i2, j))));
}
}
}