// MC# Examples
// Parallel matrix multiplication.
//
using System;
public class MatrixMultiplierParallel
{
    public static void Main (String[] args)
    {

        if (args.Length < 2)
        {
            Console.WriteLine("Usage: matrixmult.exe <size> <parts>");
            return;
        }

        int         i, j;

        int         N = System.Convert.ToInt32(args[0]); // Matrix size
        int         M = System.Convert.ToInt32(args[1]); // Partition

        double[,]   A = new double[N, N];
        double[,]   B = new double[N, N];
        double[,]   C = new double[N, N];

        Random      rnd = new Random();

        //  Matrix content generation

        for (i = 0; i < N; ++i)
        {
            for (j = 0; j < N; ++j)
            {
                A[i, j] = rnd.NextDouble();
                B[i, j] = rnd.NextDouble();
                C[i, j] = 0.0;
            }
        }

        // Divide matrix between asynchronous processes

        int q = N / M,           
            r = N % M;           

        int from = 0,
            to;

        MatrixMultiplierParallel mmp = new MatrixMultiplierParallel();

        DateTime dt1 = DateTime.Now; // Check the time

        for (i = 0; i < M; ++i)
        {
            to = from + q + (i < r ? 1 : 0);

            mmp.Multiply(N, A, B, C, from, to, mmp.sendStop); // Start the async 
                                                                                               //  method      
            from = to;
        }

        for (i = 0; i < M; ++i) mmp.getStop?(); // Wait the process termination

        Console.WriteLine("Matrix size: {0}, Number of parts: {1}.", N, M);
        Console.WriteLine("Time was " + (DateTime.Now - dt1).TotalSeconds + 
                                       " sec.");                                                 // Check the time
    }

    public handler getStop int() & channel sendStop()
    {
        return;
    }

   public async Multiply (int N, double[,] A, double[,] B, double[,] C,
                                       int from, int to, channel () sendStop)    
  {
        int i, j, k;

        for (i = from; i < to; i++)
        {
            for (j = 0; j < N; j++)
            {
                for (k = 0; k < N; k++)
                  C [i, j] += A [i, k] * B [k, j];
            }
        }

        sendStop ! ();
    }
}