/* * lib_zmatrix.h * * Created on: Sep 28, 2010 * Author: anders */ #ifndef LIB_ZMATRIX_H_ #define LIB_ZMATRIX_H_ #include #include #include "gfanlib_vector.h" namespace gfan{ template class Matrix{ int width,height; std::vector > rows; public: inline int getHeight()const{return height;}; inline int getWidth()const{return width;}; Matrix(const Matrix &a):rows(a.rows),width(a.getWidth()),height(a.getHeight()){ } Matrix(int height_, int width_):rows(height_),height(height_),width(width_){ assert(height>=0); assert(width>=0); for(int i=0;i(width); }; ~Matrix(){ }; Matrix():width(0),height(0){ }; static Matrix rowVectorMatrix(Vector const &v) { Matrix ret(1,v.size()); for(int i=0;i column(int i)const { assert(i>=0); assert(i ret(getHeight()); for(int j=0;j::standardVector(n,i); return m; } void append(Matrix const &m) { for(int i=0;i const &v) { assert(v.size()==width); rows.push_back(v); height++; } void eraseLastRow() { assert(rows.size()>0); rows.resize(rows.size()-1); height--; } /*IntegerVector vectormultiply(IntegerVector const &v)const { assert(v.size()==width); IntegerVector ret(height); for(int i=0;i Matrix(const Matrix& c):v(c.size()){ for(int i=0;i=0); assert(startColumn>=0); assert(endRow>=startRow); assert(endColumn>=startColumn); assert(endRow<=height); assert(endColumn<=width); Matrix ret(endRow-startRow,endColumn-startColumn); for(int i=startRow;i& operator[](int n)const{assert(n>=0 && n& operator[](int n){if(!(n>=0 && n*)(this))[n];}return (rows[n]);} bool operator<(const Matrix & b)const { if(getWidth()=0 && i=0 && j=height)return false; while(++j pivotColumns()const { std::vector ret; int pivotI=-1; int pivotJ=-1; while(nextPivot(pivotI,pivotJ))ret.push_back(pivotJ); return ret; } /** Returns the indices of the columns not containing a pivot. The returned list is sorted. The matrix must be in row echelon form. */ std::vector nonPivotColumns()const { std::vector ret; int pivotI=-1; int pivotJ=-1; int firstPossiblePivot=0; while(nextPivot(pivotI,pivotJ)) { for(int j=firstPossiblePivot;jzHomomorphism(-(((int)(d+10000.5))-10000)); s.madd(multiplier,u); t.madd(multiplier,v); }*/ for(int k=0;k canonicalize(Vector v)const { assert(typ::isField()); assert(v.size()==getWidth()); int pivotI=-1; int pivotJ=-1; while(nextPivot(pivotI,pivotJ)) if(!v[pivotJ].isZero()) { typ s=-v[pivotJ]/rows[pivotI][pivotJ]; for(int k=0;k reduceAndComputeVectorInKernel() { assert(typ::isField()); // TODO: (optimization) if the field is ordered, then it is better to just keep track of signs rather than // multiplying by sign*diagonalProduct*lastEntry at the end. int nswaps=this->reduce(); typ sign=typ(1-2*(nswaps&1)); int rank=reduceAndComputeRank(); assert(rank+1==width); REformToRREform(); Vector ret(width); typ diagonalProduct(1); { int pivot2I=-1; int pivot2J=-1; while(nextPivot(pivot2I,pivot2J)) { diagonalProduct*=rows[pivot2I][pivot2J]; } } { int j=nonPivotColumns().front(); int pivot2I=-1; int pivot2J=-1; ret[j]=typ(-1); // Pretend that we are appending ret to the matrix, and reducing this // new row by the previous ones. The last entry of the resulting matrix // is lastEntry. typ lastEntry=ret[j]; while(nextPivot(pivot2I,pivot2J)) { ret[pivot2J]=rows[pivot2I][j]/rows[pivot2I][pivot2J]; lastEntry-=ret[pivot2J]*ret[pivot2J]; } ret=(sign*(diagonalProduct*lastEntry))*ret; } return ret; } /** Calls reduce() and returns the rank of the matrix. */ int reduceAndComputeRank() { reduce(); int ret=0; int pivotI=-1; int pivotJ=-1; while(nextPivot(pivotI,pivotJ))ret++; return ret; } /** * Sort the rows of the matrix. */ void sortRows() { std::sort(rows.begin(),rows.end()); } /** * Sort the rows of the matrix and remove duplicate rows. */ void sortAndRemoveDuplicateRows() { sortRows(); if(getHeight()==0)return; Matrix B(0,getWidth()); B.appendRow((*this)[0]); for(int i=1;i ZMatrix; typedef Matrix QMatrix; typedef Matrix IntMatrix; inline QMatrix ZToQMatrix(ZMatrix const &m) { QMatrix ret(m.getHeight(),m.getWidth()); for(int i=0;i