//////////////////////////////////////////////////////////////////////////////
//
// Asura_UnitTest_Maths_Vector4.cpp
//
// Copyright (c) 2005 Rebellion. All rights reserved.
//
// Description:
//
//     Unit tests for Asura_AVector4
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifdef ASURA_SUPPORT_UNITTEST

#include "UnitTest/Asura_UnitTest.h"

// Asura Platform-independent
#include "Core/Asura_HalfFloat.h"
#include "Core/Asura_Maths.h"

// V E C T O R   3 ///////////////////////////////////////////////////////////
static const Asura_AVector4 xVec1234(1.0f, 2.0f, 3.0f, 4.0f);
static const Asura_AVector4 xVec4567(4.0f, 5.0f, 6.0f, 7.0f);
static const Asura_AVector4 xVec78910(7.0f, 8.0f, 9.0f, 10.f);
static const Asura_AVector4 xVec2468(2.0f, 4.0f, 6.0f, 8.f);
static const Asura_AVector4 xVec1000(1.0f, 0.0f, 0.0f, 0.0f);
static const Asura_AVector4 xVec0100(0.0f, 1.0f, 0.0f, 0.0f);
static const Asura_AVector4 xVec0010(0.0f, 0.0f, 1.0f, 0.0f);
static const Asura_AVector4 xVec0001(0.0f, 0.0f, 0.0f, 1.0f);
static const Asura_AVector4 xVec2000(2.0f, 0.0f, 0.0f, 0.0f);
static const Asura_AVector4 xVec0200(0.0f, 2.0f, 0.0f, 0.0f);
static const Asura_AVector4 xVec0020(0.0f, 0.0f, 2.0f, 0.0f);
static const Asura_AVector4 xVec0002(0.0f, 0.0f, 0.0f, 2.0f);
static const Asura_AVector4 xVec1111(1.0f, 1.0f, 1.0f, 1.0f);
static const Asura_AVector4 xVec2222(2.0f, 2.0f, 2.0f, 2.0f);
static const Asura_AVector4 xVec3333(3.0f, 3.0f, 3.0f, 3.0f);
static const Asura_AVector4 xVec4444(4.0f, 4.0f, 4.0f, 4.0f);
static const Asura_AVector4 xVecMinus1111(-1.0f, -1.0f, -1.0f, -1.0f);
static const Asura_AVector4 xVecMinus1234(-1.0f, -2.0f, -3.0f, -4.0f);

ASURA_UNITTEST(LoadAndStore, Asura_AVector4)
{
	// from float array
	float* pfFloats = reinterpret_cast<float*>(Asura_AllocateAlign(7*sizeof(float), ASURA_ALIGN_16_BYTE));
	// fill out array
	{
		float afFloats[7] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
		memcpy( pfFloats, afFloats, 7*sizeof(float) );
	}
	Asura_AVector4 xVectorFromFloats;

	xVectorFromFloats.ZeroW0();
	xVectorFromFloats.LoadAligned(pfFloats);
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFromFloats );

	xVectorFromFloats.ZeroW0();
	xVectorFromFloats.LoadUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( xVec4567 == xVectorFromFloats );

	// to float array
	memset(pfFloats, 0, 7*sizeof(float));
	xVec4567.StoreAligned(pfFloats);
	xVec1234.StoreUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( pfFloats[0] == 4.0f );
	ASURA_UNITTEST_CHECK( pfFloats[1] == 5.0f );
	ASURA_UNITTEST_CHECK( pfFloats[2] == 6.0f );
	ASURA_UNITTEST_CHECK( pfFloats[3] == 1.0f );
	ASURA_UNITTEST_CHECK( pfFloats[4] == 2.0f );
	ASURA_UNITTEST_CHECK( pfFloats[5] == 3.0f );
	ASURA_UNITTEST_CHECK( pfFloats[6] == 4.0f );

	Asura_DeallocateAlign(pfFloats);

	// to aligned half array
	Asura_HalfFloat axHalves[8];
	xVec4567.StoreAlignedHalf(&axHalves[0]);
	xVec1234.StoreAlignedHalf(&axHalves[4]);
	ASURA_UNITTEST_CHECK( axHalves[0] == 4.0f );
	ASURA_UNITTEST_CHECK( axHalves[1] == 5.0f );
	ASURA_UNITTEST_CHECK( axHalves[2] == 6.0f );
	ASURA_UNITTEST_CHECK( axHalves[3] == 7.0f );
	ASURA_UNITTEST_CHECK( axHalves[4] == 1.0f );
	ASURA_UNITTEST_CHECK( axHalves[5] == 2.0f );
	ASURA_UNITTEST_CHECK( axHalves[6] == 3.0f );
	ASURA_UNITTEST_CHECK( axHalves[7] == 4.0f );
}

ASURA_UNITTEST(PlusEquals, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector.ZeroW0();
	xVector += xVec1000;
	ASURA_UNITTEST_CHECK( xVector == xVec1000 );
	xVector += xVec0100;
	xVector += xVec0010;
	xVector += xVec0001;
	ASURA_UNITTEST_CHECK( xVector == xVec1111 );
	xVector = xVec1234;
	xVector += xVecMinus1234;
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0 );
}

ASURA_UNITTEST(MinusEquals, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector.ZeroW0();
	xVector -= xVec1000;
	xVector -= xVec0100;
	xVector -= xVec0010;
	xVector -= xVec0001;
	ASURA_UNITTEST_CHECK( xVector == xVecMinus1111 );

	xVector = xVec1234;
	xVector -= xVec1234;
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0 );
}

ASURA_UNITTEST(TimesEquals, Asura_AVector4)
{
	Asura_AVector4 xVector(xVec1234);
	xVector *= 2.0f;
	ASURA_UNITTEST_CHECK( xVector == xVec2468 );

	xVector = xVec1234;
	xVector *= -1.0f;
	ASURA_UNITTEST_CHECK( xVector == xVecMinus1234 );

	xVector = xVec1234;
	xVector *= 0.0f;
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0 );
}

ASURA_UNITTEST(DivideEquals, Asura_AVector4)
{
	Asura_AVector4 xVector(xVec2468);
	xVector /= 2.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1234, 1.0e-3f) );

	xVector = xVec1234;
	xVector /= -1.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals( xVecMinus1234, 1.0e-3f ) );

	xVector = xVec1234;
	xVector /= 1.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals( xVec1234, 1.0e-3f ) );
}

ASURA_UNITTEST(UnaryMinus, Asura_AVector4)
{
	ASURA_UNITTEST_CHECK( -xVec1234 == xVecMinus1234 );
}

ASURA_UNITTEST(Addition, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector = xVec1234 + xVec1234;
	ASURA_UNITTEST_CHECK( xVector == xVec2468 );

	xVector = xVec1234 + xVecMinus1234;
	ASURA_UNITTEST_CHECK( xVector ==  Asura_Maths::ZeroAVector4W0);

	xVector = xVec1234 + Asura_Maths::ZeroAVector4W0;
	ASURA_UNITTEST_CHECK( xVector == xVec1234 );

	xVector = xVec1000 + xVec0100 + xVec0010 + xVec0001;
	ASURA_UNITTEST_CHECK( xVector == xVec1111 );
}

ASURA_UNITTEST(Subtraction, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector = (((Asura_Maths::ZeroAVector4W0 - xVec1000) - xVec0100) - xVec0010) - xVec0001;
	ASURA_UNITTEST_CHECK( xVector == xVecMinus1111 );

	xVector = xVec1234 - xVec1234;
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0 );

	xVector = xVec1234 - xVecMinus1234;
	ASURA_UNITTEST_CHECK( xVector == xVec2468 );
}

