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

public class TestProduitMatriceMatrice3 {

/* 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;
  }

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

/* Fonction de calcul du produit d'un tableau   */
/* de dimension 2 de taille n.m                 */
/* par un tableau de dimension 2 de taille m.p  */
/* Resultat: Un tableau de dimension 2          */
/* de taille n.p                                */

  static void produitMatriceMatrice(double [][] m1,double [][] m2,
                                    double [][] r) {
    int n = m1.length;
    int m = m2.length;
    int p = m2[0].length;
    for ( int i = 0 ; i < n ; i++ ) {
      for ( int j = 0 ; j < p ; j++ ) {
        double v = 0.0;
        for ( int k = 0 ; k < m ; k++ ) {
          v += m1[i][k]*m2[k][j]; }
        r[i][j] = v; } }
  }

  static void testsProduitMatricesNMP(int temps,int ni,int nf,
                                      int inc,int taille) {
    Ecran.formater("%18s%12s%14s%22s%14s",
                   "Tailles","Appels","Temps total","Temps moyen",
                   "o(n*m*p)");
    Ecran.formater("%18s%12s%14s%22s%14s",
                   "Tailles","Appels","Temps total","Temps moyen",
                   "o(n*m*p)");
    Ecran.formater("%18s%12s%14s%22s%14s\n",
                   "Tailles","Appels","Temps total","Temps moyen",
                   "o(n*m*p)");
    for ( int v = ni ; v <= nf ; v = v+inc ) {
      { double [][] m1 = initRandMatrice(v,taille,10.0);
        double [][] m2 = initRandMatrice(taille,taille,10.0);
        double [][] mat = new double[v][taille];
        Utilitaires.Minuteur mntr = new Utilitaires.Minuteur();
        mntr.temps = temps*1000;
        mntr.lancement();
        long i = 0;
        long ti = System.nanoTime();
        do {
          produitMatriceMatrice(m1,m2,mat);
          i++; }
        while ( mntr.enCours );
        long t = System.nanoTime()-ti;
        System.gc();
        Ecran.formater("%6d%6d%6d%12d%14d%22.3f%14.4f",
                       v,taille,taille,i,t,(double) t/i,
                       ((double) t/i)/((double) v*taille*taille)); }
      { double [][] m1 = initRandMatrice(taille,v,10.0);
        double [][] m2 = initRandMatrice(v,taille,10.0);
        double [][] mat = new double[taille][taille];
        Utilitaires.Minuteur mntr = new Utilitaires.Minuteur();
        mntr.temps = temps*1000;
        mntr.lancement();
        long i = 0;
        long ti = System.nanoTime();
        do {
          produitMatriceMatrice(m1,m2,mat);
          i++; }
        while ( mntr.enCours );
        long t = System.nanoTime()-ti;
        System.gc();
        Ecran.formater("%6d%6d%6d%12d%14d%22.3f%14.4f",
                       taille,v,taille,i,t,(double) t/i,
                       ((double) t/i)/((double) taille*v*taille)); }
      { double [][] m1 = initRandMatrice(taille,taille,10.0);
        double [][] m2 = initRandMatrice(taille,v,10.0);
        double [][] mat = new double[taille][v];
        Utilitaires.Minuteur mntr = new Utilitaires.Minuteur();
        mntr.temps = temps*1000;
        mntr.lancement();
        long i = 0;
        long ti = System.nanoTime();
        do {
          produitMatriceMatrice(m1,m2,mat);
          i++; }
        while ( mntr.enCours );
        long t = System.nanoTime()-ti;
        System.gc();
        Ecran.formater("%6d%6d%6d%12d%14d%22.3f%14.4f\n",
                       taille,taille,v,i,t,(double) t/i,
                       ((double) t/i)/((double) taille*taille*v)); } }
  }

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

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