Skip to content

Commit

Permalink
add checksum
Browse files Browse the repository at this point in the history
  • Loading branch information
sushovan4 committed Jul 24, 2021
1 parent e55ed2f commit 2529980
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tdajs/normal-form",
"version": "1.1.8",
"version": "1.2.0",
"description": "Smith Normal Form and utility",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions src/elementary-ops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function replaceRow(i: number, k: number, q: number, mat: number[][], opt
const result = opts.copy ? copyMat(mat) : mat;

for(let j = opts.offset || 0; j < result[0].length; j++)
result[i][j] += q * result[k][j];
result[i][j] += q * result[k][j];

const baseChangeMat: number[][] = opts.changeBase ? replaceRow(i, k, - q, idMat(result.length), {
copy: false,
Expand All @@ -105,7 +105,7 @@ export function multiplyRow(i: number, q: number, mat: number[][], options?: Opt
const result = opts.copy ? copyMat(mat) : mat;
result[i] = result[i].map(val => q * val );

const baseChangeMat: number[][] = opts.changeBase ? multiplyRow(i, - q, idMat(result.length), {
const baseChangeMat: number[][] = opts.changeBase ? multiplyRow(i, q, idMat(result.length), {
copy: false,
changeBase: false
})[0] : [];
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { changeBasis, mat2Tex, vec2Tex, isZero, findPivot, findAntiPivot, idMat, improvePivot } from './utils';
export { changeBasis, mat2Tex, vec2Tex, isZero, findPivot, findAntiPivot, idMat, improvePivot, multiplyMat } from './utils';
export { NormalForm, NFOpts } from './normal-form';
export { exchangeRows, exchangeCols, multiplyCol, multiplyRow, replaceRow, replaceCol, Options } from './elementary-ops';
69 changes: 48 additions & 21 deletions src/normal-form.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { copyMat, idMat, multiplyMat } from './utils';
import { copyMat, equalMatrix, idMat, multiplyMat } from './utils';
import { exchangeCols, exchangeRows, replaceCol, replaceRow, multiplyRow, multiplyCol } from './elementary-ops';
import { findAntiPivot, isZero, findPivot } from './utils'

Expand Down Expand Up @@ -96,6 +96,10 @@ class NormalForm {
* Optional arguments
*/
opts: NFOpts;
/**
*
*/
Qinv: number[][];

constructor(mat: number[][], options?: NFOpts)
{
Expand All @@ -117,27 +121,32 @@ class NormalForm {
this.m = this.A[0].length;

this.D = this.opts.copy ? copyMat(mat) : mat;
[this.P, this.Q] = this.opts.changeBases ? [idMat(this.m), idMat(this.n)] : [[[]],[[]]];
[this.P, this.Q, this.Qinv] = this.opts.changeBases ?
[idMat(this.m), idMat(this.n), idMat(this.n)] : [[], [], []];

this.diag = new Array<number>();
this.reduce(0, Math.min(this.m, this.n));
// Check sum
if(! equalMatrix( multiplyMat(this.A, this.P), multiplyMat(this.Q, this.D) ) )
throw new Error('Reduction failed.');
}

private reduce(startOffset: number, endOffset: number) {
if( startOffset >= endOffset || isZero(this.D, startOffset) )
return;

let [i,j] = this.improvePivot(startOffset);
this.addStep({ name: "improvedPivot", pivot: [i,j], antiPivot: [], offset: startOffset });
this.movePivot([i,j], startOffset);
this.diagonalizePivot(startOffset);
this.addStep({ name: "offset", offset: startOffset });
this.diag.push(this.D[startOffset][startOffset]);
this.reduce(startOffset + 1, endOffset);
}

let [i,j] = this.improvePivot(startOffset);
this.addStep({ name: "improvedPivot", pivot: [i,j], antiPivot: [], offset: startOffset });
this.movePivot([i,j], startOffset);
this.diagonalizePivot(startOffset);
this.addStep({ name: "offset", offset: startOffset });
this.diag.push(this.D[startOffset][startOffset]);
this.reduce(startOffset + 1, endOffset);
}

private improvePivot(offset: number) {
let i,j: number; // Pivot position

while(true) {
[i,j] = findPivot(this.D, offset);

Expand All @@ -152,7 +161,10 @@ class NormalForm {
if(j === t) {
let q = - Math.floor(this.D[s][j] / this.D[i][j]);
let Q = replaceRow(s, i, q, this.D, { offset: offset, changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);
if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this.Qinv = multiplyMat(replaceRow(s, i, q, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "replaceRow", args: [s, i, q], offset: offset });
}
else if(i === s) {
Expand All @@ -165,12 +177,18 @@ class NormalForm {
if(this.D[s][j] !== 0) {
let q = - Math.floor(this.D[s][j] / this.D[i][j]);
let Q = replaceRow(s, i, q, this.D, { offset: offset, changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);
if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this.Qinv = multiplyMat(replaceRow(s, i, q, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "replaceRow", args: [s, i, q], offset: offset });
}

let Q = replaceRow(i, s, 1, this.D, { offset: offset, changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);
if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this.Qinv = multiplyMat(replaceRow(i, s, 1, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "replaceRow", args: [i, s, 1], offset: offset });

let q = - Math.floor(this.D[i][t] / this.D[i][j]);
Expand All @@ -182,11 +200,13 @@ class NormalForm {
return [i,j];
}

private movePivot([i,j]: [number,number], offset: number) {

private movePivot([i,j]: [number,number], offset: number) {
if(i !== offset) {
let Q = exchangeRows(offset, i, this.D, { changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);
if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this.Qinv = multiplyMat(exchangeRows(offset, i, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "exchangeRows", args: [offset, i], offset: offset });
}
if(j !== offset) {
Expand All @@ -196,7 +216,11 @@ class NormalForm {
}
if(this.D[offset][offset] < 0 ) {
let Q = multiplyRow(offset, -1, this.D, { changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);

if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this.Qinv = multiplyMat(multiplyRow(offset, -1, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "multiplyRow", args: [offset, -1], offset: offset });
}
}
Expand All @@ -208,7 +232,10 @@ class NormalForm {
continue;
let q = - Math.floor(this.D[i][offset] / this.D[offset][offset]);
let Q = replaceRow(i, offset, q, this.D, { offset: offset, changeBase: this.opts.changeBases })[1];
if(this.opts.changeBases) this.Q = multiplyMat(this.Q, Q);
if(this.opts.changeBases) {
this.Q = multiplyMat(this.Q, Q);
this .Qinv = multiplyMat(replaceRow(i, offset, q, idMat(this.n), { offset: offset, changeBase: this.opts.changeBases })[0], this.Qinv);
}
this.addStep({ name: "replaceRow", args: [i, offset], offset: offset })
}

Expand Down
10 changes: 7 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,11 @@ export function multiplyMat(A: number[][], B: number[][]) {
for(let i = 0; i < A.length; i++)
for(let j = 0; j < B[0].length; j++) {
let sum = 0;
for(let k = 0; k < A[0].length; k++)
for(let k = 0; k < A[0].length; k++) {
sum += A[i][k] * B[k][j];
if(!Number.isSafeInteger(sum))
throw new Error('Integers too big.');
}
prod[i][j] = sum;
}
return prod;
Expand All @@ -141,7 +144,6 @@ export function equalMatrix(A: number[][], B: number[][]) {
for(let i = 0; i < A.length; i++)
for(let j = 0; j < A[0].length; j++)
if(A[i][j] !== B[i][j]) {
console.log(A[i][j] + ':' + B[i][j]);
return false;
}
return true;
Expand All @@ -150,8 +152,10 @@ export function equalMatrix(A: number[][], B: number[][]) {
export function isZero(mat: number[][], offset: number = 0) {
for(let i = offset; i < mat.length; i++)
for(let j = offset; j < mat[0].length; j++) {
if(!Number.isSafeInteger(mat[i][j]))
throw new Error('Integers too big.');
if(mat[i][j] !== 0)
return false;
return false;
}
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2017",
"target": "esnext",
"module": "commonjs",
"removeComments": true,
"declaration": true,
Expand Down

0 comments on commit 2529980

Please sign in to comment.