ASURA_UNITTEST(ScalarMultiplication, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector = xVec1234 * 2.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec2468,  1.0e-3f) );

	xVector = xVec1234 * -1.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVecMinus1234,  1.0e-3f) );

	xVector = xVec1234 * 0.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(Asura_Maths::ZeroAVector4W0) );

	xVector = 2.0f * xVec1234;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec2468) );

	xVector = -1.0f * xVec1234;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVecMinus1234) );

	xVector = 0.0f * xVec1234;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(Asura_Maths::ZeroAVector4W0) );

}

ASURA_UNITTEST(ScalarDivision, Asura_AVector4)
{
	Asura_AVector4 xVector;
	xVector = xVec2468 / 2.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1234) );

	xVector = xVec1234 / -1.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVecMinus1234) );

	xVector = xVec1234 / 1.0f;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1234) );
}

ASURA_UNITTEST(ScalarProduct, Asura_AVector4)
{
	Asura_AVector4 xVector(xVec4567);
	xVector.Normalise();

	// 3-component dot-product...
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0001.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0010.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0100.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec1000.DotProduct3(xVec0100), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1000.DotProduct3(xVec1000), 0.0f );

	ASURA_UNITTEST_FLOATS_EQUAL( 0.611f, xVector.DotProduct3(xVector), 1.0e-3f );

	ASURA_UNITTEST_FLOATS_EQUAL( 6.0f, xVec1234.DotProduct3(xVec1111), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1234.DotProduct3(xVec1000), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, xVec1234.DotProduct3(xVec0100), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 3.0f, xVec1234.DotProduct3(xVec0010), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec1234.DotProduct3(xVec0001), 1.0e-3f );

	// 4-component dot-product...
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0001.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0010.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec0100.DotProduct3(xVec1000), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 0.0f, xVec1000.DotProduct3(xVec0100), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1000.DotProduct3(xVec1000), 0.0f );

	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVector.DotProduct4(xVector), 1.0e-3f );

	ASURA_UNITTEST_FLOATS_EQUAL(10.0f, xVec1234.DotProduct4(xVec1111), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1234.DotProduct4(xVec1000), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, xVec1234.DotProduct4(xVec0100), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 3.0f, xVec1234.DotProduct4(xVec0010), 1.0e-3f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec1234.DotProduct4(xVec0001), 1.0e-3f );
}

ASURA_UNITTEST(CrossProduct, Asura_AVector4)
{
	ASURA_UNITTEST_CHECK( xVec1000.ApproximatelyEquals(xVec0100 ^ xVec0010) );
	ASURA_UNITTEST_CHECK( xVec0100.ApproximatelyEquals(xVec0010 ^ xVec1000) );
	ASURA_UNITTEST_CHECK( xVec0010.ApproximatelyEquals(xVec1000 ^ xVec0100) );
	ASURA_UNITTEST_CHECK( (xVec1234 ^ xVec4567) == -(xVec4567 ^ xVec1234) );
}

ASURA_UNITTEST(ApproximateEquality, Asura_AVector4)
{
	Asura_AVector4 xVec1(0.1f, 0.2f, 0.3f, 0.4f);
	Asura_AVector4 xVec2(0.1001f, 0.2001f, 0.30001f, 0.40001f);
	Asura_AVector4 xVec3(1.001f, 0.2001f, 0.30001f, 0.40001f);

	ASURA_UNITTEST_CHECK( xVec1.ApproximatelyEquals(xVec2) );
	ASURA_UNITTEST_CHECK( !xVec1.ApproximatelyEquals(xVec3) );
}

ASURA_UNITTEST(Inequality, Asura_AVector4)
{
	ASURA_UNITTEST_CHECK( !(xVec1000 != xVec1000) );
	ASURA_UNITTEST_CHECK( !(xVec0100 != xVec0100) );
	ASURA_UNITTEST_CHECK( !(xVec0010 != xVec0010) );
	ASURA_UNITTEST_CHECK( !(xVec0001 != xVec0001) );
	ASURA_UNITTEST_CHECK( xVec0010 != xVec1234 );
	ASURA_UNITTEST_CHECK( !(xVecMinus1234 != xVecMinus1234) );
	ASURA_UNITTEST_CHECK( xVec1234 != xVecMinus1234 );
}

ASURA_UNITTEST(ComponentwiseProduct, Asura_AVector4)
{
	ASURA_UNITTEST_CHECK( (xVec1000.ComponentwiseProduct( xVec1000 )) == xVec1000 );
	ASURA_UNITTEST_CHECK( (xVec0100.ComponentwiseProduct( xVec0100 )) == xVec0100 );
	ASURA_UNITTEST_CHECK( (xVec0010.ComponentwiseProduct( xVec0010 )) == xVec0010 );
	ASURA_UNITTEST_CHECK( (xVec0001.ComponentwiseProduct( xVec0001 )) == xVec0001 );
	ASURA_UNITTEST_CHECK( (xVec1234.ComponentwiseProduct( xVec0001 )) == Asura_AVector4(0.0f, 0.0f, 0.0f, 4.0f)  );
	ASURA_UNITTEST_CHECK( (xVec1234.ComponentwiseProduct( xVec0010 )) == Asura_AVector4(0.0f, 0.0f, 3.0f, 0.0f)  );
	ASURA_UNITTEST_CHECK( (xVec1234.ComponentwiseProduct( xVec0100 )) == Asura_AVector4(0.0f, 2.0f, 0.0f, 0.0f)  );
	ASURA_UNITTEST_CHECK( (xVec1234.ComponentwiseProduct( xVec1000 )) == Asura_AVector4(1.0f, 0.0f, 0.0f, 0.0f)  );
	ASURA_UNITTEST_CHECK( (xVec1234.ComponentwiseProduct( xVec1234 )) == Asura_AVector4(1.0f, 4.0f, 9.0f, 16.0f) );
}

ASURA_UNITTEST(Normalise, Asura_AVector4)
{
	Asura_AVector4 xVector = xVec0001;
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0001) );
	xVector = xVec0010;
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0010) );
	xVector = xVec0100;
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0100) );
	xVector = xVec1000;
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1000) );

	Asura_AVector4 xVector2;
	xVector = xVec0001;
	xVector2 = xVector; 
	xVector2.Normalise();
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0001) );
	xVector = xVec0010;
	xVector2 = xVector; 
	xVector2.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0010) );
	xVector = xVec0100;
	xVector2 = xVector; 
	xVector2.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0100) );
	xVector = xVec1000;
	xVector2 = xVector; 
	xVector2.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1000) );

	xVector = Asura_AVector4(2.0f, 0.0f, 0.0f, 0.0f);
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1000) );
	xVector = Asura_AVector4(0.0f, 2.0f, 0.0f, 0.0f);
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0100) );
	xVector = Asura_AVector4(0.0f, 0.0f, 2.0f, 0.0f);
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0010) );
	xVector = Asura_AVector4(0.0f, 0.0f, 0.0f, 2.0f);
	xVector.Normalise();
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0001) );

	xVector = xVec4567;
	xVector.Normalise();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVector.Magnitude(), 0.001f );
}

