// bsp9.cpp : Defines the entry point for the console application.


#include "stdafx.h"

#include <time.h>

#include <windows.h>  // LARGE_INTEGER

#include <omp.h>

// fuer die genaue Zeitmessung
LARGE_INTEGER GetTickCount2() {
	HANDLE hCurrentProcess = GetCurrentProcess();
	DWORD dwProcessAffinity;
	DWORD dwSystemAffinity;
	LARGE_INTEGER result;

	GetProcessAffinityMask(hCurrentProcess,&dwProcessAffinity, &dwSystemAffinity);
	SetProcessAffinityMask(hCurrentProcess,1);
	QueryPerformanceCounter(&result);
	SetProcessAffinityMask(hCurrentProcess,dwProcessAffinity);
	return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
	const int MAX_THREAD=4;
	const int N = 10000; // 200 5000  8000;

	int tid;
	//float a[N][N];
	double  **a;
	a = new (double* [N]);      // Allocate Zeilen Pointers
	for (int i = 0; i < N; i++)
	{
      a[i] = new double[N];    // Allocate rows
	}

	
    LARGE_INTEGER t1,t2;
	long z;


	LARGE_INTEGER Frequency;
	if ( ! QueryPerformanceFrequency( &Frequency ) )
	{
		Frequency.HighPart=0;
		Frequency.LowPart=0;
	}
	printf("Frequency: %u %u\n ", Frequency.HighPart, Frequency.LowPart );

	omp_set_num_threads(MAX_THREAD);

	t1 = GetTickCount2();
		for (int i1=0; i1<N; i1++) {
			a[0][i1] = 0.0;
			for (int i2=0; i2<N; i2++) {
				// printf("AnzThread: %d\n", omp_get_num_threads());
				a[0][i2] += a[i2][i1];
			}
		}
	t2 = GetTickCount2();
	z=  (t2.HighPart-t1.HighPart)  +  (t2.LowPart-t1.LowPart);
	printf("Ein Thread  time: %u\n ", z );
	if (t2.HighPart==t1.HighPart) puts("high=high\n");


	t1 = GetTickCount2();
		//Console::WriteLine("AnzThread: {0}", omp_get_num_threads());
	#pragma omp parallel for private(tid)
		for (int i1=0; i1<N; i1++) {
			a[0][i1] = 0.0;
			for (int i2=0; i2<N; i2++) {
				tid = omp_get_thread_num();						
				//printf("tid: %d  i1: %d  AnzThread: %d\n", tid, i1, omp_get_num_threads());
				a[0][i2] += a[i2][i1];
			}
		}
	t2 = GetTickCount2();
	z=  (t2.HighPart-t1.HighPart)  +  (t2.LowPart-t1.LowPart);
	printf("Aussen parallelisiert  time: %u\n ", z );
	if (t2.HighPart==t1.HighPart) puts("high=high");



	
	t1 = GetTickCount2();
	for (int i1=0; i1<N; i1++) {
		a[0][i1] = 0.0;
		#pragma omp parallel for
			for (int i2=0; i2<N; i2++) {
				//Console::WriteLine("AnzThread: {0}", omp_get_num_threads());
				a[0][i2] += a[i2][i1];
			}
	}

	t2 = GetTickCount2();
	z=  (t2.HighPart-t1.HighPart)  +  (t2.LowPart-t1.LowPart);
	printf("Innen parallelisiert  time: %u\n ", z );
	if (t2.HighPart==t1.HighPart) puts("high=high");


	
	t1 = GetTickCount2();
	#pragma omp parallel for
		for (int i1=0; i1<N; i1++) {
			a[0][i1] = 0.0;
			#pragma omp parallel for
				for (int i2=0; i2<N; i2++) {
					//Console::WriteLine("AnzThread: {0}", omp_get_num_threads());
					a[0][i2] += a[i2][i1];
				}
		}

	t2 = GetTickCount2();
	z=  (t2.HighPart-t1.HighPart)  +  (t2.LowPart-t1.LowPart);
	printf("Innen und Außen parallelisiert  time: %u\n ", z );
	if (t2.HighPart==t1.HighPart) puts("high=high");

	char ch[200];
	printf("\nEnde\n " );
	gets(ch);

	return 0;
}
