/*

    Bist: a chemical drawing tool
    Copyright (C) 2008 Valerio Benfante

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


/* aX1+bX2+..zXn=c*/

class gauss {

public:

  /* sist -- array con il sistema; deve essere del tipo:
     int v[5]={a1,a2,noto,
               a3,a4,noto2
	       };
     inc --  numero di incognite nell'esempio dato piu' sopra e' uguale a 2
     
  */

  gauss(double* sist, int inc)
    :incognite(inc)

  {
    mx=sist;
    risultati=new double[incognite];
    //diagonalizza();
  }

  /*lancia  un eccezione "runtime_error"  se il  sistema non  ammette un
    'unica soluzione*/
bool diagonalizza(){
  
  

  for(int el=1;el<incognite;el++){
    
    int max=0;
    
    double piv=fabs(mx[el*(incognite+1)+el]);
   
    for(int sc=el*(incognite+1);sc<incognite*incognite+incognite;sc+=incognite+1){
      
      if(fabs(mx[sc+el])>fabs(piv)){
	max=sc;
	piv=mx[sc+(el-1)];
      }

    }
    
    if(mx[max]==0){
      string wht="Eccezione lanciata: Il sistema non ammette un'unica soluzione";
      throw runtime_error(wht);
      return false;
    }
    
    for(int los=max;los<=max+incognite;los++){
      double tmp=mx[los];
      mx[los]=mx[los-max];
      mx[los-max]=tmp;
    }
    
       
    for(int col=el*(incognite+1);col < incognite*incognite+incognite; col+=incognite+1){
      for(int ri=incognite; ri>=0;ri--){
	mx[col+ri]-=mx[el*(incognite+1)-(incognite+1)+ri]*
	  (mx[col+el-1]/mx[(el-1)*(incognite+1)+(el-1)]);
      } 
    }
  }

  return true;

}

  /*risolve il sistema*/
  void risolvi(){
    int limri=1;
    for(int col=incognite*incognite+(incognite-1); col>=incognite; col-=incognite+1, limri++){
      double tmp=0;
      int ri=1;
      for( ;ri<limri; ri++){
	tmp+=mx[col-ri]*risultati[ri-1];
      }
      risultati[limri-1]=(mx[col]-tmp)/mx[col-ri];
      //cout << tmp << "\t" << col << endl;
    }

  }


  /*ritorna un puntatore ai risultati*/
  const double* ritorna_risultati(){
    reverse(risultati,risultati+incognite);
    return risultati;
  }

  /*ritorna il numero di incognite*/
  int ritorna_numero_incognite(){
    return incognite;
  }

  ~gauss(){
    delete [] risultati;
  }


protected:
  int incognite;
  double* mx;
  double* risultati;
  

};



bool compare_x_pair(pair<double,double> un,pair<double,double> due){

  if(un.first<due.first){ 
    return true;
  }else{ 
    return false;
  }
}

				     










