class MultMatrixMS implements Runnable
{
   private Thread t;
   private double[][] matrix1;
   private double[][] matrix2;
   private int nThreads, iThread, dim, row, col;
   private double res;

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

	  dim = d;
	  nThreads = nT;
   }

   public void calculaCelula( int i, int j, int iT )
   {
	  res = 0;
	  row = i;
	  col = j;
	  iThread = iT;
      t = new Thread ( this );
      t.start();
   }

   public void run()
   {
	  int nCels = dim/nThreads;
	  int shift = (dim/nThreads)*iThread;
	  for ( int k = 0; k < nCels; ++k ) res += matrix1[row][k+shift] * matrix2[k+shift][col];
   }

   public double getRes()
   {
	  try
	  {
		t.join();
	  }
	  catch( InterruptedException e )
	  {
		e.printStackTrace();
	  }
	  return res;
   }
}

class TesteMS
{
   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();

	  MultMatrixMS[] m = new MultMatrixMS[nThreads];
      for ( int t = 0; t < nThreads; ++t ) m[t] = new MultMatrixMS(m1, m2, d, nThreads);

      for ( int i = 0; i < d; ++i )
      {
		 for ( int j = 0; j < d; ++j )
		 {
			for ( int t = 0; t < nThreads; ++t ) m[t].calculaCelula(i, j, t);

			m3[i][j] = 0;
			for ( int t = 0; t < nThreads; ++t ) m3[i][j] += m[t].getRes();
		 }
      }

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