/* Resolution d'un systeme de n equations       */
/* lineaires a n inconnues                      */
/* par la methode du pivot de Gauss             */
/* Test des erreurs commises                    */

public class PivotGaussErreurs {

/* Fonction de generation d'un nombre aleatoire */
/* entier compris dans l'intervalle [-max,max]  */

  static int nombreAleatoire(int max) {
    int v =(int) ((2*max+1)*Math.random()-max-1);
    return v;
  }
/* Fonction de creation d'un tableau de double  */
/* initialise avec des nombres aleatoires       */
/* entiers compris dans l'intervalle [-max,max] */

  static double [] initRandTableau(int taille) {
    double [] tab = new double[taille];
    for ( int i = 0 ; i < taille ; i++ ) {
      tab[i] = nombreAleatoire(i*10+10); }
    return tab;
  }

/* Fonction de creation d'une matrice de double */
/* initialisee avec des nombres aleatoires      */
/* entiers compris dans l'intervalle [-max,max] */

  static double [][] initRandMatrice(int taille) {
    double [][] tab = new double[taille][taille];
    for ( int i = 0 ; i < taille ; i++ ) {
      for ( int j = 0 ; j < taille ; j++ ) {
        tab[i][j] = nombreAleatoire(i*10+10); } }
     return tab;
  }

/* Fonction d'affichage des valeurs contenues  */
/* dans un tableau de double a 1 indice        */
  
  static void affichageVecteur(double [] t) {
    for ( int i = 0 ; i < t.length ; i++ ) {
      Ecran.afficherln(t[i]); }
  }

/* Fonction d'affichage des valeurs contenues  */
/* dans un tableau de double a 2 indices       */
  
  static void affichageMatrice(double [][] t) {
    for ( int i = 0 ; i < t.length ; i++ ) {
      for ( int j = 0 ; j < t[i].length ; j++ ) {
        Ecran.afficher(t[i][j]," "); }
      Ecran.sautDeLigne(); }
  }
  
/* Fonction de calcul du produit d'un tableau  */
/* carre de taille n.n par un tableau          */
/* a 1 indice de taille n                      */
/* Retour: Un tableau a 1 indice de taille n   */

  static double [] produit(double [][] m,double [] v) {
    int n = v.length;
    double [] w = new double[n];
    for ( int i = 0 ; i < n ; i++ ) {
      w[i] = 0.0;
      for ( int j = 0 ; j < n ; j++ ) {
        w[i] = w[i] + m[i][j]*v[j]; } }
    return w;
  }
  
/////////////////////////////////////////////////

/* Fonction de clonage d'un tableau            */
/* a 1 indice de double                        */

  static double [] clone(double [] t) {
    int n = t.length;
    double [] nt = new double[n];
    for ( int i = 0 ; i < n ; i++ ) {
      nt[i] = t[i]; }
    return nt;
  }

/* Fonction de clonage d'un tableau            */
/* a 2 indices de double                       */

  static double [][] clone(double [][] t) {
    int n = t.length;
    int m = t[0].length;
    double [][] nt = new double[n][m];
    for ( int i = 0 ; i < n ; i++ ) {
      for ( int j = 0 ; j < m ; j++ ) {
        nt[i][j] = t[i][j]; } }
    return nt;
  }

/* Permutation de Gauss                        */

  static void permutation(int l,double [][] m,double [] v) {
    int n = v.length;
    double aux;
    int ll = l;
    while ( m[ll][l] == 0.0 ) {
      ll++; }
    for ( int i = l ; i < n ; i++ ) {
      aux = m[l][i];
      m[l][i] = m[ll][i];
      m[ll][i] = aux; }
    aux = v[l];
    v[l] = v[ll];
    v[ll] = aux;
  }

/* Transformation de Gauss                     */

  static void transformation(double [][] m,double [] v) {
  int n = v.length;
  double facteur;
  for ( int i = 1 ; i < n ; i++ ) {
    if ( m[i-1][i-1] == 0.0 )
      permutation(i-1,m,v);
    for ( int j = i ; j < n ; j++ ) {
      facteur = m[j][i-1]/m[i-1][i-1];
      for ( int k = i-1 ; k < n ; k++ ) {
        m[j][k] = m[j][k] - m[i-1][k]*facteur; }
      v[j] = v[j] - v[i-1]*facteur;  } }
  }

/* Extraction de Gauss                         */
  
  static double [] extraction(double [][] a,double [] b) {
    int n = b.length;
    double [] v = new double[n];
    v[n-1] = b[n-1]/a[n-1][n-1];
    for ( int i = n-2 ; i >= 0 ; i-- ) {
      v[i] = b[i];
      for ( int j = n-1 ; j > i ; j-- ) {
        v[i] = v[i] - v[j]*a[i][j]; }
      v[i] = v[i]/a[i][i]; }
    return v;
  }
      
/* Resolution de Gauss                         */

  static double [] resolution(double [][] a,
                              double [] b) {
    double [] v;
    transformation(a,b);
    v = extraction(a,b);
    return v;
  }
  
/* Resolution de Gauss                         */
/* sur une copie des 2 tableaux en parametres  */

  static double [] resolutionGauss(double [][] a,
                                   double [] b) {
    double [][] ca = clone(a);
    double [] cb = clone(b);
    double [] v;
    v = resolution(ca,cb);
    return v;
  }

/////////////////////////////////////////////////
  
/* Programme principal                         */

  public static void main(String [] args) {
    double [][] a;
    double [] b;
    double [] v;
    double [] w;
    int n;
    Ecran.afficher("Taille du systeme: ");
    n = Clavier.saisirInt();
    a = initRandMatrice(n);
    w = initRandTableau(n);
    b = produit(a,w);
    v = resolutionGauss(a,b);
    //Ecran.afficherln("Matrice A:");
    //affichageMatrice(a);
    //Ecran.sautDeLigne();
    //Ecran.afficherln("Vecteur B:");
    //affichageVecteur(b);
    //Ecran.sautDeLigne();
    //Ecran.afficherln("Vecteur a trouver:");
    //affichageVecteur(w);
    //Ecran.sautDeLigne();
    //Ecran.afficherln("Vecteur trouvé par Pivot de Gauss :");
    //affichageVecteur(v);
    double erreurMoyenne = 0.0;
    for ( int i = 0 ; i < n ; i++ ) {
      erreurMoyenne += Math.abs(w[i]-v[i]); }
    erreurMoyenne /= n;
    Ecran.afficherln("Erreur moyenne :",erreurMoyenne);
    }
}