ASURA_UNITTEST(NormaliseReturningMagnitude, Asura_AVector4)
{
	float fMagnitude;
	Asura_AVector4 xVector, xVector2;
	
	xVector = xVec0001;
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0001) );
	xVector = xVec0010;
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0010) );
	xVector = xVec0100;
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0100) );
	xVector = xVec1000;
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1000) );

	xVector = xVec0001;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0001) );
	xVector = xVec0010;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0010) );
	xVector = xVec0100;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0100) );
	xVector = xVec1000;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, fMagnitude, 0.001f);
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec1000) );

	xVector = Asura_AVector4(2.0f, 0.0f, 0.0f, 0.0f);
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec1000) );
	xVector = Asura_AVector4(0.0f, 2.0f, 0.0f, 0.0f);
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0100) );
	xVector = Asura_AVector4(0.0f, 0.0f, 2.0f, 0.0f);
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0010) );
	xVector = Asura_AVector4(0.0f, 0.0f, 0.0f, 2.0f);
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector.ApproximatelyEquals(xVec0001) );

	xVector = Asura_AVector4(2.0f, 0.0f, 0.0f, 0.0f);
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec1000) );
	xVector = Asura_AVector4(0.0f, 2.0f, 0.0f, 0.0f);
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0100) );
	xVector = Asura_AVector4(0.0f, 0.0f, 2.0f, 0.0f);
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0010) );
	xVector = Asura_AVector4(0.0f, 0.0f, 0.0f, 2.0f);
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, fMagnitude, 0.001f) ;
	ASURA_UNITTEST_CHECK( xVector2.ApproximatelyEquals(xVec0001) );

	xVector = xVec4567;
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( Asura_Maths::Sqrt(16.0f + 25.0f + 36.0f + 49.0f), fMagnitude, 0.001f) ;
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVector.Magnitude(), 0.001f );
	xVector = xVec4567;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_FLOATS_EQUAL( Asura_Maths::Sqrt(16.0f + 25.0f + 36.0f + 49.0f), fMagnitude, 0.001f) ;
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVector2.Magnitude(), 0.001f );

	// JAT 06/07/07 Normalise functions should leave a 0,0,0,0 vector as 0,0,0,0
	xVector.ZeroW0();
	Asura_AVector4 xVecZero = xVector;
	xVector2 = xVector;
	fMagnitude = xVector2.NormaliseReturningMagnitude();
	ASURA_UNITTEST_CHECK( fMagnitude == 0.0f );
	ASURA_UNITTEST_CHECK( xVector2 == xVecZero );
	ASURA_UNITTEST_CHECK( (xVector2 + xVec1234) == xVec1234 );
	fMagnitude = xVector.NormaliseReturningMagnitude();
	ASURA_UNITTEST_CHECK( fMagnitude == 0.0f );
	ASURA_UNITTEST_CHECK( xVector == xVecZero );
	ASURA_UNITTEST_CHECK( (xVector + xVec1234) == xVec1234 );
}

ASURA_UNITTEST(Magnitude, Asura_AVector4)
{
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0001.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0010.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0100.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1000.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, xVec1111.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( Asura_Maths::Sqrt(4.0f + 16.0f + 36.0f + 64.0f), xVec2468.Magnitude(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( Asura_Maths::Sqrt(1.0f + 4.0f + 9.0f + 16.0f), xVec1234.Magnitude(), 0.001f );
}

ASURA_UNITTEST(MagnitudeSquared, Asura_AVector4)
{
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0001.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0010.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec0100.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1000.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec1111.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( (4.0f + 16.0f + 36.0f + 64.0f), xVec2468.MagnitudeSquared(), 0.001f );
	ASURA_UNITTEST_FLOATS_EQUAL( (1.0f + 4.0f + 9.0f + 16.0f), xVec1234.MagnitudeSquared(), 0.001f );
}

ASURA_UNITTEST(GetXYZW, Asura_AVector4)
{
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1234.GetX(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, xVec1234.GetY(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 3.0f, xVec1234.GetZ(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec1234.GetW(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec4567.GetX(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 5.0f, xVec4567.GetY(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 6.0f, xVec4567.GetZ(), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 7.0f, xVec4567.GetW(), 0.0f );
}

ASURA_UNITTEST(SetXYZW, Asura_AVector4)
{
	Asura_AVector4 xVec4;

	xVec4.ZeroW0();
	xVec4.SetX(1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec1000 );

	xVec4.ZeroW0();
	xVec4.SetY(1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0100 );

	xVec4.ZeroW0();
	xVec4.SetZ(1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0010 );

	xVec4.ZeroW0();
	xVec4.SetW(1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0001 );

	xVec4.ZeroW0();
	xVec4.SetX(4.0f);
	xVec4.SetY(5.0f);
	xVec4.SetZ(6.0f);
	xVec4.SetW(7.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec4567 );
}

ASURA_UNITTEST(GetElement, Asura_AVector4)
{
	ASURA_UNITTEST_FLOATS_EQUAL( 1.0f, xVec1234.GetElement(0), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 2.0f, xVec1234.GetElement(1), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 3.0f, xVec1234.GetElement(2), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec1234.GetElement(3), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 4.0f, xVec4567.GetElement(0), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 5.0f, xVec4567.GetElement(1), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 6.0f, xVec4567.GetElement(2), 0.0f );
	ASURA_UNITTEST_FLOATS_EQUAL( 7.0f, xVec4567.GetElement(3), 0.0f );
}

ASURA_UNITTEST(SetElement, Asura_AVector4)
{
	Asura_AVector4 xVec4;

	xVec4.ZeroW0();
	xVec4.SetElement(0, 1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec1000 );

	xVec4.ZeroW0();
	xVec4.SetElement(1, 1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0100 );

	xVec4.ZeroW0();
	xVec4.SetElement(2, 1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0010 );

	xVec4.ZeroW0();
	xVec4.SetElement(3, 1.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec0001 );

	xVec4.ZeroW0();
	xVec4.SetElement(0, 4.0f);
	xVec4.SetElement(1, 5.0f);
	xVec4.SetElement(2, 6.0f);
	xVec4.SetElement(3, 7.0f);
	ASURA_UNITTEST_CHECK( xVec4 == xVec4567 );
}

ASURA_UNITTEST(Select, Asura_AVector4)
{
	// EQ
	Asura_AVector4 xVector;

	xVector.SelectEQ(xVec1234, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567 == xVector );

	xVector.SelectEQ(xVec1234, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 9.0f, 10.f) == xVector );

	xVector.SelectEQ(xVec1234, xVec2222, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 9.0f, 10.f) == xVector );

	xVector.SelectEQ(xVec1234, xVec3333, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 8.0f, 6.0f, 10.f) == xVector );

	xVector.SelectEQ(xVec1234, xVec4444, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 8.0f, 9.0f,  7.f) == xVector );

	// NE
	xVector.SelectNE(xVec1234, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectNE(xVec1234, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 6.0f, 7.0f) == xVector );

	xVector.SelectNE(xVec1234, xVec2222, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 6.0f, 7.0f) == xVector );

	xVector.SelectNE(xVec1234, xVec3333, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 9.0f, 7.0f) == xVector );

	xVector.SelectNE(xVec1234, xVec4444, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 6.0f,10.0f) == xVector );

	// LT
	xVector.SelectLT(xVec1234, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectLT(xVec4567, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectLT(xVec1234, xVec4567, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectLT(xVec0001, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 6.0f, 10.0f) == xVector );

	xVector.SelectLT(xVec0010, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 9.0f,  7.0f) == xVector );

	xVector.SelectLT(xVec0100, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 6.0f,  7.0f) == xVector );

	xVector.SelectLT(xVec1000, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 6.0f,  7.0f) == xVector );

	// LE
	xVector.SelectLE(xVec1234, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectLE(xVec4567, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectLE(xVec1234, xVec4567, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectLE(xVec0002, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 6.0f, 10.0f) == xVector );

	xVector.SelectLE(xVec0020, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 9.0f,  7.0f) == xVector );

	xVector.SelectLE(xVec0200, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 6.0f,  7.0f) == xVector );

	xVector.SelectLE(xVec2000, xVec1111, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 6.0f,  7.0f) == xVector );

	// GT
	xVector.SelectGT(xVec1234, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectGT(xVec1234, xVec4567, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectGT(xVec4567, xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectGT(xVec1111,  xVec0001, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 6.0f, 10.0f) == xVector );

	xVector.SelectGT(xVec1111,  xVec0010, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 9.0f,  7.0f) == xVector );

	xVector.SelectGT(xVec1111,  xVec0100, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 6.0f,  7.0f) == xVector );

	xVector.SelectGT(xVec1111,  xVec1000, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 6.0f,  7.0f) == xVector );

	// GE
	xVector.SelectGE(xVec1234,  xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectGE(xVec1234,  xVec4567, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector.SelectGE(xVec4567,  xVec1234, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector.SelectGE(xVec1111,  xVec0002, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 6.0f, 10.0f) == xVector );

	xVector.SelectGE(xVec1111,  xVec0020, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 5.0f, 9.0f,  7.0f) == xVector );

	xVector.SelectGE(xVec1111,  xVec0200, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 6.0f,  7.0f) == xVector );

	xVector.SelectGE(xVec1111,  xVec2000, xVec4567, xVec78910);
	ASURA_UNITTEST_CHECK( Asura_AVector4(7.0f, 5.0f, 6.0f,  7.0f) == xVector );
}

