/* Produit vecteur*matrice                      */
/* Evaluation du temps d'execution              */  

public class TestProduitVecteurMatriceAvecTransposition {

/* Fonction de creation d'une vecteur de double */
/* initialise avec des nombres aleatoires       */
/* compris dans l'intervalle [0.0,max]          */
/* et un chiffre apres la virgule               */

  static double [] initRandVecteur(int lignes,
                                     double max) {
    double [] tab = new double[lignes];
    for ( int i = 0 ; i < lignes ; i++ ) {
      tab[i] = ((int) (Math.random()*max*1000.0))/1000.0; }
    return tab;
  }

/* Fonction de creation d'une matrice de double */
/* initialise avec des nombres aleatoires       */
/* compris dans l'intervalle [0.0,max]          */
/* et un chiffre apres la virgule               */

  static double [][] initRandMatrice(int lignes,
                                     int colonnes,
                                     double max) {
    double [][] tab = new double[lignes][colonnes];
    for ( int i = 0 ; i < lignes ; i++ ) {
      for ( int j = 0 ; j < colonnes ; j++ ) {
        tab[i][j] = ((int) (Math.random()*max*1000.0))/1000.0; } }
    return tab;
  }

//////////////////////////////////////////////////

  static void transposition(double [][] m) {
    int n = m.length;
    for ( int i = 0 ; i < n-1 ; i++ ) {
      for ( int j = i+1 ; j < n ; j++ ) {
        double aux = m[i][j];
        m[i][j] = m[j][i];
        m[j][i] = aux; } }
  }
  
/* Fonction de calcul du produit d'une matrice */
/* carree de reel de taille n.n par un tableau */
/* de reel de taille n                         */
/* n quelconque                                */
/* Retour: Un tableau de reel de taille n      */

  static double [] produitVecteurMatriceAvecTransposition(double [] v,
                                                          double [][] m) {
    int n = v.length;
    double [] w = new double[n];
    transposition(m);
    for ( int i = 0 ; i < n ; i++ ) {
      w[i] = 0.0;
      for ( int j = 0 ; j < n ; j++ ) {
        w[i] = w[i] + v[j]*m[i][j]; } }
    transposition(m);
    return w;
  }
  
/* Fonction de calcul du produit d'une matrice */
/* carree de reel de taille n.n par un tableau */
/* de reel de taille n                         */
/* n quelconque                                */
/* Retour: Un tableau de reel de taille n      */

  static void produitVecteurMatriceAvecTransposition(double [] v,
                                    double [][] m,
                                    double [] w) {
    int n = v.length;
    for ( int i = 0 ; i < n ; i++ ) {
      w[i] = 0.0;
      for ( int j = 0 ; j < n ; j++ ) {
        w[i] = w[i] + v[j]*m[j][i]; } }
  }
  
  static void testsRapiditeProduitVecteurMatriceAvecTransposition(int temps,int ni,int nf,int inc) {
    Ecran.formater("%6s%12s%14s%22s%14s","Taille","Appels","Temps total","Temps moyen","o(n*n)");
    Ecran.formater("%12s%14s%22s%14s\n","Appels","Temps total","Temps moyen","o(n*n)");
    for ( int n = ni ; n <= nf ; n = n+inc ) { 
      double [][] m = initRandMatrice(n,n,10.0);
      double [] v = initRandVecteur(n,10.0);
      { double [] w = new double[n];
        Utilitaires.Minuteur minuteur = new Utilitaires.Minuteur();
        minuteur.temps = temps*1000;
        minuteur.lancement();
        long i = 0;
        long ti = System.nanoTime();
        do {
          produitVecteurMatriceAvecTransposition(v,m,w);
          i++; }
        while ( minuteur.enCours) ;
        long t = System.nanoTime()-ti;
        Ecran.formater("%6d%12d%14d%22.3f%14.4f",n,i,t,(double) t/i,((double) t/i)/((double) n*n)); }
      { Utilitaires.Minuteur minuteur = new Utilitaires.Minuteur();
        minuteur.temps = temps*1000;
        minuteur.lancement();
        long i = 0;
        long ti = System.nanoTime();
        double [] w;
        do {
          w = produitVecteurMatriceAvecTransposition(v,m);
          i++; }
        while ( minuteur.enCours) ;
        long t = System.nanoTime()-ti;
        Ecran.formater("%12d%14d%22.3f%14.4f\n",i,t,(double) t/i,((double) t/i)/((double) n*n)); } }
  }

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

  public static void main(String [] args) {
    int temps;
    int ni;
    int nf;
    int inc;
    Ecran.afficher("Nombre de secondes de test? ");
    temps = Clavier.saisirInt();
    Ecran.afficher("Taille initiale? ");
    ni = Clavier.saisirInt();
    Ecran.afficher("Taille finale  ? ");
    nf = Clavier.saisirInt();
    Ecran.afficher("Increment      ? ");
    inc = Clavier.saisirInt();
    testsRapiditeProduitVecteurMatriceAvecTransposition(temps,ni,nf,inc);
  }
}