//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
//  
using System;

namespace MatrixMultiplication
{
	/// <summary>
	/// Podsumowanie dla Class1.
	/// </summary>
	class MatrixMultiplicationMain
	{
		static void Main(string[] args)
		{
			const int niter = 50;
			const int xdim = 100;
			const int ydim = 100;
			double [,] A = new double [,] {{2,3},
										   {3,4},
										   {4,5}};
			double [,] B = new double [,] {{2,3,4},
										   {3,4,5}};
			double [,] C;
			double [,] D;

			MatrixMultiplyDirect direct = new MatrixMultiplyDirect(A, B);
			C = direct.Multiply();
			MatrixMultiplyFixed fix = new MatrixMultiplyFixed(A, B);
			C = D = fix.Multiply();
			MatrixMultiplyLoop loop = new MatrixMultiplyLoop(A, B);
			C = D = loop.Multiply();
			for(int i = 0; i < C.GetLength(0); i++)
			{
				for(int j = 0; j < C.GetLength(1); j++)
				{
					Console.WriteLine("C[{0},{1}] = {2}", i, j, C[i,j]);
				}
			}

			A = new double [ydim, xdim];
			B = new double [ydim, xdim];

			Random r = new Random();

			for(int i = 0; i < ydim; i++)
			{
				for(int j = 0; j < xdim; j++)
				{
					A[i,j] = r.NextDouble();
					B[i,j] = r.NextDouble();
				}
			}

			direct = new MatrixMultiplyDirect(A, B);
			int start,stop;

			start = Environment.TickCount;
			for(int i = 0; i < niter; i++)
				C = direct.Multiply();
			stop = Environment.TickCount;
			Console.WriteLine("Bezpośrednie takty: {0} {1} mnożeń/sekundę", stop - start, ((double)niter/(double)(stop-start)) * 1000);

			fix = new MatrixMultiplyFixed(A, B);
			start = Environment.TickCount;
			for(int i = 0; i < niter * 100000; i++)
				C = fix.Multiply();
			stop = Environment.TickCount;
			Console.WriteLine("Stałe takty: {0} {1} mnożeń/sekundę", stop - start, ((double)(niter*100000)/(double)(stop-start)) * 1000);

			loop = new MatrixMultiplyLoop(A, B);
			start = Environment.TickCount;
			for(int i = 0; i < niter; i++)
				D = loop.Multiply();
			stop = Environment.TickCount;
			Console.WriteLine("Takty pętli: {0} {1} mnożeń/sekundę", stop - start, ((double)(niter)/(double)(stop-start)) * 1000);
			double maxdeviation = 0.0;
			double temp;
			for(int i = 0; i < ydim; i++)
			{
				for(int j = 0; j < xdim; j++)
				{
					temp = C[i,j] - D[i,j];
					if(temp > maxdeviation)
						maxdeviation = temp;
				}
			}
			Console.WriteLine("Maksymalne odchylenie: {0}", maxdeviation);
		}
	}
}