ASURA_UNITTEST(ZeroW0, Asura_AVector4)
{
	Asura_AVector4 xVector	= xVec0001;
	xVector.ZeroW0();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0);
	xVector = xVec0010;
	xVector.ZeroW0();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0);
	xVector = xVec0100;
	xVector.ZeroW0();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0);
	xVector = xVec1000;
	xVector.ZeroW0();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0);
	xVector = xVec4567;
	xVector.ZeroW0();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W0);
}

ASURA_UNITTEST(ZeroW1, Asura_AVector4)
{
	Asura_AVector4 xVector	= xVec0001;
	xVector.ZeroW1();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W1);
	xVector = xVec0010;
	xVector.ZeroW1();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W1);
	xVector = xVec0100;
	xVector.ZeroW1();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W1);
	xVector = xVec1000;
	xVector.ZeroW1();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W1);
	xVector = xVec4567;
	xVector.ZeroW1();
	ASURA_UNITTEST_CHECK( xVector == Asura_Maths::ZeroAVector4W1);
}

ASURA_UNITTEST(Min, Asura_AVector4)
{
	Asura_AVector4	xVector;

	xVector.Min(xVec1234, xVec4567);
	ASURA_UNITTEST_CHECK(xVec1234 == xVector);
	xVector.Min(xVec0002, xVec1234);
	ASURA_UNITTEST_CHECK(Asura_AVector4(0.0f, 0.0f, 0.0f, 2.0f) == xVector);
}

ASURA_UNITTEST(Max, Asura_AVector4)
{
	Asura_AVector4	xVector;

	xVector.Max(xVec1234, xVec4567);
	ASURA_UNITTEST_CHECK(xVec4567 == xVector);
	xVector.Max(xVec2000, xVec1234);
	ASURA_UNITTEST_CHECK(Asura_AVector4(2.0f, 2.0f, 3.0f, 4.0f) == xVector);
}

ASURA_UNITTEST(Constructors, Asura_AVector4)
{
	// from 4 floats
	Asura_AVector4 xVectorFrom4Floats(1.0f, 2.0f, 3.0f, 4.0f);
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFrom4Floats );

	// from other vector (copy constructor)
	Asura_AVector4 xVectorFromOtherVec(xVec1234);
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFromOtherVec );

	// from vector 3 + w
	Asura_Vector_3 xVec3(1.0f, 2.0f, 3.0f);
	Asura_AVector4 xVectorFromVec3(xVec3, 4.0f);
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFromVec3 );

	// from aligned vector 3 + w
	Asura_AVector3 xAVec3(1.0f, 2.0f, 3.0f);
	Asura_AVector4 xVectorFromAVec3(xAVec3, 4.0f);
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFromAVec3 );
}

ASURA_UNITTEST(Assignment, Asura_AVector4)
{
	// from vector 4
	Asura_AVector4 xVector4(1.0f, 2.0f, 3.0f, 4.0f);
	Asura_AVector4 xVectorFromVec4(0.0f, 0.0f, 0.0f, 0.0f);
	xVectorFromVec4 = xVector4;
	ASURA_UNITTEST_CHECK( xVec1234 == xVectorFromVec4 );
}

ASURA_UNITTEST(Equality, Asura_AVector4)
{
	ASURA_UNITTEST_CHECK( xVec1000 == xVec1000 );
	ASURA_UNITTEST_CHECK( xVec0100 == xVec0100 );
	ASURA_UNITTEST_CHECK( xVec0010 == xVec0010 );
	ASURA_UNITTEST_CHECK( xVec0001 == xVec0001 );
	ASURA_UNITTEST_CHECK( !(xVec0010 == xVec1234) );
	ASURA_UNITTEST_CHECK( xVecMinus1234 == xVecMinus1234 );
	ASURA_UNITTEST_CHECK( !(xVec1234 == xVecMinus1234) );
}


// M A T R I X   4 X 4 ///////////////////////////////////////////////////////
static const Asura_AMatrix4x4 xMat1To16(  1.0f, 2.0f, 3.0f,  4.0f,   5.0f, 6.0f, 7.0f,  8.0f,   9.0f,  10.0f, 11.0f, 12.0f,  13.0f, 14.0f, 15.0f, 16.0f);
static const Asura_AMatrix4x4 xMatMinus1To16(  -1.0f, -2.0f, -3.0f,  -4.0f,   -5.0f, -6.0f, -7.0f,  -8.0f,   -9.0f,  -10.0f, -11.0f, -12.0f,  -13.0f, -14.0f, -15.0f, -16.0f);
static const Asura_AMatrix4x4 xMat1To16T( 1.0f, 5.0f, 9.0f,  13.0f,  2.0f, 6.0f, 10.0f, 14.0f,  3.0f,  7.0f,  11.0f, 15.0f,  4.0f,  8.0f,  12.0f, 16.0f);
static const Asura_AMatrix4x4 xMat4To19(  4.0f, 5.0f, 6.0f,  7.0f,   8.0f, 9.0f, 10.0f, 11.0f,  12.0f, 13.0f, 14.0f, 15.0f,  16.0f, 17.0f, 18.0f, 19.0f);
static const Asura_AMatrix4x4 xMat4To19T( 4.0f, 8.0f, 12.0f, 16.0f,  5.0f, 9.0f, 13.0f, 17.0f,  6.0f,  10.0f, 14.0f, 18.0f,  7.0f,  11.0f, 15.0f, 19.0f);

