/*
   Test-ZTransform.cpp
Author: Charles Lena <cmlena@762studios.com>
Created: 3/29/2012

Purpose: 

Tests to ensure that the math transform routines function accurately.
*/

#include "ZUnitTest.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <climits>
#include <cfloat>
#include <math.h>
#include <SST/SST_Transform.h>
#include <SST/SST_Vec3.h>
#include <SST/SST_Vec4.h>


const double dPI = 3.1415926535897932384626433832795028841971693993751058209;
const float  fPI = 3.1415926535897932384626433832795028841971693993751058209f;

inline bool fpcomp(float typed_1, float typed_2, float tol = FLT_EPSILON)
{
		return (abs(typed_1 - typed_2) <= tol);
}
inline bool dpcomp(double typed_1, double typed_2, double tol = DBL_EPSILON)
{
		return (abs(typed_1 - typed_2) <= tol);
}

static const char* testSST_Mat33f_IdentityCreate();
static const char* testSST_Mat33f_Add();
static const char* testSST_Mat33f_Sub();
static const char* testSST_Mat33f_ElementMult();

//List of unit tests
ZUnitTest SST_TransformUnitTests[] =
{
{ "testSST_Mat33f_IdentityCreate" , testSST_Mat33f_IdentityCreate },
{ "testSST_Mat44f_IdentityCreate" , testSST_Mat44f_IdentityCreate },
{ "testSST_Mat33d_IdentityCreate" , testSST_Mat33d_IdentityCreate },
{ "testSST_Mat44d_IdentityCreate" , testSST_Mat44d_IdentityCreate },
{ "testSST_Mat33f_TranslationCreate" , testSST_Mat33f_TranslationCreate },
{ "testSST_Mat44f_TranslationCreate" , testSST_Mat44f_TranslationCreate },
{ "testSST_Mat44f_EulerXCreate" , testSST_Mat44f_EulerXCreate },
{ "testSST_Mat44f_EulerYCreate" , testSST_Mat44f_EulerYCreate },
{ "testSST_Mat44f_EulerZCreate" , testSST_Mat44f_EulerZCreate },
{ "testSST_Mat44f_EulerXCreateC" , testSST_Mat44f_EulerXCreateC },
{ "testSST_Mat44f_EulerYCreateC" , testSST_Mat44f_EulerYCreateC },
{ "testSST_Mat44f_EulerZCreateC" , testSST_Mat44f_EulerZCreateC },
{ "testSST_Mat44f_ShearCreate" , testSST_Mat44f_ShearCreate },
{ "testSST_Mat44f_FreeTransformCreate" , testSST_Mat44f_FreeTransformCreate },
{ "testSST_Mat44f_QuaternionCreate" , testSST_Mat44f_QuaternionCreate },
{ "testSST_Mat44f_ScaleCreate" , testSST_Mat44f_ScaleCreate },
{ "testSST_Mat44_LookAt" , testSST_Mat44_LookAt },
{ "testSST_Mat33_ExtractFromMat44" , testSST_Mat33_ExtractFromMat44 },
{ "testSST_Mat44_PerspectiveProjectionCreate" , testSST_Mat44_PerspectiveProjectionCreate },
{ "testSST_Mat44_OrthogonalProjectionCreate" , testSST_Mat44_OrthogonalProjectionCreate }
};

DECLARE_ZTESTBLOCK(SST_Transform);

