Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418425/*1* Normaliz2* Copyright (C) 2007-2014 Winfried Bruns, Bogdan Ichim, Christof Soeger3* This program is free software: you can redistribute it and/or modify4* it under the terms of the GNU General Public License as published by5* the Free Software Foundation, either version 3 of the License, or6* (at your option) any later version.7*8* This program is distributed in the hope that it will be useful,9* but WITHOUT ANY WARRANTY; without even the implied warranty of10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11* GNU General Public License for more details.12*13* You should have received a copy of the GNU General Public License14* along with this program. If not, see <http://www.gnu.org/licenses/>.15*16* As an exception, when this program is distributed through (i) the App Store17* by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or (iii) Google Play18* by Google Inc., then that store may impose any digital rights management,19* device limits and/or redistribution restrictions that are required by its20* terms of service.21*/2223//---------------------------------------------------------------------------2425#include <fstream>26#include <set>27#include <algorithm>28#include <math.h>2930#include "libQnormaliz/Qmatrix.h"31#include "libQnormaliz/Qvector_operations.h"32#include "libQnormaliz/Qnormaliz_exception.h"33#include "libQnormaliz/Qsublattice_representation.h"3435//---------------------------------------------------------------------------3637namespace libQnormaliz {38using namespace std;3940//---------------------------------------------------------------------------41//Public42//---------------------------------------------------------------------------4344template<typename Number>45Matrix<Number>::Matrix(){46nr=0;47nc=0;48}4950//---------------------------------------------------------------------------5152template<typename Number>53Matrix<Number>::Matrix(size_t dim){54nr=dim;55nc=dim;56elem = vector< vector<Number> >(dim, vector<Number>(dim));57for (size_t i = 0; i < dim; i++) {58elem[i][i]=1;59}60}6162//---------------------------------------------------------------------------6364template<typename Number>65Matrix<Number>::Matrix(size_t row, size_t col){66nr=row;67nc=col;68elem = vector< vector<Number> >(row, vector<Number>(col));69}7071//---------------------------------------------------------------------------7273template<typename Number>74Matrix<Number>::Matrix(size_t row, size_t col, Number value){75nr=row;76nc=col;77elem = vector< vector<Number> > (row, vector<Number>(col,value));78}7980//---------------------------------------------------------------------------8182template<typename Number>83Matrix<Number>::Matrix(const vector< vector<Number> >& new_elem){84nr=new_elem.size();85if (nr>0) {86nc=new_elem[0].size();87elem=new_elem;88//check if all rows have the same length89for (size_t i=1; i<nr; i++) {90if (elem[i].size() != nc) {91throw BadInputException("Inconsistent lengths of rows in matrix!");92}93}94} else {95nc=0;96}97}9899//---------------------------------------------------------------------------100101template<typename Number>102Matrix<Number>::Matrix(const list< vector<Number> >& new_elem){103nr = new_elem.size();104elem = vector< vector<Number> > (nr);105nc = 0;106size_t i=0;107typename list< vector<Number> >::const_iterator it=new_elem.begin();108for(; it!=new_elem.end(); ++it, ++i) {109if(i == 0) {110nc = (*it).size();111} else {112if ((*it).size() != nc) {113throw BadInputException("Inconsistent lengths of rows in matrix!");114}115}116elem[i]=(*it);117}118}119120//---------------------------------------------------------------------------121/*122template<typename Number>123void Matrix<Number>::write(istream& in){124size_t i,j;125for(i=0; i<nr; i++){126for(j=0; j<nc; j++) {127in >> elem[i][j];128}129}130}131*/132//---------------------------------------------------------------------------133134template<typename Number>135void Matrix<Number>::write_column(size_t col, const vector<Number>& data){136assert(col >= 0);137assert(col < nc);138assert(nr == data.size());139140for (size_t i = 0; i < nr; i++) {141elem[i][col]=data[i];142}143}144145//---------------------------------------------------------------------------146147template<typename Number>148void Matrix<Number>::print(const string& name,const string& suffix) const{149string file_name = name+"."+suffix;150const char* file = file_name.c_str();151ofstream out(file);152print(out);153out.close();154}155156//---------------------------------------------------------------------------157158template<typename Number>159void Matrix<Number>::print_append(const string& name,const string& suffix) const{160string file_name = name+"."+suffix;161const char* file = file_name.c_str();162ofstream out(file,ios_base::app);163print(out);164out.close();165}166167//---------------------------------------------------------------------------168169template<typename Number>170void Matrix<Number>::print(ostream& out) const{171size_t i,j;172out<<nr<<endl<<nc<<endl;173for (i = 0; i < nr; i++) {174for (j = 0; j < nc; j++) {175out<<elem[i][j]<<" ";176}177out<<endl;178}179}180181//---------------------------------------------------------------------------182183template<typename Number>184void Matrix<Number>::pretty_print(ostream& out, bool with_row_nr) const{185if(nr>1000000 && !with_row_nr){186print(out);187return;188}189size_t i,j,k;190vector<size_t> max_length = maximal_decimal_length_columnwise();191size_t max_index_length = decimal_length(nr);192for (i = 0; i < nr; i++) {193if (with_row_nr) {194for (k= 0; k <= max_index_length - decimal_length(i); k++) {195out<<" ";196}197out << i << ": ";198}199for (j = 0; j < nc; j++) {200ostringstream to_print;201to_print << elem[i][j];202for (k= 0; k <= max_length[j] - to_print.str().size(); k++) {203out<<" ";204}205out<< to_print.str();206}207out<<endl;208}209}210211/*212* string to_print;213ostringstream(to_print) << elem[i][j];214cout << elem[i][j] << " S " << to_print << " L " << decimal_length(elem[i][j]) << endl;215for (k= 0; k <= max_length[j] - to_print.size(); k++) {216out<<" ";217}218out << to_print;219*/220//---------------------------------------------------------------------------221222template<typename Number>223size_t Matrix<Number>::nr_of_rows () const{224return nr;225}226227//---------------------------------------------------------------------------228229template<typename Number>230size_t Matrix<Number>::nr_of_columns () const{231return nc;232}233234//---------------------------------------------------------------------------235236template<typename Number>237void Matrix<Number>::set_nr_of_columns(size_t c){238nc=c;239}240241//---------------------------------------------------------------------------242243template<typename Number>244void Matrix<Number>::random (int mod) {245size_t i,j;246int k;247for (i = 0; i < nr; i++) {248for (j = 0; j < nc; j++) {249k = rand();250elem[i][j]=k % mod;251}252}253}254//---------------------------------------------------------------------------255256template<typename Number>257void Matrix<Number>::set_zero() {258size_t i,j;259for (i = 0; i < nr; i++) {260for (j = 0; j < nc; j++) {261elem[i][j] = 0;262}263}264}265266//---------------------------------------------------------------------------267268template<typename Number>269void Matrix<Number>::select_submatrix(const Matrix<Number>& mother, const vector<key_t>& rows){270271assert(nr>=rows.size());272assert(nc>=mother.nc);273274size_t size=rows.size(), j;275for (size_t i=0; i < size; i++) {276j=rows[i];277for(size_t k=0;k<mother.nc;++k)278elem[i][k]=mother[j][k];279}280}281282//---------------------------------------------------------------------------283284template<typename Number>285void Matrix<Number>::select_submatrix_trans(const Matrix<Number>& mother, const vector<key_t>& rows){286287assert(nc>=rows.size());288assert(nr>=mother.nc);289290size_t size=rows.size(), j;291for (size_t i=0; i < size; i++) {292j=rows[i];293for(size_t k=0;k<mother.nc;++k)294elem[k][i]=mother[j][k];295}296}297298//---------------------------------------------------------------------------299300template<typename Number>301Matrix<Number> Matrix<Number>::submatrix(const vector<key_t>& rows) const{302size_t size=rows.size(), j;303Matrix<Number> M(size, nc);304for (size_t i=0; i < size; i++) {305j=rows[i];306assert(j >= 0);307assert(j < nr);308M.elem[i]=elem[j];309}310return M;311}312313//---------------------------------------------------------------------------314315template<typename Number>316Matrix<Number> Matrix<Number>::submatrix(const vector<int>& rows) const{317size_t size=rows.size(), j;318Matrix<Number> M(size, nc);319for (size_t i=0; i < size; i++) {320j=rows[i];321assert(j >= 0);322assert(j < nr);323M.elem[i]=elem[j];324}325return M;326}327328//---------------------------------------------------------------------------329330template<typename Number>331Matrix<Number> Matrix<Number>::submatrix(const vector<bool>& rows) const{332assert(rows.size() == nr);333size_t size=0;334for (size_t i = 0; i <rows.size(); i++) {335if (rows[i]) {336size++;337}338}339Matrix<Number> M(size, nc);340size_t j = 0;341for (size_t i = 0; i < nr; i++) {342if (rows[i]) {343M.elem[j++] = elem[i];344}345}346return M;347}348349//---------------------------------------------------------------------------350351template<typename Number>352Matrix<Number>& Matrix<Number>::remove_zero_rows() {353size_t from = 0, to = 0; // maintain to <= from354while (from < nr && v_is_zero(elem[from])) from++; //skip zero rows355while (from < nr) { // go over matrix356// now from is a non-zero row357if (to != from) elem[to].swap(elem[from]);358++to; ++from;359while (from < nr && v_is_zero(elem[from])) from++; //skip zero rows360}361nr = to;362elem.resize(nr);363return *this;364}365366//---------------------------------------------------------------------------367368template<typename Number>369void Matrix<Number>::swap(Matrix<Number>& x) {370size_t tmp = nr; nr = x.nr; x.nr = tmp;371tmp = nc; nc = x.nc; x.nc = tmp;372elem.swap(x.elem);373}374375//---------------------------------------------------------------------------376377template<typename Number>378void Matrix<Number>::resize(size_t nr_rows, size_t nr_cols) {379nc = nr_cols; //for adding new rows with the right length380resize(nr_rows);381resize_columns(nr_cols);382}383384template<typename Number>385void Matrix<Number>::resize(size_t nr_rows) {386if (nr_rows > elem.size()) {387elem.resize(nr_rows, vector<Number>(nc));388}389nr = nr_rows;390}391392template<typename Number>393void Matrix<Number>::resize_columns(size_t nr_cols) {394for (size_t i=0; i<nr; i++) {395elem[i].resize(nr_cols);396}397nc = nr_cols;398}399400//---------------------------------------------------------------------------401402template<typename Number>403vector<Number> Matrix<Number>::diagonal() const{404assert(nr == nc);405vector<Number> diag(nr);406for(size_t i=0; i<nr;i++){407diag[i]=elem[i][i];408}409return diag;410}411412//---------------------------------------------------------------------------413414template<typename Number>415size_t Matrix<Number>::maximal_decimal_length() const{416size_t i,maxim=0;417vector<size_t> maxim_col;418maxim_col=maximal_decimal_length_columnwise();419for (i = 0; i <nr; i++)420maxim=max(maxim,maxim_col[i]);421return maxim;422}423424//---------------------------------------------------------------------------425426template<typename Number>427vector<size_t> Matrix<Number>::maximal_decimal_length_columnwise() const{428size_t i,j=0;429vector<size_t> maxim(nc,0);430for (i = 0; i <nr; i++) {431for (j = 0; j <nc; j++) {432maxim[j]=max(maxim[j],decimal_length(elem[i][j]));433/* if(elem[i][j]<0){434if(elem[i][j]<neg_max[j])435neg_max[j]=elem[i][j];436continue;437}438if(elem[i][j]>pos_max[j])439pos_max[j]=elem[i][j];440*/441}442}443/* for(size_t j=0;j<nc;++j)444maxim[j]=max(decimal_length(neg_max[j]),decimal_length(pos_max[j])); */445return maxim;446}447448//---------------------------------------------------------------------------449450template<typename Number>451void Matrix<Number>::append(const Matrix<Number>& M) {452assert (nc == M.nc);453elem.reserve(nr+M.nr);454for (size_t i=0; i<M.nr; i++) {455elem.push_back(M.elem[i]);456}457nr += M.nr;458}459460//---------------------------------------------------------------------------461462template<typename Number>463void Matrix<Number>::append(const vector<vector<Number> >& M) {464if(M.size()==0)465return;466assert (nc == M[0].size());467elem.reserve(nr+M.size());468for (size_t i=0; i<M.size(); i++) {469elem.push_back(M[i]);470}471nr += M.size();472}473474//---------------------------------------------------------------------------475476template<typename Number>477void Matrix<Number>::append(const vector<Number>& V) {478assert (nc == V.size());479elem.push_back(V);480nr++;481}482483//---------------------------------------------------------------------------484485template<typename Number>486void Matrix<Number>::append_column(const vector<Number>& v) {487assert (nr == v.size());488for (size_t i=0; i<nr; i++) {489elem[i].resize(nc+1);490elem[i][nc] = v[i];491}492nc++;493}494495//---------------------------------------------------------------------------496497template<typename Number>498void Matrix<Number>::remove_row(const vector<Number>& row) {499size_t tmp_nr = nr;500for (size_t i = 1; i <= tmp_nr; ++i) {501if (elem[tmp_nr-i] == row) {502elem.erase(elem.begin()+(tmp_nr-i));503nr--;504}505}506}507508//---------------------------------------------------------------------------509510template<typename Number>511void Matrix<Number>::remove_duplicate_and_zero_rows() {512bool remove_some = false;513vector<bool> key(nr, true);514515set<vector<Number> > SortedRows;516SortedRows.insert( vector<Number>(nc,0) );517typename set<vector<Number> >::iterator found;518for (size_t i = 0; i<nr; i++) {519found = SortedRows.find(elem[i]);520if (found != SortedRows.end()) {521key[i] = false;522remove_some = true;523}524else525SortedRows.insert(found,elem[i]);526}527528if (remove_some) {529*this = submatrix(key);530}531}532533//---------------------------------------------------------------------------534535template<typename Number>536Matrix<Number> Matrix<Number>::add(const Matrix<Number>& A) const{537assert (nr == A.nr);538assert (nc == A.nc);539540Matrix<Number> B(nr,nc);541size_t i,j;542for(i=0; i<nr;i++){543for(j=0; j<nc; j++){544B.elem[i][j]=elem[i][j]+A.elem[i][j];545}546}547return B;548}549550//---------------------------------------------------------------------------551552template<typename Number>553Matrix<Number> Matrix<Number>::multiplication(const Matrix<Number>& A) const{554assert (nc == A.nr);555556Matrix<Number> B(nr,A.nc,0); //initialized with 0557size_t i,j,k;558for(i=0; i<B.nr;i++){559for(j=0; j<B.nc; j++){560for(k=0; k<nc; k++){561B.elem[i][j]=B.elem[i][j]+elem[i][k]*A.elem[k][j];562}563}564}565return B;566}567568//---------------------------------------------------------------------------569570template<typename Number>571Matrix<Number> Matrix<Number>::multiplication_cut(const Matrix<Number>& A, const size_t& c) const{572assert (nc == A.nr);573assert(c<= A.nc);574575Matrix<Number> B(nr,c,0); //initialized with 0576size_t i,j,k;577for(i=0; i<B.nr;i++){578for(j=0; j<c; j++){579for(k=0; k<nc; k++){580B.elem[i][j]=B.elem[i][j]+elem[i][k]*A.elem[k][j];581}582}583}584return B;585}586587588//---------------------------------------------------------------------------589/*590template<typename Number>591Matrix<Number> Matrix<Number>::multiplication(const Matrix<Number>& A, long m) const{592assert (nc == A.nr);593594Matrix<Number> B(nr,A.nc,0); //initialized with 0595size_t i,j,k;596for(i=0; i<B.nr;i++){597for(j=0; j<B.nc; j++){598for(k=0; k<nc; k++){599B.elem[i][j]=(B.elem[i][j]+elem[i][k]*A.elem[k][j])%m;600if (B.elem[i][j]<0) {601B.elem[i][j]=B.elem[i][j]+m;602}603}604}605}606return B;607}608*/609610//---------------------------------------------------------------------------611612template<typename Number>613bool Matrix<Number>::equal(const Matrix<Number>& A) const{614if ((nr!=A.nr)||(nc!=A.nc)){ return false; }615size_t i,j;616for (i=0; i < nr; i++) {617for (j = 0; j < nc; j++) {618if (elem[i][j]!=A.elem[i][j]) {619return false;620}621}622}623return true;624}625626//---------------------------------------------------------------------------627/*628template<typename Number>629bool Matrix<Number>::equal(const Matrix<Number>& A, long m) const{630if ((nr!=A.nr)||(nc!=A.nc)){ return false; }631size_t i,j;632for (i=0; i < nr; i++) {633for (j = 0; j < nc; j++) {634if (((elem[i][j]-A.elem[i][j]) % m)!=0) {635return false;636}637}638}639return true;640} */641642//---------------------------------------------------------------------------643644template<typename Number>645Matrix<Number> Matrix<Number>::transpose()const{646Matrix<Number> B(nc,nr);647size_t i,j;648for(i=0; i<nr;i++){649for(j=0; j<nc; j++){650B.elem[j][i]=elem[i][j];651}652}653return B;654}655656//---------------------------------------------------------------------------657658template<typename Number>659void Matrix<Number>::scalar_multiplication(const Number& scalar){660size_t i,j;661for(i=0; i<nr;i++){662for(j=0; j<nc; j++){663elem[i][j] *= scalar;664}665}666}667668//---------------------------------------------------------------------------669670template<typename Number>671void Matrix<Number>::scalar_division(const Number& scalar){672size_t i,j;673assert(scalar != 0);674for(i=0; i<nr;i++){675for(j=0; j<nc; j++){676// assert (elem[i][j]%scalar == 0);677elem[i][j] /= scalar;678}679}680}681682//---------------------------------------------------------------------------683684/*685template<typename Number>686void Matrix<Number>::reduction_modulo(const Number& modulo){687size_t i,j;688for(i=0; i<nr;i++){689for(j=0; j<nc; j++){690elem[i][j] %= modulo;691if (elem[i][j] < 0) {692elem[i][j] += modulo;693}694}695}696}697*/698699700//---------------------------------------------------------------------------701702template<typename Number>703void Matrix<Number>::simplify_rows() {704// vector<Number> g(nr);705for (size_t i = 0; i <nr; i++) {706v_simplify(elem[i]);707}708// return g;709}710711//---------------------------------------------------------------------------712713template<typename Number>714Matrix<Number> Matrix<Number>::multiply_rows(const vector<Number>& m) const{ //row i is multiplied by m[i]715Matrix M = Matrix(nr,nc);716size_t i,j;717for (i = 0; i<nr; i++) {718for (j = 0; j<nc; j++) {719M.elem[i][j] = elem[i][j]*m[i];720}721}722return M;723}724725//---------------------------------------------------------------------------726727template<typename Number>728void Matrix<Number>::MxV(vector<Number>& result, const vector<Number>& v) const{729assert (nc == v.size());730result.resize(nr);731for(size_t i=0; i<nr;i++){732result[i]=v_scalar_product(elem[i],v);733}734}735736//---------------------------------------------------------------------------737738template<typename Number>739vector<Number> Matrix<Number>::MxV(const vector<Number>& v) const{740vector<Number> w(nr);741MxV(w, v);742return w;743}744745//---------------------------------------------------------------------------746747template<typename Number>748vector<Number> Matrix<Number>::VxM(const vector<Number>& v) const{749assert (nr == v.size());750vector<Number> w(nc,0);751size_t i,j;752for (i=0; i<nc; i++){753for (j=0; j<nr; j++){754w[i] += v[j]*elem[j][i];755}756if(!check_range(w[i]))757break;758}759760return w;761}762763//---------------------------------------------------------------------------764765template<typename Number>766vector<Number> Matrix<Number>::VxM_div(const vector<Number>& v, const Number& divisor, bool& success) const{767assert (nr == v.size());768vector<Number> w(nc,0);769success=true;770size_t i,j;771for (i=0; i<nc; i++){772for (j=0; j<nr; j++){773w[i] += v[j]*elem[j][i];774}775if(!check_range(w[i])){776success=false;777break;778}779}780781if(success)782v_scalar_division(w,divisor);783784return w;785}786787//---------------------------------------------------------------------------788789template<typename Number>790bool Matrix<Number>::is_diagonal() const{791792for(size_t i=0;i<nr;++i)793for(size_t j=0;j<nc;++j)794if(i!=j && elem[i][j]!=0)795return false;796return true;797}798799//---------------------------------------------------------------------------800801template<typename Number>802vector<long> Matrix<Number>::pivot(size_t corner){803assert(corner < nc);804assert(corner < nr);805size_t i,j;806Number help=0;807vector<long> v(2,-1);808809for (i = corner; i < nr; i++) {810for (j = corner; j < nc; j++) {811if (elem[i][j]!=0) {812if ((help==0)||(Iabs(elem[i][j])<help)) {813help=Iabs(elem[i][j]);814v[0]=i;815v[1]=j;816if (help == 1) return v;817}818}819}820}821822return v;823}824825//---------------------------------------------------------------------------826827template<typename Number>828long Matrix<Number>::pivot_column(size_t row,size_t col){829assert(col < nc);830assert(row < nr);831size_t i;832long j=-1;833Number help=0;834835for (i = row; i < nr; i++) {836if (elem[i][col]!=0) {837if ((help==0)||(Iabs(elem[i][col])<help)) {838help=Iabs(elem[i][col]);839j=i;840if (help == 1) return j;841}842}843}844845return j;846}847848//---------------------------------------------------------------------------849850template<typename Number>851long Matrix<Number>::pivot_column(size_t col){852return pivot_column(col,col);853}854855//---------------------------------------------------------------------------856857template<typename Number>858void Matrix<Number>::exchange_rows(const size_t& row1, const size_t& row2){859if (row1 == row2) return;860assert(row1 < nr);861assert(row2 < nr);862elem[row1].swap(elem[row2]);863}864865//---------------------------------------------------------------------------866867template<typename Number>868void Matrix<Number>::exchange_columns(const size_t& col1, const size_t& col2){869if (col1 == col2) return;870assert(col1 < nc);871assert(col2 < nc);872for(size_t i=0; i<nr;i++){873std::swap(elem[i][col1], elem[i][col2]);874}875}876877//---------------------------------------------------------------------------878879template<typename Number>880bool Matrix<Number>::reduce_row (size_t row, size_t col) {881assert(col < nc);882assert(row < nr);883size_t i,j;884Number help;885for (i =row+1; i < nr; i++) {886if (elem[i][col]!=0) {887help=elem[i][col] / elem[row][col];888for (j = col; j < nc; j++) {889elem[i][j] -= help*elem[row][j];890if (!check_range(elem[i][j]) ) {891return false;892}893}894// v_el_trans<Number>(elem[row],elem[i],-help,col);895}896}897return true;898}899900//---------------------------------------------------------------------------901902template<typename Number>903bool Matrix<Number>::reduce_row (size_t corner) {904return reduce_row(corner,corner);905}906907//---------------------------------------------------------------------------908909template<typename Number>910bool Matrix<Number>::reduce_rows_upwards () {911// assumes that "this" is in row echelon form912// and reduces eevery column in which the rank jumps913// by its lowest element914//915// Aplies v_simplify to make rows "nice"916if(nr==0)917return true;918919for(size_t row=0;row<nr;++row){920size_t col;921for(col=0;col<nc;++col)922if(elem[row][col]!=0)923break;924if(col==nc) // zero row925continue;926if(elem[row][col]<0)927v_scalar_multiplication<Number>(elem[row],-1); // make corner posizive928929for(long i=row-1;i>=0;--i){930Number quot;931//minimal_remainder(elem[i][col],elem[row][col],quot,rem);932quot=elem[i][col]/elem[row][col];933elem[i][col]=0; // rem934for(size_t j=col+1;j<nc;++j){935elem[i][j]-=quot* elem[row][j];936}937}938}939940simplify_rows();941942return true;943}944945//---------------------------------------------------------------------------946947template<typename Number>948bool Matrix<Number>::linear_comb_columns(const size_t& col,const size_t& j,949const Number& u,const Number& w,const Number& v,const Number& z){950951for(size_t i=0;i<nr;++i){952Number rescue=elem[i][col];953elem[i][col]=u*elem[i][col]+v*elem[i][j];954elem[i][j]=w*rescue+z*elem[i][j];955if ( (!check_range(elem[i][col]) || !check_range(elem[i][j]) )) {956return false;957}958}959return true;960}961962//---------------------------------------------------------------------------963964template<typename Number>965bool Matrix<Number>::gcd_reduce_column (size_t corner, Matrix<Number>& Right){966assert(corner < nc);967assert(corner < nr);968Number d,u,w,z,v;969for(size_t j=corner+1;j<nc;++j){970d =elem[corner][corner],elem[corner]; // ext_gcd(elem[corner][corner],elem[corner][j],u,v);971u=1;972v=0;973w=-elem[corner][j]/d;974z=elem[corner][corner]/d;975// Now we multiply the submatrix formed by columns "corner" and "j"976// and rows corner,...,nr from the right by the 2x2 matrix977// | u w |978// | v z |979if(!linear_comb_columns(corner,j,u,w,v,z))980return false;981if(!Right.linear_comb_columns(corner,j,u,w,v,z))982return false;983}984return true;985}986987988//---------------------------------------------------------------------------989990template<typename Number>991bool Matrix<Number>::column_trigonalize(size_t rk, Matrix<Number>& Right) {992assert(Right.nr == nc);993assert(Right.nc == nc);994vector<long> piv(2,0);995for(size_t j=0;j<rk;++j){996piv=pivot(j);997assert(piv[0]>=0); // protect against wrong rank998exchange_rows (j,piv[0]);999exchange_columns (j,piv[1]);1000Right.exchange_columns(j,piv[1]);1001if(!gcd_reduce_column(j, Right))1002return false;1003}1004return true;1005}10061007//---------------------------------------------------------------------------10081009template<typename Number>1010Number Matrix<Number>::compute_vol(bool& success){10111012assert(nr<=nc);10131014Number det=1;1015for(size_t i=0;i<nr;++i){1016det*=elem[i][i];1017if(!check_range(det)){1018success=false;1019return 0;1020}1021}10221023det=Iabs(det);1024success=true;1025return det;1026}10271028//---------------------------------------------------------------------------10291030template<typename Number>1031size_t Matrix<Number>::row_echelon_inner_elem(bool& success){10321033size_t pc=0;1034long piv=0, rk=0;1035success=true;10361037if(nr==0)1038return 0;10391040for (rk = 0; rk < (long) nr; rk++){1041for(;pc<nc;pc++){1042piv=pivot_column(rk,pc);1043if(piv>=0)1044break;1045}1046if(pc==nc)1047break;1048do{1049exchange_rows (rk,piv);1050if(!reduce_row(rk,pc)){1051success=false;1052return rk;1053}1054piv=pivot_column(rk,pc);1055}while (piv>rk);1056}10571058return rk;1059}10601061//---------------------------------------------------------------------------10621063/*1064template<typename Number>1065size_t Matrix<Number>::row_echelon_inner_bareiss(bool& success, Number& det){1066// no overflow checks since this is supposed to be only used with GMP10671068success=true;1069if(nr==0)1070return 0;1071assert(using_GMP<Number>());10721073size_t pc=0;1074long piv=0, rk=0;1075vector<bool> last_time_mult(nr,false),this_time_mult(nr,false);1076Number last_div=1,this_div=1;1077size_t this_time_exp=0,last_time_exp=0;1078Number det_factor=1;10791080for (rk = 0; rk < (long) nr; rk++){10811082for(;pc<nc;pc++){1083piv=pivot_column(rk,pc);1084if(piv>=0)1085break;1086}1087if(pc==nc)1088break;10891090if(!last_time_mult[piv]){1091for(size_t k=rk;k<nr;++k)1092if(elem[k][pc]!=0 && last_time_mult[k]){1093piv=k;1094break;1095}1096}10971098exchange_rows (rk,piv);1099v_bool_entry_swap(last_time_mult,rk,piv);11001101if(!last_time_mult[rk])1102for(size_t i=0;i<nr;++i)1103last_time_mult[i]=false;11041105Number a=elem[rk][pc];1106this_div=Iabs(a);1107this_time_exp=0;11081109for(size_t i=rk+1;i<nr;++i){1110if(elem[i][pc]==0){1111this_time_mult[i]=false;1112continue;1113}11141115this_time_exp++;1116this_time_mult[i]=true;1117bool divide=last_time_mult[i] && (last_div!=1);1118if(divide)1119last_time_exp--;1120Number b=elem[i][pc];1121elem[i][pc]=0;1122if(a==1){1123for(size_t j=pc+1;j<nc;++j){1124elem[i][j]=elem[i][j]-b*elem[rk][j];1125if(divide){1126elem[i][j]/=last_div;1127}1128}1129}1130else{1131if(a==-1){1132for(size_t j=pc+1;j<nc;++j){1133elem[i][j]=-elem[i][j]-b*elem[rk][j];1134if(divide){1135elem[i][j]/=last_div;1136}1137}1138}1139else{1140for(size_t j=pc+1;j<nc;++j){1141elem[i][j]=a*elem[i][j]-b*elem[rk][j];1142if(divide){1143elem[i][j]/=last_div;1144}1145}1146}1147}1148}11491150for(size_t i=0;i<last_time_exp;++i)1151det_factor*=last_div;1152last_time_mult=this_time_mult;1153last_div=this_div;1154last_time_exp=this_time_exp;1155}11561157det=0;1158if (nr <= nc && rk == (long) nr) { // must allow nonsquare matrices1159det=1;1160for(size_t i=0;i<nr;++i)1161det*=elem[i][i];1162det=Iabs<Number>(det/det_factor);1163}11641165return rk;1166}1167*/11681169//---------------------------------------------------------------------------11701171template<typename Number>1172size_t Matrix<Number>::row_echelon_reduce(bool& success){11731174size_t rk=row_echelon_inner_elem(success);1175if(success)1176success=reduce_rows_upwards();1177return rk;1178}11791180//---------------------------------------------------------------------------11811182template<typename Number>1183Number Matrix<Number>::full_rank_index(bool& success){11841185size_t rk=row_echelon_inner_elem(success);1186Number index=1;1187if(success){1188for(size_t i=0;i<rk;++i){1189index*=elem[i][i];1190if(!check_range(index)){1191success=false;1192index=0;1193return index;1194}1195}1196}1197assert(rk==nc); // must have full rank1198index=Iabs(index);1199return index;1200}1201//---------------------------------------------------------------------------12021203template<typename Number>1204Matrix<Number> Matrix<Number>::row_column_trigonalize(size_t& rk, bool& success) {12051206Matrix<Number> Right(nc);1207rk=row_echelon_reduce(success);1208if(success)1209success=column_trigonalize(rk,Right);1210return Right;1211}12121213//---------------------------------------------------------------------------12141215template<typename Number>1216size_t Matrix<Number>::row_echelon(bool& success, bool do_compute_vol, Number& det){12171218/* if(using_GMP<Number>()){1219return row_echelon_inner_bareiss(success,det);;1220}1221else{ */1222size_t rk=row_echelon_inner_elem(success);1223if(do_compute_vol)1224det=compute_vol(success);1225return rk;1226// }1227}12281229//---------------------------------------------------------------------------12301231template<typename Number>1232size_t Matrix<Number>::row_echelon(bool& success){12331234Number dummy;1235return row_echelon(success,false,dummy);1236}12371238//---------------------------------------------------------------------------12391240template<typename Number>1241size_t Matrix<Number>::row_echelon(bool& success, Number& det){12421243return row_echelon(success,true,det);1244}1245124612471248//---------------------------------------------------------------------------12491250template<typename Number>1251size_t Matrix<Number>::rank_submatrix(const Matrix<Number>& mother, const vector<key_t>& key){12521253assert(nc>=mother.nc);1254if(nr<key.size()){1255elem.resize(key.size(),vector<Number>(nc,0));1256nr=key.size();1257}1258size_t save_nr=nr;1259size_t save_nc=nc;1260nr=key.size();1261nc=mother.nc;12621263select_submatrix(mother,key);12641265bool success;1266size_t rk=row_echelon(success);12671268nr=save_nr;1269nc=save_nc;1270return rk;1271}12721273//---------------------------------------------------------------------------12741275template<typename Number>1276size_t Matrix<Number>::rank_submatrix(const vector<key_t>& key) const{12771278Matrix<Number> work(key.size(),nc);1279return work.rank_submatrix(*this,key);1280}12811282//---------------------------------------------------------------------------12831284template<typename Number>1285size_t Matrix<Number>::rank() const{1286vector<key_t> key(nr);1287for(size_t i=0;i<nr;++i)1288key[i]=i;1289return rank_submatrix(key);1290}12911292//---------------------------------------------------------------------------12931294template<typename Number>1295Number Matrix<Number>::vol_submatrix(const Matrix<Number>& mother, const vector<key_t>& key){12961297assert(nc>=mother.nc);1298if(nr<key.size()){1299elem.resize(key.size(),vector<Number>(nc,0));1300nr=key.size();1301}1302size_t save_nr=nr;1303size_t save_nc=nc;1304nr=key.size();1305nc=mother.nc;13061307select_submatrix(mother,key);13081309bool success;1310Number det;1311row_echelon(success,det);13121313nr=save_nr;1314nc=save_nc;1315return det;1316}1317//---------------------------------------------------------------------------13181319template<typename Number>1320Number Matrix<Number>::vol_submatrix(const vector<key_t>& key) const{13211322Matrix<Number> work(key.size(),nc);1323return work.vol_submatrix(*this,key);1324}13251326//---------------------------------------------------------------------------13271328template<typename Number>1329Number Matrix<Number>::vol() const{1330vector<key_t> key(nr);1331for(size_t i=0;i<nr;++i)1332key[i]=i;1333return vol_submatrix(key);1334}13351336//---------------------------------------------------------------------------13371338template<typename Number>1339vector<key_t> Matrix<Number>::max_rank_submatrix_lex_inner(bool& success) const{13401341success=true;1342size_t max_rank=min(nr,nc);1343Matrix<Number> Test(max_rank,nc);1344Test.nr=0;1345vector<key_t> col;1346col.reserve(max_rank);1347vector<key_t> key;1348key.reserve(max_rank);1349size_t rk=0;13501351vector<vector<bool> > col_done(max_rank,vector<bool>(nc,false));13521353vector<Number> Test_vec(nc);13541355for(size_t i=0;i<nr;++i){1356Test_vec=elem[i];1357for(size_t k=0;k<rk;++k){1358if(Test_vec[col[k]]==0)1359continue;1360Number a=Test[k][col[k]];1361Number b=Test_vec[col[k]];1362for(size_t j=0;j<nc;++j)1363if(!col_done[k][j]){1364Test_vec[j]=a*Test_vec[j]-b*Test[k][j];1365if (!check_range(Test_vec[j]) ) {1366success=false;1367return key;1368}1369}1370}13711372size_t j=0;1373for(;j<nc;++j)1374if(Test_vec[j]!=0)1375break;1376if(j==nc) // Test_vec=01377continue;13781379col.push_back(j);1380key.push_back(i);13811382if(rk>0){1383col_done[rk]=col_done[rk-1];1384col_done[rk][col[rk-1]]=true;1385}13861387Test.nr++;1388rk++;1389v_simplify(Test_vec);1390Test[rk-1]=Test_vec;13911392if(rk==max_rank)1393break;1394}1395return key;1396}13971398//---------------------------------------------------------------------------13991400template<typename Number>1401vector<key_t> Matrix<Number>::max_rank_submatrix_lex() const{1402bool success;1403vector<key_t> key=max_rank_submatrix_lex_inner(success);1404return key;1405}14061407//---------------------------------------------------------------------------14081409template<typename Number>1410bool Matrix<Number>::solve_destructive_inner(bool ZZinvertible,Number& denom) {14111412assert(nc>=nr);1413size_t dim=nr;1414bool success;14151416size_t rk;14171418if(ZZinvertible){1419rk=row_echelon_inner_elem(success);1420if(!success)1421return false;1422assert(rk==nr);1423denom=compute_vol(success);1424}1425else{1426rk=row_echelon(success,denom);1427if(!success)1428return false;1429}14301431if (denom==0) {1432if(using_GMP<Number>()){1433errorOutput() << "Cannot solve system (denom=0)!" << endl;1434throw ArithmeticException();1435}1436else1437return false;1438}14391440Number S;1441size_t i;1442long j;1443size_t k;1444for (i = nr; i < nc; i++) {1445for (j = dim-1; j >= 0; j--) {1446S=denom*elem[j][i];1447for (k = j+1; k < dim; k++) {1448S-=elem[j][k]*elem[k][i];1449}1450if(!check_range(S))1451return false;1452elem[j][i]=S/elem[j][j];1453}1454}1455return true;1456}14571458//---------------------------------------------------------------------------14591460template<typename Number>1461void Matrix<Number>::customize_solution(size_t dim, Number& denom, size_t red_col,1462size_t sign_col, bool make_sol_prime) {14631464return;14651466/* assert(!(make_sol_prime && (sign_col>0 || red_col>0)));14671468for(size_t j=0;j<red_col;++j){ // reduce first red_col columns of solution mod denom1469for(size_t k=0;k<dim;++k){1470elem[k][dim+j]%=denom;1471if(elem[k][dim+j]<0)1472elem[k][dim+j]+=Iabs(denom);1473}1474}14751476for(size_t j=0;j<sign_col;++j) // replace entries in the next sign_col columns by their signs1477for(size_t k=0;k<dim;++k){1478if(elem[k][dim+red_col+j]>0){1479elem[k][dim+red_col+j]=1;1480continue;1481}1482if(elem[k][dim+red_col+j]<0){1483elem[k][dim+red_col+j]=-1;1484continue;1485}1486}14871488if(make_sol_prime) // make columns of solution coprime if wanted1489make_cols_prime(dim,nc-1); */1490}14911492//---------------------------------------------------------------------------14931494template<typename Number>1495void Matrix<Number>::solve_system_submatrix_outer(const Matrix<Number>& mother, const vector<key_t>& key, const vector<vector<Number>* >& RS,1496Number& denom, bool ZZ_invertible, bool transpose, size_t red_col, size_t sign_col,1497bool compute_denom, bool make_sol_prime) {14981499size_t dim=mother.nc;1500assert(key.size()==dim);1501assert(nr==dim);1502assert(dim+RS.size()<=nc);1503size_t save_nc=nc;1504nc=dim+RS.size();15051506if(transpose)1507select_submatrix_trans(mother,key);1508else1509select_submatrix(mother,key);15101511for(size_t i=0;i<dim;++i)1512for(size_t k=0;k<RS.size();++k)1513elem[i][k+dim]= (*RS[k])[i];15141515if(solve_destructive_inner(ZZ_invertible,denom)){1516customize_solution(dim, denom,red_col,sign_col,make_sol_prime);1517} /*1518else{1519#pragma omp atomic1520GMP_mat++;15211522Matrix<mpz_class> mpz_this(nr,nc);1523mpz_class mpz_denom;1524if(transpose)1525mpz_submatrix_trans(mpz_this,mother,key);1526else1527mpz_submatrix(mpz_this,mother,key);15281529for(size_t i=0;i<dim;++i)1530for(size_t k=0;k<RS.size();++k)1531convert(mpz_this[i][k+dim], (*RS[k])[i]);1532mpz_this.solve_destructive_inner(ZZ_invertible,mpz_denom);1533mpz_this.customize_solution(dim, mpz_denom,red_col,sign_col,make_sol_prime);15341535for(size_t i=0;i<dim;++i) // replace left side by 0, except diagonal if ZZ_invetible1536for(size_t j=0;j<dim;++j){1537if(i!=j || !ZZ_invertible)1538mpz_this[i][j]=0;1539}15401541mat_to_Int(mpz_this,*this);1542if(compute_denom)1543convert(denom, mpz_denom);1544}*/1545nc=save_nc;1546}154715481549//---------------------------------------------------------------------------155015511552template<typename Number>1553void Matrix<Number>::solve_system_submatrix(const Matrix<Number>& mother, const vector<key_t>& key, const vector<vector<Number>* >& RS,1554vector< Number >& diagonal, Number& denom, size_t red_col, size_t sign_col) {15551556solve_system_submatrix_outer(mother,key,RS,denom,true,false,red_col,sign_col);1557assert(diagonal.size()==nr);1558for(size_t i=0;i<nr;++i)1559diagonal[i]=elem[i][i];15601561}1562156315641565//---------------------------------------------------------------------------1566// the same without diagonal1567template<typename Number>1568void Matrix<Number>::solve_system_submatrix(const Matrix<Number>& mother, const vector<key_t>& key, const vector<vector<Number>* >& RS,1569Number& denom, size_t red_col, size_t sign_col, bool compute_denom, bool make_sol_prime) {15701571solve_system_submatrix_outer(mother,key,RS,denom,false,false,red_col,sign_col,1572compute_denom, make_sol_prime);1573}15741575//---------------------------------------------------------------------------15761577template<typename Number>1578void Matrix<Number>::solve_system_submatrix_trans(const Matrix<Number>& mother, const vector<key_t>& key, const vector<vector<Number>* >& RS,1579Number& denom, size_t red_col, size_t sign_col) {15801581solve_system_submatrix_outer(mother,key,RS,denom,false,true,red_col,sign_col);1582}15831584//---------------------------------------------------------------------------15851586template<typename Number>1587Matrix<Number> Matrix<Number>::extract_solution() const {1588assert(nc>=nr);1589Matrix<Number> Solution(nr,nc-nr);1590for(size_t i=0;i<nr;++i){1591for(size_t j=0;j<Solution.nc;++j)1592Solution[i][j]=elem[i][j+nr];1593}1594return Solution;1595}15961597//---------------------------------------------------------------------------15981599template<typename Number>1600vector<vector<Number>* > Matrix<Number>::row_pointers(){16011602vector<vector<Number>* > pointers(nr);1603for(size_t i=0;i<nr;++i)1604pointers[i]=&(elem[i]);1605return pointers;1606}16071608//---------------------------------------------------------------------------16091610template<typename Number>1611vector<vector<Number>* > Matrix<Number>::submatrix_pointers(const vector<key_t>& key){16121613vector<vector<Number>* > pointers(key.size());1614for(size_t i=0;i<key.size();++i)1615pointers[i]=&(elem[key[i]]);1616return pointers;1617}1618//---------------------------------------------------------------------------16191620template<typename Number>1621Matrix<Number> Matrix<Number>::solve(const Matrix<Number>& Right_side,vector<Number>& diagonal,Number& denom) const {16221623Matrix<Number> M(nr,nc+Right_side.nc);1624vector<key_t> key=identity_key(nr);1625Matrix<Number> RS_trans=Right_side.transpose();1626vector<vector<Number>* > RS=RS_trans.row_pointers();1627M.solve_system_submatrix(*this,key,RS,diagonal,denom,0,0);1628return M.extract_solution();1629}16301631//---------------------------------------------------------------------------16321633template<typename Number>1634Matrix<Number> Matrix<Number>::solve(const Matrix<Number>& Right_side, Number& denom) const {16351636Matrix<Number> M(nr,nc+Right_side.nc);1637vector<key_t> key=identity_key(nr);1638Matrix<Number> RS_trans=Right_side.transpose();1639vector<vector<Number>* > RS=RS_trans.row_pointers();1640M.solve_system_submatrix(*this,key,RS,denom,0,0);1641return M.extract_solution();1642}16431644//---------------------------------------------------------------------------16451646template<typename Number>1647Matrix<Number> Matrix<Number>::invert(Number& denom) const{1648assert(nr == nc);1649Matrix<Number> Right_side(nr);16501651return solve(Right_side,denom);1652}16531654//---------------------------------------------------------------------------16551656template<typename Number>1657Matrix<Number> Matrix<Number>::bundle_matrices(const Matrix<Number>& Right_side) const {16581659assert(nr == nc);1660assert(nc == Right_side.nr);1661Matrix<Number> M(nr,nc+Right_side.nc);1662for(size_t i=0;i<nr;++i){1663for(size_t j=0;j<nc;++j)1664M[i][j]=elem[i][j];1665for(size_t j=nc;j<M.nc;++j)1666M[i][j]=Right_side[i][j-nc];1667}1668return M;1669}1670//---------------------------------------------------------------------------16711672template<typename Number>1673Matrix<Number> Matrix<Number>::invert_unprotected(Number& denom, bool& success) const{1674assert(nr == nc);1675Matrix<Number> Right_side(nr);1676Matrix<Number> M=bundle_matrices(Right_side);1677success=M.solve_destructive_inner(false,denom);1678return M.extract_solution();;1679}16801681//---------------------------------------------------------------------------16821683template<typename Number>1684void Matrix<Number>::invert_submatrix(const vector<key_t>& key, Number& denom, Matrix<Number>& Inv, bool compute_denom, bool make_sol_prime) const{1685assert(key.size() == nc);1686Matrix<Number> unit_mat(key.size());1687Matrix<Number> M(key.size(),2*key.size());1688vector<vector<Number>* > RS_pointers=unit_mat.row_pointers();1689M.solve_system_submatrix(*this,key,RS_pointers,denom,0,0, compute_denom, make_sol_prime);1690Inv=M.extract_solution();;1691}16921693//---------------------------------------------------------------------------16941695template<typename Number>1696void Matrix<Number>::simplex_data(const vector<key_t>& key, Matrix<Number>& Supp, Number& vol, bool compute_vol) const{1697assert(key.size() == nc);1698invert_submatrix(key,vol,Supp,compute_vol,true);1699Supp=Supp.transpose();1700// Supp.make_prime(); now done internally -- but not in Q !! Therefore1701Supp.simplify_rows();1702}1703//---------------------------------------------------------------------------17041705template<typename Number>1706vector<Number> Matrix<Number>::solve_rectangular(const vector<Number>& v, Number& denom) const {1707if (nc == 0 || nr == 0) { //return zero-vector as solution1708return vector<Number>(nc,0);1709}1710size_t i;1711vector<key_t> rows=max_rank_submatrix_lex();1712Matrix<Number> Left_Side=submatrix(rows);1713assert(nc == Left_Side.nr); //otherwise input hadn't full rank //TODO1714Matrix<Number> Right_Side(v.size(),1);1715Right_Side.write_column(0,v);1716Right_Side = Right_Side.submatrix(rows);1717Matrix<Number> Solution=Left_Side.solve(Right_Side, denom);1718vector<Number> Linear_Form(nc);1719for (i = 0; i <nc; i++) {1720Linear_Form[i] = Solution[i][0]; // the solution vector is called Linear_Form1721}1722vector<Number> test = MxV(Linear_Form); // we have solved the system by taking a square submatrix1723// now we must test whether the solution satisfies the full system1724for (i = 0; i <nr; i++) {1725if (test[i] != denom * v[i]){1726return vector<Number>();1727}1728}1729Number total_gcd = 1; // libnormaliz::gcd(denom,v_gcd(Linear_Form)); // extract the gcd of denom and solution1730denom/=total_gcd;1731v_scalar_division(Linear_Form,total_gcd);1732return Linear_Form;1733}1734//---------------------------------------------------------------------------17351736template<typename Number>1737vector<Number> Matrix<Number>::solve_ZZ(const vector<Number>& v) const {17381739Number denom;1740vector<Number> result=solve_rectangular(v,denom);1741if(denom!=1)1742result.clear();1743return result;1744}1745//---------------------------------------------------------------------------17461747template<typename Number>1748vector<Number> Matrix<Number>::find_linear_form() const {17491750Number denom;1751vector<Number> result=solve_rectangular(vector<Number>(nr,1),denom);1752return result;1753}17541755//---------------------------------------------------------------------------17561757template<typename Number>1758vector<Number> Matrix<Number>::find_linear_form_low_dim () const{1759size_t rank=(*this).rank();1760if (rank == 0) { //return zero-vector as linear form1761return vector<Number>(nc,0);1762}1763if (rank == nc) { // basis change not necessary1764return (*this).find_linear_form();1765}17661767Sublattice_Representation<Number> Basis_Change(*this,true);1768vector<Number> Linear_Form=Basis_Change.to_sublattice(*this).find_linear_form();1769if(Linear_Form.size()!=0)1770Linear_Form=Basis_Change.from_sublattice_dual(Linear_Form);17711772return Linear_Form;1773}17741775//---------------------------------------------------------------------------17761777template<typename Number>1778size_t Matrix<Number>::row_echelon_reduce(){17791780size_t rk;1781Matrix<Number> Copy(*this);1782bool success;1783rk=row_echelon_reduce(success);17841785Shrink_nr_rows(rk);1786return rk;17871788}1789//---------------------------------------------------------------------------17901791template<typename Number>1792Number Matrix<Number>::full_rank_index() const{17931794Matrix<Number> Copy(*this);1795Number index;1796bool success;1797index=Copy.full_rank_index(success);17981799return index;1800}18011802//---------------------------------------------------------------------------18031804template<typename Number>1805size_t Matrix<Number>::row_echelon(){18061807Matrix<Number> Copy(*this);1808bool success;1809size_t rk;1810rk=row_echelon(success);18111812Shrink_nr_rows(rk);1813return rk;18141815}18161817//---------------------------------------------------------------------------18181819template<typename Number>1820Matrix<Number> Matrix<Number>::kernel () const{1821// computes a ZZ-basis of the solutions of (*this)x=01822// the basis is formed by the rOWS of the returned matrix18231824size_t dim=nc;1825if(nr==0)1826return(Matrix<Number>(dim));18271828Matrix<Number> Copy(*this);1829size_t rank;1830bool success;1831Matrix<Number> Transf=Copy.row_column_trigonalize(rank,success);18321833Matrix<Number> ker_basis(dim-rank,dim);1834Matrix<Number> Help =Transf.transpose();1835for (size_t i = rank; i < dim; i++)1836ker_basis[i-rank]=Help[i];1837ker_basis.row_echelon_reduce();1838return(ker_basis);1839}18401841//---------------------------------------------------------------------------1842// Converts "this" into (column almost) Hermite normal form, returns column transformation matrix1843/*template<typename Number>1844Matrix<Number> Matrix<Number>::AlmostHermite(size_t& rk){18451846Matrix<Number> Copy=*this;1847Matrix<Number> Transf;1848bool success;1849Transf=row_column_trigonalize(rk,success);18501851return Transf;1852} */18531854//---------------------------------------------------------------------------1855// Classless conversion routines1856//---------------------------------------------------------------------------18571858template<typename ToType, typename FromType>1859void convert(Matrix<ToType>& to_mat, const Matrix<FromType>& from_mat){1860size_t nrows = from_mat.nr_of_rows();1861size_t ncols = from_mat.nr_of_columns();1862to_mat.resize(nrows, ncols);1863for(size_t i=0; i<nrows; ++i)1864for(size_t j=0; j<ncols; ++j)1865convert(to_mat[i][j], from_mat[i][j]);1866}18671868//---------------------------------------------------------------------------186918701871template<typename Number>1872bool weight_lex(const order_helper<Number>& a, const order_helper<Number>& b){18731874if(a.weight < b.weight)1875return true;1876if(a.weight==b.weight)1877if(*(a.v)< *(b.v))1878return true;1879return false;1880}18811882//---------------------------------------------------------------------------18831884template<typename Number>1885void Matrix<Number>::order_rows_by_perm(const vector<key_t>& perm){1886order_by_perm(elem,perm);1887}18881889template<typename Number>1890Matrix<Number>& Matrix<Number>::sort_by_weights(const Matrix<Number>& Weights, vector<bool> absolute){1891if(nr<=1)1892return *this;1893vector<key_t> perm=perm_by_weights(Weights,absolute);1894order_by_perm(elem,perm);1895return *this;1896}18971898template<typename Number>1899Matrix<Number>& Matrix<Number>::sort_lex(){1900if(nr<=1)1901return *this;1902vector<key_t> perm=perm_by_weights(Matrix<Number>(0,nc),vector<bool>(0));1903order_by_perm(elem,perm);1904return *this;1905}19061907template<typename Number>1908vector<key_t> Matrix<Number>::perm_by_weights(const Matrix<Number>& Weights, vector<bool> absolute){1909// the smallest entry is the row with index perm[0], then perm[1] etc.19101911assert(Weights.nc==nc);1912assert(absolute.size()==Weights.nr);19131914list<order_helper<Number> > order;1915order_helper<Number> entry;1916entry.weight.resize(Weights.nr);19171918for(key_t i=0;i<nr; ++i){1919for(size_t j=0;j<Weights.nr;++j){1920if(absolute[j])1921entry.weight[j]=v_scalar_product(Weights[j],v_abs_value(elem[i]));1922else1923entry.weight[j]=v_scalar_product(Weights[j],elem[i]);1924}1925entry.index=i;1926entry.v=&(elem[i]);1927order.push_back(entry);1928}1929order.sort(weight_lex<Number>);1930vector<key_t> perm(nr);1931typename list<order_helper<Number> >::const_iterator ord=order.begin();1932for(key_t i=0;i<nr;++i, ++ord)1933perm[i]=ord->index;19341935return perm;1936}19371938//---------------------------------------------------19391940/* template<typename Number>1941Matrix<Number> Matrix<Number>::solve_congruences(bool& zero_modulus) const{194219431944zero_modulus=false;1945size_t i,j;1946size_t nr_cong=nr, dim=nc-1;1947if(nr_cong==0)1948return Matrix<Number>(dim); // give back unit matrix19491950//add slack variables to convert congruences into equaitions1951Matrix<Number> Cong_Slack(nr_cong, dim+nr_cong);1952for (i = 0; i < nr_cong; i++) {1953for (j = 0; j < dim; j++) {1954Cong_Slack[i][j]=elem[i][j];1955}1956Cong_Slack[i][dim+i]=elem[i][dim];1957if(elem[i][dim]==0){1958zero_modulus=true;1959return Matrix<Number>(0,dim);1960}1961}19621963//compute kernel19641965Matrix<Number> Help=Cong_Slack.kernel(); // gives the solutions to the the system with slack variables1966Matrix<Number> Ker_Basis(dim,dim); // must now project to first dim coordinates to get rid of them1967for(size_t i=0;i<dim;++i)1968for(size_t j=0;j<dim;++j)1969Ker_Basis[i][j]=Help[i][j];1970return Ker_Basis;19711972} */19731974//---------------------------------------------------19751976template<typename Number>1977void Matrix<Number>::saturate(){19781979// *this=kernel().kernel();1980return; // no saturation necessary over a field1981}19821983//---------------------------------------------------19841985template<typename Number>1986vector<key_t> Matrix<Number>::max_and_min(const vector<Number>& L, const vector<Number>& norm) const{19871988vector<key_t> result(2,0);1989if(nr==0)1990return result;1991key_t maxind=0,minind=0;1992Number maxval=v_scalar_product(L,elem[0]);1993Number maxnorm=1,minnorm=1;1994if(norm.size()>0){1995maxnorm=v_scalar_product(norm,elem[0]);1996minnorm=maxnorm;1997}1998Number minval=maxval;1999for(key_t i=0;i<nr;++i){2000Number val=v_scalar_product(L,elem[i]);2001if(norm.size()==0){2002if(val>maxval){2003maxind=i;2004maxval=val;2005}2006if(val<minval){2007minind=i;2008minval=val;2009}2010}2011else{2012Number nm=v_scalar_product(norm,elem[i]);2013if(maxnorm*val>nm*maxval){2014maxind=i;2015maxval=val;2016}2017if(minnorm*val<nm*minval){2018minind=i;2019minval=val;2020}2021}2022}2023result[0]=maxind;2024result[1]=minind;2025return result;2026}20272028/*2029template<typename Number>2030size_t Matrix<Number>::extreme_points_first(const vector<Number> norm){20312032if(nr==0)2033return 1;20342035vector<long long> norm_copy;20362037size_t nr_extr=0;2038Matrix<long long> HelpMat(nr,nc);2039try{2040convert(HelpMat,*this);2041convert(norm_copy,norm);2042}2043catch(ArithmeticException){2044return nr_extr;2045}20462047HelpMat.sort_lex();20482049vector<bool> marked(nr,false);2050size_t no_success=0;2051// size_t nr_attempt=0;2052while(true){2053// nr_attempt++; cout << nr_attempt << endl;2054vector<long long> L=v_random<long long>(nc,10);2055vector<key_t> max_min_ind;2056max_min_ind=HelpMat.max_and_min(L,norm_copy);20572058if(marked[max_min_ind[0]] && marked[max_min_ind[1]])2059no_success++;2060else2061no_success=0;2062if(no_success > 1000)2063break;2064marked[max_min_ind[0]]=true;2065marked[max_min_ind[1]]=true;2066}2067Matrix<long long> Extr(nr_extr,nc); // the recognized extreme rays2068Matrix<long long> NonExtr(nr_extr,nc); // the other generators2069size_t j=0;2070vector<key_t> perm(nr);2071for(size_t i=0;i<nr;++i) {2072if(marked[i]){2073perm[j]=i;;2074j++;2075}2076}2077nr_extr=j;2078for(size_t i=0;i<nr;++i) {2079if(!marked[i]){2080perm[j]=i;;2081j++;2082}2083}2084order_rows_by_perm(perm);2085// cout << nr_extr << "extreme points found" << endl;2086return nr_extr;2087// exit(0);2088}20892090template<typename Number>2091vector<Number> Matrix<Number>::find_inner_point(){2092vector<key_t> simplex=max_rank_submatrix_lex();2093vector<Number> point(nc);2094for(size_t i=0;i<simplex.size();++i)2095point=v_add(point,elem[simplex[i]]);2096return point;2097}2098*/20992100template<typename Number>2101void Matrix<Number>::Shrink_nr_rows(size_t new_nr_rows){21022103if(new_nr_rows>=nr)2104return;2105nr=new_nr_rows;2106elem.resize(nr);2107}21082109template<typename Number>2110Matrix<Number> readMatrix(const string project){2111// reads one matrix from file with name project2112// format: nr of rows, nr of colimns, entries2113// all separated by white space21142115string name_in=project;2116const char* file_in=name_in.c_str();2117ifstream in;2118in.open(file_in,ifstream::in);2119if (in.is_open()==false){2120cerr << "Cannot find input file" << endl;2121exit(1);2122}21232124int nrows,ncols;2125in >> nrows;2126in >> ncols;21272128if(nrows==0 || ncols==0){2129cerr << "Matrix empty" << endl;2130exit(1);2131}213221332134int i,j,entry;2135Matrix<Number> result(nrows,ncols);21362137for(i=0;i<nrows;++i)2138for(j=0;j<ncols;++j){2139in >> entry;2140result[i][j]=entry;2141}2142return result;2143}21442145/*2146#ifndef NMZ_MIC_OFFLOAD //offload with long is not supported2147template Matrix<long> readMatrix(const string project);2148#endif // NMZ_MIC_OFFLOAD2149template Matrix<long long> readMatrix(const string project);2150template Matrix<mpz_class> readMatrix(const string project);2151*/21522153} // namespace215421552156