ASURA_UNITTEST(Constructors, Asura_AMatrix4x4)
{
	// from 16 floats
	ASURA_UNITTEST_CHECK(  1.0f == xMat1To16.GetElement(0,0) );
	ASURA_UNITTEST_CHECK(  2.0f == xMat1To16.GetElement(0,1) );
	ASURA_UNITTEST_CHECK(  3.0f == xMat1To16.GetElement(0,2) );
	ASURA_UNITTEST_CHECK(  4.0f == xMat1To16.GetElement(0,3) );
	ASURA_UNITTEST_CHECK(  5.0f == xMat1To16.GetElement(1,0) );
	ASURA_UNITTEST_CHECK(  6.0f == xMat1To16.GetElement(1,1) );
	ASURA_UNITTEST_CHECK(  7.0f == xMat1To16.GetElement(1,2) );
	ASURA_UNITTEST_CHECK(  8.0f == xMat1To16.GetElement(1,3) );
	ASURA_UNITTEST_CHECK(  9.0f == xMat1To16.GetElement(2,0) );
	ASURA_UNITTEST_CHECK( 10.0f == xMat1To16.GetElement(2,1) );
	ASURA_UNITTEST_CHECK( 11.0f == xMat1To16.GetElement(2,2) );
	ASURA_UNITTEST_CHECK( 12.0f == xMat1To16.GetElement(2,3) );
	ASURA_UNITTEST_CHECK( 13.0f == xMat1To16.GetElement(3,0) );
	ASURA_UNITTEST_CHECK( 14.0f == xMat1To16.GetElement(3,1) );
	ASURA_UNITTEST_CHECK( 15.0f == xMat1To16.GetElement(3,2) );
	ASURA_UNITTEST_CHECK( 16.0f == xMat1To16.GetElement(3,3) );

	// from 4 columns
	Asura_AMatrix4x4 xMatrixFromColumns;
	xMatrixFromColumns.SetColumns( xVec1111, xVec1234, xVec4567, xVec78910 );

	Asura_AVector4 xVector = xMatrixFromColumns.GetColumn(0);
	ASURA_UNITTEST_CHECK( xVec1111  == xVector );

	xVector = xMatrixFromColumns.GetColumn0();
	ASURA_UNITTEST_CHECK( xVec1111  == xVector );

	xVector = xMatrixFromColumns.GetColumn(1);
	ASURA_UNITTEST_CHECK( xVec1234  == xVector );

	xVector = xMatrixFromColumns.GetColumn1();
	ASURA_UNITTEST_CHECK( xVec1234  == xVector );

	xVector = xMatrixFromColumns.GetColumn(2);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector = xMatrixFromColumns.GetColumn2();
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector = xMatrixFromColumns.GetColumn(3);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector = xMatrixFromColumns.GetColumn3();
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	// from 4 rows
	Asura_AMatrix4x4 xMatrixFromRows;
	xMatrixFromRows.SetRows( xVec1111, xVec1234, xVec4567, xVec78910 );

	xVector = xMatrixFromRows.GetRow(0);
	ASURA_UNITTEST_CHECK( xVec1111  == xVector );

	xVector = xMatrixFromRows.GetRow0();
	ASURA_UNITTEST_CHECK( xVec1111  == xVector );

	xVector = xMatrixFromRows.GetRow(1);
	ASURA_UNITTEST_CHECK( xVec1234  == xVector );

	xVector = xMatrixFromRows.GetRow1();
	ASURA_UNITTEST_CHECK( xVec1234  == xVector );

	xVector = xMatrixFromRows.GetRow(2);
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector = xMatrixFromRows.GetRow2();
	ASURA_UNITTEST_CHECK( xVec4567  == xVector );

	xVector = xMatrixFromRows.GetRow(3);
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	xVector = xMatrixFromRows.GetRow3();
	ASURA_UNITTEST_CHECK( xVec78910 == xVector );

	// from other matrix
	Asura_AMatrix4x4 xMatrixFromOtherMatrix( xMat1To16 );
	ASURA_UNITTEST_CHECK( xMat1To16 == xMatrixFromOtherMatrix );

    // From quat + vector.
    {
        float fAngle = Asura_Maths::DegToRad(45.0f);

        Asura_Quat xQuat;
        xQuat.FromRotation( fAngle, Asura_Vector_3(1.0f, 0.0f, 0.0f) );

        Asura_AMatrix4x4 xMat( xQuat, Asura_Vector_3(1.0f, 2.0f, 3.0f) );

        float fCos = Asura_Maths::Cosine( fAngle );
        float fSin = Asura_Maths::Sine( fAngle );
        ASURA_UNITTEST_CHECK( xMat.ApproximatelyEquals(Asura_AMatrix4x4(1.0f, 0.0f,  0.0f, 1.0f,
                                                                        0.0f, fCos, -fSin, 2.0f,
                                                                        0.0f, fSin,  fCos, 3.0f,
                                                                        0.0f, 0.0f,  0.0f, 1.0f)) );
    }

    // From quat + vector and also from Asura_Matrix_3x3.
    {
        Asura_Quat xQuat;
        xQuat.FromRotation( Asura_Maths::DegToRad(15.0f), Asura_Vector_3(0.57735027f, 0.57735027f, 0.57735027f) );

        Asura_Matrix_3x3 x3x3Mat;
        xQuat.ToMatrix( x3x3Mat );

        Asura_AMatrix4x4 xMat1( xQuat, Asura_Vector_3(5.0f, 6.0f, 7.0f) );
        Asura_AMatrix4x4 xMat2( x3x3Mat, Asura_Vector_3(5.0f, 6.0f, 7.0f) );
        ASURA_UNITTEST_CHECK( xMat1.ApproximatelyEquals(xMat2) );
    }
}

ASURA_UNITTEST(UnaryMinus, Asura_AMatrix4x4)
{
	ASURA_UNITTEST_CHECK( -xMat1To16 == xMatMinus1To16 );
}

ASURA_UNITTEST(GetElement, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix( 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f );

	ASURA_UNITTEST_CHECK( xMatrix.GetElement(0, 0) == 1.0f );
	ASURA_UNITTEST_CHECK( xMatrix.GetElement(2, 3) == 12.0f );
	ASURA_UNITTEST_CHECK( xMatrix.GetElement(3, 3) == 16.0f );
}


ASURA_UNITTEST(SetElement, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix( 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f );

    xMatrix.SetElement( 0, 0, -1.0f );
	ASURA_UNITTEST_CHECK( xMatrix == Asura_AMatrix4x4(-1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f) );

    xMatrix.SetElement( 2, 3, -1.0f );
	ASURA_UNITTEST_CHECK( xMatrix == Asura_AMatrix4x4(-1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, -1.0f, 13.0f, 14.0f, 15.0f, 16.0f) );

    xMatrix.SetElement( 3, 3, -1.0f );
	ASURA_UNITTEST_CHECK( xMatrix == Asura_AMatrix4x4(-1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, -1.0f, 13.0f, 14.0f, 15.0f, -1.0f) );
}


ASURA_UNITTEST(Assignment, Asura_AMatrix4x4)
{
	const Asura_AMatrix4x4 xMatrix1to16(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
	Asura_AMatrix4x4 xMatrix = xMatrix1to16;
	ASURA_UNITTEST_CHECK( xMatrix1to16 == xMatrix );
}

ASURA_UNITTEST(GetColumns, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
	Asura_AVector4 xVector = xMatrix.GetColumn(0);
	ASURA_UNITTEST_CHECK( Asura_AVector4(1.0f, 5.0f,  9.0f, 13.0f) == xVector );

	xVector = xMatrix.GetColumn0();
	ASURA_UNITTEST_CHECK( Asura_AVector4(1.0f, 5.0f,  9.0f, 13.0f) == xVector );

	xVector = xMatrix.GetColumn(1);
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 6.0f, 10.0f, 14.0f) == xVector );

	xVector = xMatrix.GetColumn1();
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 6.0f, 10.0f, 14.0f) == xVector );

	xVector = xMatrix.GetColumn(2);
	ASURA_UNITTEST_CHECK( Asura_AVector4(3.0f, 7.0f, 11.0f, 15.0f) == xVector );

	xVector = xMatrix.GetColumn2();
	ASURA_UNITTEST_CHECK( Asura_AVector4(3.0f, 7.0f, 11.0f, 15.0f) == xVector );

	xVector = xMatrix.GetColumn(3);
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 12.0f, 16.0f) == xVector );

	xVector = xMatrix.GetColumn3();
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 8.0f, 12.0f, 16.0f) == xVector );
}


ASURA_UNITTEST(Transpose, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
	Asura_AMatrix4x4 xMatT;
	xMatrix.Transpose( xMatT );
	ASURA_UNITTEST_CHECK( Asura_AMatrix4x4(1.0f, 5.0f, 9.0f, 13.0f, 2.0f, 6.0f, 10.0f, 14.0f, 3.0f, 7.0f, 11.0f, 15.0f, 4.0f, 8.0f, 12.0f, 16.0f) == xMatT );
	xMatrix.Transpose();
	ASURA_UNITTEST_CHECK( Asura_AMatrix4x4(1.0f, 5.0f, 9.0f, 13.0f, 2.0f, 6.0f, 10.0f, 14.0f, 3.0f, 7.0f, 11.0f, 15.0f, 4.0f, 8.0f, 12.0f, 16.0f) == xMatrix );
}