// =======================================
#define A9f(i,j) A9f[i*3+j]
#define A16f(i,j) A16f[i*4+j]
#define A9d(i,j) A9d[i*3+j]
#define A16d(i,j) A16d[i*4+j]
static const char* testSST_Mat33f_IdentityCreate()
{	
		float A9f[9];
		SST_Mat33f_IdentityCreate(A9f);
		for(int i=0; i<3; i++)
				TASSERT((A9f(i,i) != 1.f),"SST_Mat33f_IdentityCreate failed!");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat33d_IdentityCreate()
{
		double A9d[9];
		SST_Mat33d_IdentityCreate(A9d);
		for(int i=0; i<3; i++)
				TASSERT((A9d(i,i) != 1.0),"SST_Mat33d_IdentityCreate failed!");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_IdentityCreate()
{
		float A16f[16];
		SST_Mat44f_IdentityCreate(A16f);
		for(int i=0; i<4; i++)
				TASSERT((A16f(i,i) != 1.f),"SST_Mat44f_IdentityCreate failed!");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44d_IdentityCreate()
{
		double A16d[16];
		SST_Mat44d_IdentityCreate(A16d);
		for(int i=0; i<4; i++)
				TASSERT((A16d(i,i) != 1.0),"SST_Mat44d_IdentityCreate failed!");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat33f_TranslationCreate()
{
		float A9f[9];
		float txy[] = {1.0,2.0};

		SST_Mat33f_TranslationCreate(txy,A9f);
		for(int i = 0; i<2; i++)
				TASSERT(A9f(i,i) == 1.f,"TranslationCreate: Diagonals incorrect");
		for(int i = 0; i<2; i++)
				TASSERT(A9f(i,2) == txy[i],"TranslationCreate: Translation Column not correctly set!");
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_TranslationCreate(){
		float A16f[16];
		float txyz[] = {1.0,2.0,3.0};

		SST_Mat44f_TranslationCreate(txyz,A16f);
		for(int i = 0; i<3; i++)
				TASSERT(A16f(i,i) == 1.f,"TranslationCreate: Diagonals incorrect");
		for(int i = 0; i<3; i++)
				TASSERT(A16f(i,3) == txyz[i],"TranslationCreate: Translation Column not correctly set!");
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerXCreate(){

		float angle = fPI / 2.f; // 90 degrees
		float* A16f = new float[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};

		// Make sure its actually setting entries to zero
		for(int i=0; i < 16; i++) A16f[i] = 1.0*rand();

		// Call
		SST_Mat44f_EulerXCreate(angle,A16f);
		// Check Actual Mat
		TASSERT(A16f[0]  == 1.f,"Entry 1 incorrect in EulerX Mat");
		TASSERT(A16f[1]  == 0.f,"Entry 2 incorrect in EulerX Mat");
		TASSERT(A16f[2]  == 0.f,"Entry 3 incorrect in EulerX Mat");
		TASSERT(A16f[3]  == 0.f,"Entry 4 incorrect in EulerX Mat");
		TASSERT(A16f[4]  == 0.f,"Entry 5 incorrect in EulerX Mat");
		TASSERT(A16f[5]  == cosf(angle),"Entry 6 incorrect in EulerX Mat"); 
		TASSERT(A16f[6]  == -sinf(angle),"Entry 7 incorrect in EulerX Mat");
		TASSERT(A16f[7]  == 0.f,"Entry 8 incorrect in EulerX Mat");
		TASSERT(A16f[8]  == 0.f,"Entry 9 incorrect in EulerX Mat");
		TASSERT(A16f[9]  == sinf(angle),"Entry 10 incorrect in EulerX Mat");
		TASSERT(A16f[10] == cosf(angle),"Entry 11 incorrect in EulerX Mat");
		TASSERT(A16f[11] == 0.f,"Entry 12 incorrect in EulerX Mat");
		TASSERT(A16f[12] == 0.f,"Entry 13 incorrect in EulerX Mat");
		TASSERT(A16f[13] == 0.f,"Entry 14 incorrect in EulerX Mat");
		TASSERT(A16f[14] == 0.f,"Entry 15 incorrect in EulerX Mat");
		TASSERT(A16f[15] == 1.f,"Entry 16 incorrect in EulerX Mat");
		// Check Function of Mat Applied to a [0 1 1 .5] vector
		float vectold[] = {2.f,1.f,1.f,.5f};
		float vectnew[] = {0.f,0.f,0.f,0.f};
		//C_ij = A_ik * B_kj	
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += A16f[4*i+k]*vectold[k];

		TASSERT((vectnew[0] == 2.f),    "Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],1.f), "Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],-1.f),"Resulting vectnew[2] is incorrect");
		TASSERT((vectnew[3] == .5f),    "Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		//C_ij = A_ik * A_kj	
		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*A16f[4*k+j];

		// Check Function of Mat Applied twice to [0 1 1 .5] vector
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT((vectnew[0] == 2.f),    "Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],-1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],-1.f),"Resulting vectnew[2] is incorrect");
		TASSERT((vectnew[3] == .5f),    "Resulting vectnew[3] is incorrect");

		// Check Function of Mat Applied 3 times to [0 1 1 .5] vector
		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp2[4*i+j] += A16f[4*i+k]*temp[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp2[4*i+k]*vectold[k];

		TASSERT((vectnew[0] == 2.f),   "Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],-1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 1.f),"Resulting vectnew[2] is incorrect");
		TASSERT((vectnew[3] == .5f),   "Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*temp2[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT((vectnew[0] == 2.f),   "Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],1.f),"Resulting vectnew[2] is incorrect");
		TASSERT((vectnew[3] == .5f),   "Resulting vectnew[3] is incorrect");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerYCreate(){
		float angle = fPI / 2.f; // 90 degrees
		float* A16f = new float[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};

		// Make sure its actually setting entries to zero
		for(int i=0; i < 16; i++) A16f[i] = 1.0*rand();

		TASSERT(A16f[0]  == cosf(angle),"EulerY entry 1 is incorrect");
		TASSERT(A16f[1]  == 0.f,        "EulerY entry 2 is incorrect");
		TASSERT(A16f[2]  == sinf(angle),"EulerY entry 3 is incorrect");
		TASSERT(A16f[3]  == 0.f,        "EulerY entry 4 is incorrect");
		TASSERT(A16f[4]  == 0.f,        "EulerY entry 5 is incorrect");
		TASSERT(A16f[5]  == 1.f,        "EulerY entry 6 is incorrect");
		TASSERT(A16f[6]  == 0.f,        "EulerY entry 7 is incorrect");
		TASSERT(A16f[7]  == 0.f,        "EulerY entry 8 is incorrect");
		TASSERT(A16f[8]  ==-sinf(angle),"EulerY entry 9 is incorrect");
		TASSERT(A16f[9]  == 0.f,        "EulerY entry 10 is incorrect");
		TASSERT(A16f[10] == cosf(angle),"EulerY entry 11 is incorrect");
		TASSERT(A16f[11] == 0.f,        "EulerY entry 12 is incorrect");
		TASSERT(A16f[12] == 0.f,        "EulerY entry 13 is incorrect");
		TASSERT(A16f[13] == 0.f,        "EulerY entry 14 is incorrect");
		TASSERT(A16f[14] == 0.f,        "EulerY entry 15 is incorrect");
		TASSERT(A16f[15] == 1.f,        "EulerY entry 16 is incorrect");
		// Check Function of Mat Applied to a [0 1 1 .5] vector
		float vectold[] = {1.f,2.f,1.f,.5f};
		float vectnew[] = {0.f,0.f,0.f,0.f};
		//C_ij = A_ik * B_kj	
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += A16f[4*i+k]*vectold[k];

		TASSERT(    (vectnew[0] ==-1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1], 2.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 1.f),"Resulting vectnew[2] is incorrect");
		TASSERT(    (vectnew[3] == .5f),"Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		//C_ij = A_ik * A_kj	
		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*A16f[4*k+j];

		// Check Function of Mat Applied twice to [0 1 1 .5] vector
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT(   (vectnew[0] == -1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1], 2.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],-1.f),"Resulting vectnew[2] is incorrect");
		TASSERT(    (vectnew[3] == .5f),"Resulting vectnew[3] is incorrect");

		// Check Function of Mat Applied 3 times to [0 1 1 .5] vector
		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp2[4*i+j] += A16f[4*i+k]*temp[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp2[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0],-1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1], 2.f,0.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 1.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3], .5f,0.f),"Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*temp2[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0],1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],2.f,0.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],1.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3],.5f,0.f),"Resulting vectnew[3] is incorrect");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerZCreate(){
		float angle = fPI / 2.f; // 90 degrees
		float* A16f = new float[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};

		// Make sure its actually setting entries to zero
		for(int i=0; i < 16; i++) A16f[i] = 1.0*rand();

		const float cosa = cosf(angle);
		const float sina = sinf(angle);
		TASSERT(A16f[0] ==  cosa,"EulerY entry 10 is incorrect");
		TASSERT(A16f[1] == -sina,"EulerY entry 10 is incorrect");
		TASSERT(A16f[2] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[3] == 0.f,"EulerY entry 10 is incorrect");

		TASSERT(A16f[4] == sina,"EulerY entry 10 is incorrect");
		TASSERT(A16f[5] == cosa,"EulerY entry 10 is incorrect"); 
		TASSERT(A16f[6] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[7] == 0.f,"EulerY entry 10 is incorrect");

		TASSERT(A16f[8] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[9] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[10] == 1.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[11] == 0.f,"EulerY entry 10 is incorrect");

		TASSERT(A16f[12] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[13] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[14] == 0.f,"EulerY entry 10 is incorrect");
		TASSERT(A16f[15] == 1.f,"EulerY entry 10 is incorrect");

		// Check Function of Mat Applied to a [0 1 1 .5] vector
		float vectold[] = {1.f,1.f,2.f,.5f};
		float vectnew[] = {0.f,0.f,0.f,0.f};
		//C_ij = A_ik * B_kj	
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += A16f[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0],-1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1], 1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 2.f,0.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3], .5f,0.f),"Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		//C_ij = A_ik * A_kj	
		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*A16f[4*k+j];

		// Check Function of Mat Applied twice to [0 1 1 .5] vector
		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0],-1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],-1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 2.f,0.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3], .5f,0.f),"Resulting vectnew[3] is incorrect");

		// Check Function of Mat Applied 3 times to [0 1 1 .5] vector
		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp2[4*i+j] += A16f[4*i+k]*temp[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp2[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0], 1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],-1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2], 2.f,0.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3], .5f,0.f),"Resulting vectnew[3] is incorrect");

		memset(vectnew,0.f,4*sizeof(float));

		for(int i = 0; i < 4; i++)
				for(int j = 0; j < 4; j++)
						for(int k = 0; k < 4; k++)
								temp[4*i+j] += A16f[4*i+k]*temp2[4*k+j];

		for(int i = 0; i < 4; i++)
				for(int k = 0; k < 4; k++)
						vectnew[i] += temp[4*i+k]*vectold[k];

		TASSERT(fpcomp(vectnew[0],1.f),"Resulting vectnew[0] is incorrect");
		TASSERT(fpcomp(vectnew[1],1.f),"Resulting vectnew[1] is incorrect");
		TASSERT(fpcomp(vectnew[2],2.f,0.f),"Resulting vectnew[2] is incorrect");
		TASSERT(fpcomp(vectnew[3],.5f,0.f),"Resulting vectnew[3] is incorrect");
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerXCreateC(){
		float angle = fPI / 2.f; // 90 degrees
		float  A16f[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		SST_Mat44f_IdentityCreate(A16f);
		SST_Mat44f_EulerXCreateC(angle,A16f);
		SST_Mat44f_EulerXCreate(angle,temp);
		int i = 0;			
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 1 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 2 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 3 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 4 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 5 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 6 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 7 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 8 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 9 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 10 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 11 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 12 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 13 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 14 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 15 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 16 in EulerXCreateC acting on Identity disagrees with EulerXCreate"); i++;
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerYCreateC(){
		float angle = fPI / 2.f; // 90 degrees
		float  A16f[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		SST_Mat44f_IdentityCreate(A16f);
		SST_Mat44f_EulerYCreateC(angle,A16f);
		SST_Mat44f_EulerYCreate(angle,temp);
		int i = 0;			
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 1 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 2 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 3 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 4 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 5 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 6 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 7 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 8 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 9 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 10 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 11 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 12 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 13 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 14 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 15 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 16 in EulerYCreateC acting on Identity disagrees with EulerYCreate"); i++;
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_EulerZCreateC(){
		float angle = fPI / 2.f; // 90 degrees
		float  A16f[16];
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		SST_Mat44f_IdentityCreate(A16f);
		SST_Mat44f_EulerZCreateC(angle,A16f);
		SST_Mat44f_EulerZCreate(angle,temp);
		int i = 0;			
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 1  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 2  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 3  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 4  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 5  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 6  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 7  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 8  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 9  in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 10 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 11 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 12 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 13 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 14 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 15 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		TASSERT(fpcomp(A16f[i],temp[i]),"Entry 16 in EulerZCreateC acting on Identity disagrees with EulerZCreate"); i++;
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_ShearCreate(){

		float  A16f[16];
		float  shearing[6] = {0.5f,0.25f,0.5f,0.25f,.5f,.25f};
		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};

		SST_Mat44f_ShearCreate(shearing,A16f);

		TASSERT(A16f[0] == 1.f,"EulerY entry 1 is incorrect");
		TASSERT(A16f[1] == shearing[0],"EulerY entry 2 is incorrect");
		TASSERT(A16f[2] == shearing[1],"EulerY entry 3 is incorrect");
		TASSERT(A16f[3] == 0.f,"EulerY entry 4 is incorrect");

		TASSERT(A16f[4] == shearing[2],"EulerY entry 5 is incorrect");
		TASSERT(A16f[5] == 1.f,"EulerY entry 6 is incorrect");
		TASSERT(A16f[6] == shearing[3],"EulerY entry 7 is incorrect");
		TASSERT(A16f[7] == 0.f,"EulerY entry 8 is incorrect");

		TASSERT(A16f[8] == shearing[4],"EulerY entry 9 is incorrect");
		TASSERT(A16f[9] == shearing[5],"EulerY entry 10 is incorrect");
		TASSERT(A16f[10] == 1.f,"EulerY entry 11 is incorrect");
		TASSERT(A16f[11] == 0.f,"EulerY entry 12 is incorrect");

		TASSERT(A16f[12] == 0.f,"EulerY entry 13 is incorrect");
		TASSERT(A16f[13] == 0.f,"EulerY entry 14 is incorrect");
		TASSERT(A16f[14] == 0.f,"EulerY entry 15 is incorrect");
		TASSERT(A16f[15] == 1.f,"EulerY entry 16 is incorrect");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_FreeTransformCreate(){
		float  A16f[16];
		float  scale[3] = {0.5f,0.25f,0.5f};
		float  shearing[6] = {0.5f,0.25f,0.5f,0.25f,.5f,.25f};

		float  temp[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};
		float temp2[16] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f};

		TASSERT(A16f[0] == scale[0],"EulerY entry 1 is incorrect");
		TASSERT(A16f[1] == shearing[0],"EulerY entry 2 is incorrect");
		TASSERT(A16f[2] == shearing[1],"EulerY entry 3 is incorrect");
		TASSERT(A16f[3] == 0.f,"EulerY entry 4 is incorrect");

		TASSERT(A16f[4] == shearing[2],"EulerY entry 5 is incorrect");
		TASSERT(A16f[5] == scale[1],"EulerY entry 6 is incorrect");
		TASSERT(A16f[6] == shearing[3],"EulerY entry 7 is incorrect");
		TASSERT(A16f[7] == 0.f,"EulerY entry 8 is incorrect");

		TASSERT(A16f[8] == shearing[4],"EulerY entry 9 is incorrect");
		TASSERT(A16f[9] == shearing[5],"EulerY entry 10 is incorrect");
		TASSERT(A16f[10] == scale[2],"EulerY entry 11 is incorrect");
		TASSERT(A16f[11] == 0.f,"EulerY entry 12 is incorrect");

		TASSERT(A16f[12] == 0.f,"EulerY entry 13 is incorrect");
		TASSERT(A16f[13] == 0.f,"EulerY entry 14 is incorrect");
		TASSERT(A16f[14] == 0.f,"EulerY entry 15 is incorrect");
		TASSERT(A16f[15] == 1.f,"EulerY entry 16 is incorrect");

		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_QuaternionCreate(){
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44f_ScaleCreate(){
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44_LookAt(){
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat33_ExtractFromMat44(){
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44_PerspectiveProjectionCreate(){
		return ZTEST_SUCCESS;
}
static const char* testSST_Mat44_OrthogonalProjectionCreate(){
		return ZTEST_SUCCESS;
}
