#include "CORE/CORE.h" #include "CORE/LinearAlgebra.h" using namespace std; // Normally, we want the inverse of U as in // A = U^{-1}SV // But since I can't find matrix inversion in CORE, // we want U so that we can test if A=U*S*V. //#define INVERSE_U 1 // public interface // returns a vector 's' such that // A = U^{-1} * diag(s) * V. Vector SNF(const Matrix &A, Matrix &U, Matrix &V); Vector SNF(const Matrix &A); // On input S=A. // On output, S is reduced to Smith Normal Form. // U and V can be optional. void getSNF(Matrix &S, Matrix *U = 0, Matrix *V = 0); // // internal stuff below // Vector diag(const Matrix &A) { int r = min(A.dimension_1(), A.dimension_2()); Vector v(r); for(int i=0; idimension_1(); i++) (*U)(i,i) = 1; } if (V) { *V = Matrix(S.dimension_2()); for(int i=0; i< V->dimension_1(); i++) (*V)(i,i) = 1; } int r=min(S.dimension_1(), S.dimension_2()); int k=0; while(k < r) { int i,j; if (!findMinEntry(S,k, i,j)) return; // no more entry left bool allZero = reduceRowCol(k,i,j, S,U,V); if (allZero) { int u,v; if (findNonDivide(S,k,i,j, u,v)) { addRow2Row(i, u, 1, S,U,V); reduceRowCol(k,u,j, S,U,V); } else { pivotAway(k,i,j,S, U, V); k++; } } } // make sure all diagonal entries are nonnegative for(int i=0; i