ASURA_UNITTEST(ApplyMatrixToVector, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
	Asura_AVector4 xVec = xVec1111 * xMatrix;
	ASURA_UNITTEST_CHECK( xVec.ApproximatelyEquals(Asura_AVector4(10.0f, 26.0f, 42.0f, 58.0f)) );
}

ASURA_UNITTEST(ApplyMatrixToVectorArray, Asura_AMatrix4x4)
{
	Asura_AVector4 xVecIn[4];
	Asura_AVector4 xVecOut[4];
	Asura_AMatrix4x4 xMatrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);

	xVecIn[0] = xVec1111;
	xVecIn[1] = xVec2222;
	xVecIn[2] = xVec3333;
	xVecIn[3] = xVec4444;

	xMatrix.ApplyToArray(xVecIn, 4, xVecOut);
	
	for(int i = 1; i <= 4; i++)
	{
		ASURA_UNITTEST_CHECK( xVecOut[i-1].ApproximatelyEquals(Asura_AVector4(i*10.0f, i*26.0f, i*42.0f, i*58.0f)) );
	}
}

ASURA_UNITTEST(Identity, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
	Asura_AMatrix4x4 xMatrix2;
	xMatrix2.Identity();
	ASURA_UNITTEST_CHECK( Asura_Maths::IdentityAMatrix4x4 == xMatrix );
	ASURA_UNITTEST_CHECK( Asura_Maths::IdentityAMatrix4x4 == xMatrix2 );
}

ASURA_UNITTEST(MatrixMultiply, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix1(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix2(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);

    for( u_int u = 0; u < 6; ++u )
    {
	    Asura_AMatrix4x4 xMatrix3;
        switch( u )
        {
            case 0: xMatrix3 = xMatrix1 * xMatrix2; break;
            case 1: xMatrix3 = xMatrix2 * xMatrix1; break;
            case 2: xMatrix2.Apply( xMatrix1, xMatrix3 ); break;
            case 3: xMatrix1.Apply( xMatrix2, xMatrix3 ); break;
            case 4: xMatrix3 = xMatrix2; xMatrix3.Apply( xMatrix1, xMatrix3 ); break;
            case 5: xMatrix3 = xMatrix2; xMatrix1.Apply( xMatrix3, xMatrix3 ); break;
			default: xMatrix3 = Asura_Maths::IdentityAMatrix4x4; break;
        }

        // Multiplication result generated by http://wims.unice.fr/wims/wims.cgi?module=tool%2Flinear%2Fmatmult.en
        Asura_AVector4 xVector = xMatrix3.GetColumn0();
        ASURA_UNITTEST_CHECK( Asura_AVector4( 90.0f, 202.0f, 314.0f, 426.0f).ApproximatelyEquals( xVector ) );

        xVector = xMatrix3.GetColumn1();
        ASURA_UNITTEST_CHECK( Asura_AVector4(100.0f, 228.0f, 356.0f, 484.0f).ApproximatelyEquals( xVector ) );

        xVector = xMatrix3.GetColumn2();
        ASURA_UNITTEST_CHECK( Asura_AVector4(110.0f, 254.0f, 398.0f, 542.0f).ApproximatelyEquals( xVector ) );

       xVector =  xMatrix3.GetColumn3();
        ASURA_UNITTEST_CHECK( Asura_AVector4(120.0f, 280.0f, 440.0f, 600.0f).ApproximatelyEquals( xVector ) );
    }
}

ASURA_UNITTEST(ApplyMatrixToMatrixArray, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatIn[4];
	Asura_AMatrix4x4 xMatOut[4];
	Asura_AMatrix4x4 xMatrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);

	xMatIn[0] = Asura_AMatrix4x4(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
	xMatIn[1] = Asura_AMatrix4x4(2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f);
	xMatIn[2] = Asura_AMatrix4x4(3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f);
	xMatIn[3] = Asura_AMatrix4x4(4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f);

	xMatrix.ApplyToArray(xMatIn, 4, xMatOut);
	
	for(int i = 1; i <= 4; i++)
	{
		for(int j = 0; j < 4; j++)
		{
			Asura_AVector4 xVector = xMatOut[i-1].GetColumn(j);
			ASURA_UNITTEST_CHECK(xVector.ApproximatelyEquals(Asura_AVector4(i*10.0f, i*26.0f, i*42.0f, i*58.0f)));
		}
	}
}

ASURA_UNITTEST(Scaling, Asura_AMatrix4x4)
{
	/* Simple scaling */
	Asura_AMatrix4x4 xMatrix = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f) * 2.0f;
	Asura_AVector4 xVector = xMatrix.GetColumn0();
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 10.0f, 18.0f, 26.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix.GetColumn1();
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 12.0f, 20.0f, 28.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix.GetColumn2();
	ASURA_UNITTEST_CHECK( Asura_AVector4(6.0f, 14.0f, 22.0f, 30.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix.GetColumn3();
	ASURA_UNITTEST_CHECK( Asura_AVector4(8.0f, 16.0f, 24.0f, 32.0f).ApproximatelyEquals( xVector ) );

	/* Assignment */
	Asura_AMatrix4x4 xMatrix2(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	xMatrix2 *= 2.0f;

	xVector = xMatrix2.GetColumn0();
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 10.0f, 18.0f, 26.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix2.GetColumn1();
	ASURA_UNITTEST_CHECK( Asura_AVector4(4.0f, 12.0f, 20.0f, 28.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix2.GetColumn2();
	ASURA_UNITTEST_CHECK( Asura_AVector4(6.0f, 14.0f, 22.0f, 30.0f).ApproximatelyEquals( xVector ) );

	xVector = xMatrix2.GetColumn3();
	ASURA_UNITTEST_CHECK( Asura_AVector4(8.0f, 16.0f, 24.0f, 32.0f).ApproximatelyEquals( xVector ) );
}

ASURA_UNITTEST(Zero, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	xMatrix.Zero();
	for (u_int u = 0; u < 16; ++u)
	{
		ASURA_UNITTEST_CHECK_EQUAL( 0.0f, xMatrix.GetElement(u/4,u%4) );
	}
}

ASURA_UNITTEST(Equality, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix0  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix1  = Asura_AMatrix4x4(0.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix2  = Asura_AMatrix4x4(1.0f, 0.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix3  = Asura_AMatrix4x4(1.0f, 2.0f, 0.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix4  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 0.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix5  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 0.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix6  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 0.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix7  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 0.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix8  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 0.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix9  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 0.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix10 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f,  0.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix11 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f,  0.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix12 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f,  0.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix13 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f,  0.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix14 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f,  0.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix15 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f,  0.f, 16.f);
	Asura_AMatrix4x4 xMatrix16 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f,  0.f);
	Asura_AMatrix4x4 xMatrix17 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	ASURA_UNITTEST_CHECK( xMatrix0 == xMatrix0 );
	ASURA_UNITTEST_CHECK( xMatrix0 == xMatrix17 );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix1) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix2) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix3) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix4) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix5) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix6) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix7) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix8) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix9) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix10) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix11) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix12) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix13) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix14) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix15) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 == xMatrix16) );
}

