#include <iostream>
using namespace std;

inline __int64 GetMachineCycleCount()
{      
   __int64 cycles;
   _asm rdtsc; // won't work on 486 or below - only pentium or above
   _asm lea ebx,cycles;
   _asm mov [ebx],eax;
   _asm mov [ebx+4],edx;
   return cycles;
}


struct myStruct {
	double a;
	double b;
} ;

void fill1(double *arr[2], const int numRows);
void fill2(myStruct* arr, const int numRows);
double sum1(double *arr[2], const int numRows);
double sum2(myStruct* arr, const int numRows);

int main()
{
	const int numRows = 1000000;
	int numTests = 5;
	double **arr1 = new double*[numRows];
	for (int i=0;i<numRows;i++)
		arr1[i] = new double[2];
	myStruct *arr2 = new myStruct[numRows];

	fill1(arr1, numRows);
	fill2(arr2, numRows);

	//prime the testing...
	double s1 = sum1(arr1, numRows);
	double s2 = sum2(arr2, numRows);

	cout << "sums: "<<s1<<" "<<s2<<endl;

	double total1 = 0;
	double total2 = 0;

	double temp = 0;

	//timed tests
	for (int i=0;i<numTests;i++) {
		__int64 cycles1 = GetMachineCycleCount();
		double s1 = sum1(arr1, numRows);
		__int64 cycles2 = GetMachineCycleCount();
		double s2 = sum2(arr2, numRows);
		__int64 cycles3 = GetMachineCycleCount();

		__int64 elapsed1 = cycles2 - cycles1;
		__int64 elapsed2 = cycles3 - cycles2;

		total1+=elapsed1;
		total2+=elapsed2;

		temp+=s1+s2;
	}

	cout << temp<<endl;

	double avg1 = (double)((double)(total1 / numTests) / numRows);
	double avg2 = (double)((double)(total2 / numTests) / numRows);

	cout << "2-D Arrays : "<< avg1 << " cycles/row"<<endl;
	cout << "Structs    : "<< avg2 << " cycles/row"<<endl;

	return 0;
}


double sum1(double *arr[2], const int numRows)
{
	cout <<"sum1: ";
	double answer = 0;
	for (int i=0;i<numRows;i++)
	{
		answer+=arr[i][0]+arr[i][1];
		if (i<5)
		{
			printf("0x%p 0x%p ",&arr[i][0], &arr[i][1]);
		}
		
	}
	cout << endl;
	return answer;
}

double sum2(myStruct* arr, const int numRows)
{
	cout <<"sum2: ";
	double answer = 0;
	for (int i=0;i<numRows;i++)
	{
		answer+=arr[i].a + arr[i].b;
		if (i<5)
		{
			printf("0x%p 0x%p ",&arr[i].a, &arr[i].b);
		}
		
	}
	cout << endl;
	return answer;
}

void fill1(double *arr[2], const int numRows)
{
	for (int i=0;i < numRows;i++)
	{
		arr[i][0] = rand();
		arr[i][1] = rand();
	}
}

void fill2(myStruct* arr, const int numRows)
{
	for (int i=0;i<numRows;i++)
	{
		arr[i].a = rand();
		arr[i].b = rand();
	}
}
