

class MultMatrixGeo implements Runnable
{
   private Thread t;
   private double[][] matrix1;
   private double[][] matrix2;
   private double[][] matrix3;
   private int nThreads, iThread, dim;

   public MultMatrixGeo( double[][] m1, double[][] m2, double[][] m3, int d, int nT )
   {
	  matrix1 = m1;
	  matrix2 = m2;
	  matrix3 = m3;

	  dim = d;
	  nThreads = nT;
      t = new Thread ( this );
   }

   public void calculaCelula( int iT )
   {
      iThread = iT;
      t.start();
   }

   public void run()
   {
	  int nRows = dim/nThreads;
	  int shift = iThread*nRows;
      for ( int i = 0; i < nRows; ++i )
	  {
		 for ( int j = 0; j < dim; ++j )
		 {
			matrix3[i+shift][j] = 0;
			for ( int k = 0; k < dim; ++k )
			{
			   matrix3[i+shift][j] += matrix1[i+shift][k] * matrix2[k][j];
			}
		 }
	  }
   }

   public void join()
   {
	  try
	  {
		t.join();
	  }
	  catch( InterruptedException e )
	  {
		e.printStackTrace();
	  }
   }
}

class TesteGeo
{
   public static void main( String args[] )
   {
      int d = Integer.parseInt(args[0]);
	  int nThreads = Integer.parseInt(args[1]);

      double[][] m1 = new double[d][];
      for ( int i = 0; i < d; ++i )
      {
         m1[i] = new double[d];
         for ( int j = 0; j < d; ++j ) m1[i][j] = (i*d)+j;
      }

      double[][] m2 = new double[d][];
      for ( int i = 0; i < d; ++i )
      {
         m2[i] = new double[d];
         for ( int j = 0; j < d; ++j ) m2[i][j] = (i*d)+j;
      }

      double[][] m3 = new double[d][];
      for ( int i = 0; i < d; ++i ) m3[i] = new double[d];

      long startTime = System.currentTimeMillis();

	  MultMatrixGeo[] m = new MultMatrixGeo[nThreads];
      for ( int i = 0; i < nThreads; ++i )
      {
         m[i] = new MultMatrixGeo(m1, m2, m3, d, nThreads);
         m[i].calculaCelula(i);
      }
	  for ( int i = 0; i < nThreads; ++i ) m[i].join();

      long endTime = System.currentTimeMillis();
      System.out.printf("duration = %f\n", (endTime - startTime)/1000.0);
   }
}