ASURA_UNITTEST(Inquality, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix0  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix1  = Asura_AMatrix4x4(0.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix2  = Asura_AMatrix4x4(1.0f, 0.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix3  = Asura_AMatrix4x4(1.0f, 2.0f, 0.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix4  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 0.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix5  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 0.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix6  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 0.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix7  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 0.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix8  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 0.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix9  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 0.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix10 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f,  0.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix11 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f,  0.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix12 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f,  0.f, 13.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix13 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f,  0.f, 14.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix14 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f,  0.f, 15.f, 16.f);
	Asura_AMatrix4x4 xMatrix15 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f,  0.f, 16.f);
	Asura_AMatrix4x4 xMatrix16 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f,  0.f);
	Asura_AMatrix4x4 xMatrix17 = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	ASURA_UNITTEST_CHECK( !(xMatrix0 != xMatrix0) );
	ASURA_UNITTEST_CHECK( !(xMatrix0 != xMatrix17) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix1) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix2) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix3) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix4) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix5) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix6) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix7) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix8) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix9) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix10) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix11) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix12) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix13) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix14) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix15) );
	ASURA_UNITTEST_CHECK( (xMatrix0 != xMatrix16) );
}

ASURA_UNITTEST(Determinant, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix1  = Asura_AMatrix4x4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f);
	ASURA_UNITTEST_FLOATS_EQUAL(0.f, xMatrix1.Determinant(), 0.0001f);

	Asura_AMatrix4x4 xMatrix2  = Asura_AMatrix4x4(1.0f, 0.0f, 0.0f, 4.0f, 0.0f, 1.0f, 0.0f, 3.0f, 0.0f, 0.f, 1.f, 2.f, 0.f, 0.f, 0.f, 1.f);
	ASURA_UNITTEST_FLOATS_EQUAL(1.f, xMatrix2.Determinant(), 0.0001f);
}

ASURA_UNITTEST(Inverse, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xMatrix2  = Asura_AMatrix4x4(1.0f, 0.0f, 0.0f, 4.0f, 0.0f, 1.0f, 0.0f, 3.0f, 0.0f, 0.f, 1.f, 2.f, 0.f, 0.f, 0.f, 1.f);

	Asura_AMatrix4x4 xInverse;
	xMatrix2.Invert( xInverse );

	Asura_AMatrix4x4 xExpectedInverse = Asura_AMatrix4x4(1.0f, 0.0f, 0.0f, -4.0f, 0.0f, 1.0f, 0.0f, -3.0f, 0.0f, 0.f, 1.f, -2.f, 0.f, 0.f, 0.f, 1.f);
	ASURA_UNITTEST_CHECK( xInverse == xExpectedInverse );

	xMatrix2 = Asura_AMatrix4x4(7.f, 0.f, 3.f, 4.f, 
								0.f, 1.f, 0.f, 3.f,
								4.f, 2.f,-2.f, 2.f,
								0.f, 5.f, 0.f, 1.f );
	xMatrix2.Invert( xInverse );
	xExpectedInverse = Asura_AMatrix4x4(0.077f, -0.176f, 0.115f, -0.011f,
										0.000f, -0.071f, 0.000f,  0.214f,
                                        0.154f, -0.066f,-0.269f,  0.121f,
										0.000f,  0.357f, 0.000f, -0.071f);
	ASURA_UNITTEST_CHECK( xInverse.ApproximatelyEquals(xExpectedInverse, 0.001f));

	ASURA_UNITTEST_CHECK( (xInverse * xMatrix2).ApproximatelyEquals(Asura_Maths::IdentityAMatrix4x4) );
}


ASURA_UNITTEST( InvertOrthogonal, Asura_AMatrix4x4 )
{
    float fAngle = Asura_Maths::DegToRad( 45.0f );
    float fCos = Asura_Maths::Cosine( fAngle );
    float fSin = Asura_Maths::Sine( fAngle );

    // Initial test with a rotation about x.
    Asura_AMatrix4x4 xMat( 1.0f,  0.0f, 0.0f, 1.0f,
                           0.0f,  fCos, fSin, 2.0f,
                           0.0f, -fSin, fCos, 3.0f,
                           0.0f,  0.0f, 0.0f, 1.0f );

    Asura_AVector4 xInVec( 0.1f, 0.2f, 0.3f, 1.0f );

    Asura_AMatrix4x4 xInverseMat;
    xMat.InvertOrthogonal( xInverseMat );

    Asura_AVector4 xOutVec = (xInVec * xMat) * xInverseMat;
    ASURA_UNITTEST_CHECK( xOutVec.ApproximatelyEquals(xInVec) );

    Asura_AMatrix4x4 xExpectedInverseMat( 1.0f, 0.0f,  0.0f, -1.0f,
                                          0.0f, fCos, -fSin, -(fCos * 2.0f - fSin * 3.0f),
                                          0.0f, fSin,  fCos, -(fSin * 2.0f + fCos * 3.0f),
                                          0.0f, 0.0f,  0.0f,  1.0f );
    ASURA_UNITTEST_CHECK( xInverseMat.ApproximatelyEquals(xExpectedInverseMat) );

    Asura_AMatrix4x4 xExpectedIdentityMat = xMat * xInverseMat;
    ASURA_UNITTEST_CHECK( xExpectedIdentityMat.ApproximatelyEquals(Asura_Maths::IdentityAMatrix4x4) );

    // Rotation about z.
    Asura_AMatrix4x4 xMat2(  fCos, fSin, 0.0f, 4.0f,
                            -fSin, fCos, 0.0f, 5.0f,
                             0.0f, 0.0f, 1.0f, 6.0f,
                             0.0f, 0.0f, 0.0f, 1.0f );

    // Test in-place version instead.
    Asura_AMatrix4x4 xInverseMat2 = xMat2;
    xInverseMat2.InvertOrthogonal();

    // Now test some slightly more complex expressions.
    xOutVec = (xInVec * (xMat * xMat2)) * (xInverseMat2 * xInverseMat);
    ASURA_UNITTEST_CHECK( xOutVec.ApproximatelyEquals(xInVec) );

    Asura_AMatrix4x4 xExpectedInverseMat2( fCos, -fSin, 0.0f, -(fCos * 4.0f - fSin * 5.0f),
                                           fSin,  fCos, 0.0f, -(fSin * 4.0f + fCos * 5.0f),
                                           0.0f,  0.0f, 1.0f, -6.0f,
                                           0.0f,  0.0f, 0.0f,  1.0f );
    ASURA_UNITTEST_CHECK( (xInverseMat * xInverseMat2).ApproximatelyEquals(xExpectedInverseMat * xExpectedInverseMat2) );

    xExpectedIdentityMat = (xMat * xMat2) * (xInverseMat2 * xInverseMat);
    ASURA_UNITTEST_CHECK( xExpectedIdentityMat.ApproximatelyEquals(Asura_Maths::IdentityAMatrix4x4) );
}


ASURA_UNITTEST(IdentityTransform, Asura_AMatrix4x4)
{
	Asura_AVector4 xVec;
	
	xVec = xVec1234 * Asura_Maths::IdentityAMatrix4x4;
	ASURA_UNITTEST_CHECK( xVec == xVec1234 );
}

ASURA_UNITTEST(Translation, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xTransMat;
    Asura_AVector3 xVec3;
	Asura_AVector4 xVec4;

	xTransMat.Identity();
	xTransMat.SetTranslation( Asura_AVector3(1.0f, 1.0f, 1.0f) );
	xVec4 = xVec1111 * xTransMat;
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 2.0f, 2.0f, 1.0f) == xVec4 );

    xVec3 = xTransMat.GetATranslation();
    ASURA_UNITTEST_CHECK( xVec3 == Asura_AVector3(1.0f, 1.0f, 1.0f) );

	xTransMat.Identity();
	xTransMat.SetTranslation( Asura_AVector4(1.0f, 1.0f, 1.0f, 1.0f) );
	xVec4 = xVec1111 * xTransMat;
	ASURA_UNITTEST_CHECK( Asura_AVector4(2.0f, 2.0f, 2.0f, 1.0f) == xVec4 );

    xVec4 = xTransMat.GetA4Translation();
    ASURA_UNITTEST_CHECK( xVec4 == Asura_AVector4(1.0f, 1.0f, 1.0f, 1.0f) );
}

