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

#include "stdafx.h"
#include <iostream>
#include <assert.h>
#include <Cry_Math.h>

/*
[][]
+=
-=
=
*
constructor
*/


void getTicks(__int64* pnTime)
{
	__asm {
		mov ebx, pnTime
		rdtsc
		mov [ebx], eax
		mov [ebx+4], edx
	}
}

int nSum =0;


template <class F, unsigned H, unsigned W, unsigned SI, unsigned SJ, unsigned BS>
std::ostream& operator <<	 (std::ostream& os, const TMatrix_tpl<F,H,W,SI,SJ,BS>&m)
{
	unsigned i, j;
	os << "Matrix " << H << "x" << W << ", strides " << SI << "x" << SJ << ", buffer "<< BS << "\n";
	for (i = 0; i < W; ++i)
		os << "--------";
	os << "\n";

	for (i = 0; i < H; ++i)
	{
		for (j = 0; j < W; ++j)
			os << m[i][j] << " ";
		os << "\n";
	}

	for (i = 0; i < nWidth; ++i)
		os << "--------";
	os << "\n";
	return os;
}

template <class TraitsLeft, class TraitsRight>
void testMultiplication (const TraitsLeft& l, const TraitsRight& r)
{
	// make the multiplication
	TraitsLeft::floattype res[l.nHeight][r.nWidth];
	int i, j, k;
	TMatrix_tpl<TMatrixBuf_traits <TraitsLeft::floattype, TraitsLeft::nHeight, TraitsRight::nWidth> > 
		mxP = l*r;
	
	for (i= 0; i < l.nHeight; ++i)
		for( j = 0; j < r.nWidth; ++j)
		{
			res[i][j] = 0;
			for (k = 0; k < l.nWidth && k < r.nHeight; ++ k)
				res[i][j] += l[i][k]*r[k][j];

			assert (fabs(res[i][j] - mxP[i][j]) < 1e-4);
		}
}

int _tmain(int argc, _TCHAR* argv[])
{
	std::cout << "Starting the test.\n"; std::cout.flush();	


	__int64 nTemplate, nNonTemplate;
	nTemplate = 0, nNonTemplate = 0;
	__int64 nBefore, nAfter;
/*
	Matrix33 m33;
	m33.SetIdentity33();
	assert (m33[2][2] == 1);
	m33[1][1] = 3;
	assert (m33[1][1] == 3);
	assert (m33.m_values[1][1] == 3);
	Matrix33 mx33a,mx33b,mx33c;

	Matrix44 m44;
	m44.Identity();
	assert ((m44.Submatrix<3,3>()[1][1]) == 1);
	m44.Submatrix<3,3>()[1][2] = 2;
	assert (m44[1][2] == 2);

	Matrix34 m34;
	m34.SetRotationXYZ34(Ang3d(Vec3d(1,2,3)), Vec3d(3,2,1));
	m33.SetRotationXYZ33(Ang3d(Vec3d(2,1,3)));

	//testMultiplication(m33, m34);
	//testMultiplication(m34, m33);

	typedef TMatrix_tpl<float, 3, 4> M34Base;
	typedef TMatrix_tpl<float, 3, 3> M33Base;
	typedef TMatrix_tpl<float, 4, 3> M43Base;

	Matrix34 m34rReference = m34*m33;
	Matrix34 m34rTest = (const M34Base&)m34*(const M33Base&)m33;

	m33 = Matrix33(m34rTest);
	m34rTest = m33;

	m33 -= m33;

	int i, j;
	for (i = 0; i < 3; ++i)for (j = 0; j < 3; ++j)
		assert (m33[i][j] == 0);

	const int nTotal = 10;
	const int nLoops = 300000;
	for (j = 0; j < nTotal; ++j)
	{
		getTicks(&nBefore);
		for (i = 0; i < nLoops; ++i)
		{
			mx33c = mx33a * mx33b;
			//resetBPC();
		}
		getTicks (&nAfter);
		nTemplate += nAfter - nBefore;
		std::cout << "Templetized Result:(" << ((nAfter - nBefore)/double(nLoops)) << ")\n";
		getTicks(&nBefore);
		for (i = 0; i < nLoops; ++i)
		{
			mx33c = mx33a * mx33b;
			//resetBPC();
		}
		getTicks (&nAfter);
		nNonTemplate += nAfter - nBefore;
		std::cout << "Non-Templetized Result:(" << ((nAfter - nBefore)/double(nLoops)) << ")\n";
	}

	std::cout << "With templates: " << (nTemplate/(double)(nLoops*nTotal)) << "\n";
	std::cout << "Without templates: " << double(nNonTemplate/double(nLoops*nTotal)) << "\n";

	std::cout.flush();
	*/
}