ASURA_UNITTEST(Rotation, Asura_AMatrix4x4)
{
	Asura_Matrix_3x3 xRotMat3x3;
	xRotMat3x3.Identity();
	xRotMat3x3.e11 = xRotMat3x3.e22 = -1.f; // rotate 180 degrees

	Asura_AMatrix4x4 xRotMat;
	xRotMat.Identity();
	xRotMat.FromMatrix( xRotMat3x3 );
	ASURA_UNITTEST_CHECK( Asura_AVector4(0, -1, 0, 1).ApproximatelyEquals(Asura_AVector4(0, 1, 0, 1) * xRotMat));
}

ASURA_UNITTEST(MultiplySequence, Asura_AMatrix4x4)
{
	Asura_AMatrix4x4 xTransMat;
	xTransMat.Identity();
	xTransMat.SetTranslation( Asura_AVector3(0, 1, 0) );
	Asura_AMatrix4x4 xRotMat;
	xRotMat.Identity();
	xRotMat.FromMatrix( Asura_Matrix_3x3(-1, 0, 0, 0, -1, 0, 0, 0, 1));
	
	Asura_AVector4 xVec = Asura_Maths::ZeroAVector4W1;
	Asura_AMatrix4x4 xMat = xTransMat * xRotMat;
	xVec = xVec * xMat;
	ASURA_UNITTEST_CHECK( Asura_AVector4(0, -1, 0, 1).ApproximatelyEquals(xVec, 1.0e-3f));
}

ASURA_UNITTEST(FromAndToMatrix, Asura_AMatrix4x4)
{
    Asura_AMatrix4x4 xAMat4( 1.0f,  2.0f,  3.0f,  4.0f,
                             5.0f,  6.0f,  7.0f,  8.0f,
                             9.0f, 10.0f, 11.0f, 12.0f,
                            13.0f, 14.0f, 15.0f, 16.0f );

    Asura_Matrix_3x3 xMat3;
    xAMat4.ToMatrix( xMat3 );
    ASURA_UNITTEST_CHECK( xMat3 == Asura_Matrix_3x3(1.0f,  2.0f,  3.0f,
                                                    5.0f,  6.0f,  7.0f,
                                                    9.0f, 10.0f, 11.0f) );

    xAMat4.FromMatrix( xMat3 );
    ASURA_UNITTEST_CHECK( xAMat4 == Asura_AMatrix4x4(1.0f,  2.0f,  3.0f, 0.0f,
                                                     5.0f,  6.0f,  7.0f, 0.0f,                
                                                     9.0f, 10.0f, 11.0f, 0.0f,
                                                     0.0f,  0.0f,  0.0f, 1.0f) );
}

ASURA_UNITTEST(LoadAndStore, Asura_AMatrix4x4)
{
	float*				pfFloats	= reinterpret_cast<float*>(Asura_AllocateAlign(19*sizeof(float), ASURA_ALIGN_16_BYTE));

	Asura_AMatrix4x4	xMatrixFromFloats;

	// fill out array
	{
		float afFloats[19] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f};
		memcpy( pfFloats, afFloats, 19*sizeof(float) );
	}
	xMatrixFromFloats.Zero();
	xMatrixFromFloats.LoadRowsAligned(pfFloats);
	ASURA_UNITTEST_CHECK( xMat1To16 == xMatrixFromFloats );

	xMatrixFromFloats.Zero();
	xMatrixFromFloats.LoadRowsUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( xMat4To19 == xMatrixFromFloats );

	// to float array
	memset(pfFloats, 0, 19*sizeof(float));
	xMat4To19.StoreRowsAligned(pfFloats);
	xMat1To16.StoreRowsUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( pfFloats[0]  == 4.0f );
	ASURA_UNITTEST_CHECK( pfFloats[1]  == 5.0f );
	ASURA_UNITTEST_CHECK( pfFloats[2]  == 6.0f );
	ASURA_UNITTEST_CHECK( pfFloats[3]  == 1.0f );
	ASURA_UNITTEST_CHECK( pfFloats[4]  == 2.0f );
	ASURA_UNITTEST_CHECK( pfFloats[5]  == 3.0f );
	ASURA_UNITTEST_CHECK( pfFloats[6]  == 4.0f );
	ASURA_UNITTEST_CHECK( pfFloats[7]  == 5.0f );
	ASURA_UNITTEST_CHECK( pfFloats[8]  == 6.0f );
	ASURA_UNITTEST_CHECK( pfFloats[9]  == 7.0f );
	ASURA_UNITTEST_CHECK( pfFloats[10] == 8.0f );
	ASURA_UNITTEST_CHECK( pfFloats[11] == 9.0f );
	ASURA_UNITTEST_CHECK( pfFloats[12] == 10.0f );
	ASURA_UNITTEST_CHECK( pfFloats[13] == 11.0f );
	ASURA_UNITTEST_CHECK( pfFloats[14] == 12.0f );
	ASURA_UNITTEST_CHECK( pfFloats[15] == 13.0f );

	// fill out array
	{
		float afFloats[19] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f};
		memcpy( pfFloats, afFloats, 19*sizeof(float) );
	}
	xMatrixFromFloats.Zero();
	xMatrixFromFloats.LoadColsAligned(pfFloats);
	ASURA_UNITTEST_CHECK( xMat1To16T == xMatrixFromFloats );

	xMatrixFromFloats.Zero();
	xMatrixFromFloats.LoadColsUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( xMat4To19T == xMatrixFromFloats );

	// to float array
	memset(pfFloats, 0, 19*sizeof(float));
	xMat4To19T.StoreColsAligned(pfFloats);
	xMat1To16T.StoreColsUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK( pfFloats[0]  == 4.0f );
	ASURA_UNITTEST_CHECK( pfFloats[1]  == 5.0f );
	ASURA_UNITTEST_CHECK( pfFloats[2]  == 6.0f );
	ASURA_UNITTEST_CHECK( pfFloats[3]  == 1.0f );
	ASURA_UNITTEST_CHECK( pfFloats[4]  == 2.0f );
	ASURA_UNITTEST_CHECK( pfFloats[5]  == 3.0f );
	ASURA_UNITTEST_CHECK( pfFloats[6]  == 4.0f );
	ASURA_UNITTEST_CHECK( pfFloats[7]  == 5.0f );
	ASURA_UNITTEST_CHECK( pfFloats[8]  == 6.0f );
	ASURA_UNITTEST_CHECK( pfFloats[9]  == 7.0f );
	ASURA_UNITTEST_CHECK( pfFloats[10] == 8.0f );
	ASURA_UNITTEST_CHECK( pfFloats[11] == 9.0f );
	ASURA_UNITTEST_CHECK( pfFloats[12] == 10.0f );
	ASURA_UNITTEST_CHECK( pfFloats[13] == 11.0f );
	ASURA_UNITTEST_CHECK( pfFloats[14] == 12.0f );
	ASURA_UNITTEST_CHECK( pfFloats[15] == 13.0f );

	// Row/column comparisons...
	xMat1To16.StoreRowsAligned(pfFloats);
	xMatrixFromFloats.LoadColsAligned(pfFloats);
	ASURA_UNITTEST_CHECK(xMatrixFromFloats == xMat1To16T);

	xMat4To19.StoreRowsUnaligned(&pfFloats[3]);
	xMatrixFromFloats.LoadColsUnaligned(&pfFloats[3]);
	ASURA_UNITTEST_CHECK(xMatrixFromFloats == xMat4To19T);

	// Free-up the data allocated...
	Asura_DeallocateAlign(pfFloats);
}

#endif // #ifdef ASURA_SUPPORT_UNITTEST

// E N D   O F   F I L E /////////////////////////////////////////////////////
