/***************************************************************************/
// 
/***************************************************************************/

/******************* includes ****************************/

#include "Math/MathPCH.h"





// Some constants
const float Math::Pi           = 3.141592654f;
#ifdef PS2
const float Math::TwoPi        = 6.283185308f;
const float Math::HalfPi       = 1.570796327f;
const float Math::QuarterPi    = 0.785398164f;
const float Math::PiSquared    = 9.869604404f;
const float Math::InvPiSquared = 0.101321184f;
const float Math::InvPi			 = 0.318309886f;
const float Math::Epsilon      = 1e-7f;

const float Math::m_Deg2Rad = 0.017453293f;
const float Math::m_Rad2Deg = 57.29577951f;
#else
const float Math::TwoPi        = Math::Pi * 2.0f;
const float Math::HalfPi       = Math::Pi / 2.0f;
const float Math::QuarterPi    = Math::Pi / 4.0f;
const float Math::PiSquared    = Math::Pi * Math::Pi;
const float Math::InvPiSquared = 1.0f / Math::PiSquared;
const float Math::InvPi			 = 1.0f / Math::Pi;
const float Math::Epsilon      = 1e-7f;

const float Math::m_Deg2Rad = Math::Pi / 180.0f;
const float Math::m_Rad2Deg = 180.0f / Math::Pi;
#endif

const float Math::PositiveInfinity = Math::IntAsFloat(0x7F800000);
const float Math::NegativeInfinity = Math::IntAsFloat(0x8F800000);

const float Math::SquareRootOfTwo = 1.414213562f;

#ifdef WIN32
#ifndef CONSUMER_BUILD
/***************************************************************************/
/***************************************************************************/
// check whether math project has MMX_OK defined or not. the issue is that all projects in a game
// must be consistent-- MMX_OK is either 1 or 0 for all. inconsistency leads to bizarre crashes
int Math::MMXOK()
{
#if !defined (_XBOX)
	return(MMX_OK);	// can't be inline, since that would just use the MMX_OK state of the including module
#else
	return(1);
#endif //XBOX
}
#endif //CONSUMER_BUILD
#endif //WIN32

#ifdef _DEBUG
/***************************************************************************/
// Make sure this compiles without warnings on your platform
/***************************************************************************/
static void TestMathStuffOut(void)
{
	float degrees = 60;
	float radians = Math::Pi * 0.44f;
	float x = 12.0f;
	float y = 13.0f;
	int i = 68;
	float f;

	// Degree to radians amd back
	f = Math::Deg2Rad(degrees);
	f = Math::Rad2Deg(radians);

	// Make an angle in the range -pi to pi
	f = Math::NormalAngle(radians);

	// The trig functions with radians as input
	f = Math::Sin(radians);
	f = Math::Cos(radians);
	f = Math::Tan(radians);

	// The trig functions with degrees as input
	f = Math::SinDeg(degrees);
	f = Math::CosDeg(degrees);
	f = Math::TanDeg(degrees);

	// Inverse functions
	f = Math::ArcSin(x);
	f = Math::ArcCos(x);
	f = Math::ArcTan(x);
	f = Math::ArcTan2(y, x);

	// Inverse functions that output degrees
	f = Math::ArcSinDeg(x);
	f = Math::ArcCosDeg(x);
	f = Math::ArcTanDeg(x);
	f = Math::ArcTan2Deg(y, x);

	// return absolute value of x
	f = Math::Abs(x);
	int j = Math::Abs(i);

	// Chop of the decimal places without rounding
	f = Math::Floor(x);

	// Return the ceil of x
	f = Math::Ceil(x);

	// Round (with .5 going higher)
	f = Math::Round(x);

	// duh
	f = Math::Mod(x, y);
	
	// return the inverse of x
	f = Math::Inverse(x);

	// return the square root of x
	f = Math::Sqrt(x);

	// Raise x^y
	f = Math::Pow(x, y);

	// return e^x
	f = Math::Exp(x);

	// return natural log of x
	f = Math::Log(x);

	// return base 10 log of x
	f = Math::Log10(x);

	// the fast versions
	f = Math::FastSin(x);
	f = Math::FastCos(x);
	f = Math::FastTan(x);
	f = Math::FastSqrt(x);
}
#endif

/* implement math stats stuff-- this is to collect data about how frequently the different math routines are called, 
with an eye towards optimizing where it gets the most return */

#include "Math/MathStats.h"
#ifdef MATH_STATS

#include <stdio.h>
#include <string.h>

/* frequency count array */

int nMathStats[MATH_STATS_COUNT] = {0};

/* name array so i can get correspondence-- do it by pairing so that changing the enum won't screw up the name order */

typedef struct
{
	int nIndex;
	char *pName;
} ts_MathStatsName;

ts_MathStatsName MathStatsName[] = {

	/* Vect2.hpp */

	{	VECTOR2_CLEAR,	"VECTOR2_CLEAR"	},
	{	VECTOR2_SET_F,	"VECTOR2_SET_F"	},
	{	VECTOR2_SET_FARRAY,	"VECTOR2_SET_FARRAY"	},
	{	VECTOR2_DOT_V2,	"VECTOR2_DOT_V2"	},
	{	VECTOR2_DIAG_V2,	"VECTOR2_DIAG_V2"	},
	{	VECTOR2_LENGTH,	"VECTOR2_LENGTH"	},
	{	VECTOR2_LENGTH_SQUARED,	"VECTOR2_LENGTH_SQUARED"	},
	{	VECTOR2_NORMALIZE,	"VECTOR2_NORMALIZE"	},
	{	VECTOR2_NORMALIZED,	"VECTOR2_NORMALIZED"	},
	{	VECTOR2_PROJECTION_V2, "VECTOR2_PROJECTION_V2"	},
	{	VECTOR2_NEGATE,	"VECTOR2_NEGATE"	},
	{	VECTOR2_DOT2_V2_V2,	"VECTOR2_DOT2_V2_V2"	},
	{	VECTOR2_DIAG_V2_V2,	"VECTOR2_DIAG_V2_V2"	},
	{	VECTOR2_LENGTH_V2,	"VECTOR2_LENGTH_V2"	},
	{	VECTOR2_NORMALIZE_V2,	"VECTOR2_NORMALIZE_V2"	},
	{	VECTOR2_EQUALS_V2,	"VECTOR2_EQUALS_V2"	},
	{	VECTOR2_NOT_EQUAL_V2,	"VECTOR2_NOT_EQUAL_V2"	},
	{	VECTOR2_PLUS_EQUALS_V2,	"VECTOR2_PLUS_EQUALS_V2"	},
	{	VECTOR2_MINUS_EQUALS_V2,	"VECTOR2_MINUS_EQUALS_V2"	},
	{	VECTOR2_TIMES_EQUALS_F,	"VECTOR2_TIMES_EQUALS_F"	},
	{	VECTOR2_DIVIDE_EQUALS_F,	"VECTOR2_DIVIDE_EQUALS_F"	},
	{	VECTOR2_PLUS_V2,	"VECTOR2_PLUS_V2"	},
	{	VECTOR2_MINUS_V2,	"VECTOR2_MINUS_V2"	},
	{	VECTOR2_TIMES_F,	"VECTOR2_TIMES_F"	},
	{	VECTOR2_DIVIDE_F,	"VECTOR2_DIVIDE_F"	},
	{	VECTOR2_ARRAY_INDEX,	"VECTOR2_ARRAY_INDEX"	},
	{	VECTOR2_CAST_F,	"VECTOR2_CAST_F"	},

	/* Vect3.hpp */

	{	VECTOR3_CLEAR,	"VECTOR3_CLEAR"	},
	{	VECTOR3_SET_F,	"VECTOR3_SET_F"	},
	{	VECTOR3_SET_FARRAY,	"VECTOR3_SET_FARRAY"	},
	{	VECTOR3_SET_V4,	"VECTOR3_SET_V4"	},
	{	VECTOR3_DOT_V3,	"VECTOR3_DOT_V3"	},
	{	VECTOR3_CROSS_V3,	"VECTOR3_CROSS_V3"	},
	{	VECTOR3_DIAG_V3,	"VECTOR3_DIAG_V3"	},
	{	VECTOR3_PROJECTION_V3,	"VECTOR3_PROJECTION_V3"	},
	{	VECTOR3_LENGTH,	"VECTOR3_LENGTH"	},
	{	VECTOR3_LENGTH_XZ,	"VECTOR3_LENGTH_XZ"	},
	{	VECTOR3_LENGTH_SQUARED,	"VECTOR3_LENGTH_SQUARED"	},
	{	VECTOR3_LENGTH_XZ_SQUARED,	"VECTOR3_LENGTH_XZ_SQUARED"	},
	{	VECTOR3_NORMALIZE,	"VECTOR3_NORMALIZE"	},
	{	VECTOR3_NORMALIZED,	"VECTOR3_NORMALIZED"	},
	{	VECTOR3_NEGATE,	"VECTOR3_NEGATE"	},
	{	VECTOR3_NEGATED,	"VECTOR3_NEGATED"	},
	{	VECTOR3_DOT_V3_V3,	"VECTOR3_DOT_V3_V3"	},
	{	VECTOR3_CROSS_V3_V3,	"VECTOR3_CROSS_V3_V3"	},
	{	VECTOR3_DIAG_V3_V3,	"VECTOR3_DIAG_V3_V3"	},
	{	VECTOR3_LENGTH_V3,	"VECTOR3_LENGTH_V3"	},
	{	VECTOR3_LENGTHXZ_V3,	"VECTOR3_LENGTHXZ_V3"	},
	{	VECTOR3_LENGTH_SQUARED_V3,	"VECTOR3_LENGTH_SQUARED_V3"	},
	{	VECTOR3_LENGTHXZ_SQUARED_V3,	"VECTOR3_LENGTHXZ_SQUARED_V3"	},
	{	VECTOR3_NORMALIZE_V3,	"VECTOR3_NORMALIZE_V3"	},
	{	VECTOR3_PROJECTION_V3_V3,	"VECTOR3_PROJECTION_V3_V3"	},
	{	VECTOR3_EQUALS_V3,	"VECTOR3_EQUALS_V3"	},
	{	VECTOR3_NOT_EQUAL_V3,	"VECTOR3_NOT_EQUAL_V3"	},
	{	VECTOR3_PLUS_EQUALS_V3,	"VECTOR3_PLUS_EQUALS_V3"	},
	{	VECTOR3_MINUS_EQUALS_V3,	"VECTOR3_MINUS_EQUALS_V3"	},
	{	VECTOR3_TIMES_EQUALS_F,	"VECTOR3_TIMES_EQUALS_F"	},
	{	VECTOR3_DIVIDE_EQUALS_F,	"VECTOR3_DIVIDE_EQUALS_F"	},
	{	VECTOR3_PLUS_V3,	"VECTOR3_PLUS_V3"	},
	{	VECTOR3_MINUS_V3,	"VECTOR3_MINUS_V3"	},
	{	VECTOR3_TIMES_F,	"VECTOR3_TIMES_F"	},
	{	VECTOR3_DIVIDE_F,	"VECTOR3_DIVIDE_F"	},
	{	VECTOR3_TIMES_M3X3,	"VECTOR3_TIMES_M3X3"	},
	{	VECTOR3_DIVIDE_D3X3,	"VECTOR3_DIVIDE_D3X3"	},
	{	VECTOR3_ARRAY_INDEX,	"VECTOR3_ARRAY_INDEX"	},
	{	VECTOR3_FAST_MULTIPLY,	"VECTOR3_FAST_MULTIPLY"	},
	{	VECTOR3_FAST_BASIS_TRANSFORM,	"VECTOR3_FAST_BASIS_TRANSFORM"	},
	{	VECTOR3_CAST_F,	"VECTOR3_CAST_F"	},

	/* Vect4.hpp */

	{	VECTOR4_CLEAR,	"VECTOR4_CLEAR"	},
	{	VECTOR4_SET_F,	"VECTOR4_SET_F"	},
	{	VECTOR4_SET_FARRAY,	"VECTOR4_SET_FARRAY"	},
	{	VECTOR4_SET_V3,	"VECTOR4_SET_V3"	},
	{	VECTOR4_DOT_V4,	"VECTOR4_DOT_V4"	},
	{	VECTOR4_CROSS_V4,	"VECTOR4_CROSS_V4"	},
	{	VECTOR4_DIAG_V4,	"VECTOR4_DIAG_V4"	},
	{	VECTOR4_LENGTH,	"VECTOR4_LENGTH"	},
	{	VECTOR4_LENGTH_SQUARED,	"VECTOR4_LENGTH_SQUARED"	},
	{	VECTOR4_NORMALIZE,	"VECTOR4_NORMALIZE"	},
	{	VECTOR4_NORMALIZED,	"VECTOR4_NORMALIZED"	},
	{	VECTOR4_NEGATE,	"VECTOR4_NEGATE"	},
	{	VECTOR4_DOT_V4_V4,	"VECTOR4_DOT_V4_V4"	},
	{	VECTOR4_CROSS_V4_V4,	"VECTOR4_CROSS_V4_V4"	},
	{	VECTOR4_DIAG_V4_V4,	"VECTOR4_DIAG_V4_V4"	},
	{	VECTOR4_LENGTH_V4,	"VECTOR4_LENGTH_V4"	},
	{	VECTOR4_NORMALIZE_V4,	"VECTOR4_NORMALIZE_V4"	},
	{	VECTOR4_EQUALS_V4,	"VECTOR4_EQUALS_V4"	},
	{	VECTOR4_NOT_EQUAL_V4,	"VECTOR4_NOT_EQUAL_V4"	},
	{	VECTOR4_PLUS_EQUALS_V4,	"VECTOR4_PLUS_EQUALS_V4"	},
	{	VECTOR4_MINUS_EQUALS_V4,	"VECTOR4_MINUS_EQUALS_V4"	},
	{	VECTOR4_TIMES_EQUALS_F,	"VECTOR4_TIMES_EQUALS_F"	},
	{	VECTOR4_DIVIDE_EQUALS_F,	"VECTOR4_DIVIDE_EQUALS_F"	},
	{	VECTOR4_PLUS_V4,	"VECTOR4_PLUS_V4"	},
	{	VECTOR4_MINUS_F4,	"VECTOR4_MINUS_F4"	},
	{	VECTOR4_TIMES_F,	"VECTOR4_TIMES_F"	},
	{	VECTOR4_DIVIDE_F,	"VECTOR4_DIVIDE_F"	},
	{	VECTOR4_ARRAY_INDEX,	"VECTOR4_ARRAY_INDEX"	},
	{	VECTOR4_FAST_MULTIPLY,	"VECTOR4_FAST_MULTIPLY"	},
	{	VECTOR4_FAST_TRANSFORM,	"VECTOR4_FAST_TRANSFORM"	},
	{	VECTOR4_FAST_BASIS_TRANSFORM,	"VECTOR4_FAST_BASIS_TRANSFORM"	},
	{	VECTOR4_CAST_F,	"VECTOR4_CAST_F"	},

	/* miscellaneous vector routines from Vector.hpp */

	{	F_TIMES_V2,	"F_TIMES_V2"	},
	{	F_TIMES_V3,	"F_TIMES_V3"	},
	{	F_TIMES_V4,	"F_TIMES_V4"	},
	{	ROTATE_POINT_AROUND_AXIS,	"ROTATE_POINT_AROUND_AXIS"	},
	{	NEAREST_POINT_ON_LINE_SEG_V2,	"NEAREST_POINT_ON_LINE_SEG_V2"	},
	{	NEAREST_POINT_ON_LINE_SEG_V3,	"NEAREST_POINT_ON_LINE_SEG_V3"	},
	{	NEAREST_POINT_ON_LINE_V2,	"NEAREST_POINT_ON_LINE_V2"	},
	{	NEAREST_POINT_ON_LINE_V3,	"NEAREST_POINT_ON_LINE_V3"	},
	{	DISTANCE_V3_V3,	"DISTANCE_V3_V3"	},
	{	DISTANCE_SQUARED_V3_V3,	"DISTANCE_SQUARED_V3_V3"	},
	{	POINTS_COINCIDE_V3_V3_F,	"POINTS_COINCIDE_V3_V3_F"	},

	/* Mat3x3.hpp */

	{	MATRIX3X3_CONSTRUCT_F,	"MATRIX3X3_CONSTRUCT_F"	},
	{	MATRIX3X3_CONSTRUCT_V3,	"MATRIX3X3_CONSTRUCT_V3"	},
	{	MATRIX3X3_CONSTRUCT_G4X4,	"MATRIX3X3_CONSTRUCT_G4X4"	},
	{	MATRIX3X3_ASSIGN_M3X3,	"MATRIX3X3_ASSIGN_M3X3"	},
	{	MATRIX3X3_ASSIGN_G4X4,	"MATRIX3X3_ASSIGN_G4X4"	},
	{	MATRIX3X3_SET_F,	"MATRIX3X3_SET_F"	},
	{	MATRIX3X3_DIAGONALIZE_V3,	"MATRIX3X3_DIAGONALIZE_V3"	},
	{	MATRIX3X3_SKEW_SYMMETRIC_V3,	"MATRIX3X3_SKEW_SYMMETRIC_V3"	},
	{	MATRIX3X3_IDENTITY,	"MATRIX3X3_IDENTITY"	},
	{	MATRIX3X3_IS_IDENTITY,	"MATRIX3X3_IS_IDENTITY"	},
	{	MATRIX3X3_TRANSPOSE_M3X3,	"MATRIX3X3_TRANSPOSE_M3X3"	},
	{	MATRIX3X3_TRANSPOSE,	"MATRIX3X3_TRANSPOSE"	},
	{	MATRIX3X3_TRANSPOSED,	"MATRIX3X3_TRANSPOSED"	},
	{	MATRIX3X3_INVERT,	"MATRIX3X3_INVERT"	},
	{	MATRIX3X3_DET_M3X3,	"MATRIX3X3_DET_M3X3"	},
	{	MATRIX3X3_DET,	"MATRIX3X3_DET"	},
	{	MATRIX3X3_COF_M3X3,	"MATRIX3X3_COF_M3X3"	},
	{	MATRIX3X3_COF,	"MATRIX3X3_COF"	},
	{	MATRIX3X3_ADJ_M3X3,	"MATRIX3X3_ADJ_M3X3"	},
	{	MATRIX3X3_ADJ,	"MATRIX3X3_ADJ"	},
	{	MATRIX3X3_EQUALS_M3X3,	"MATRIX3X3_EQUALS_M3X3"	},
	{	MATRIX3X3_NOT_EQUAL_M3X3,	"MATRIX3X3_NOT_EQUAL_M3X3"	},
	{	MATRIX3X3_TIMES_F,	"MATRIX3X3_TIMES_F"	},
	{	MATRIX3X3_TIMES_EQUALS_F,	"MATRIX3X3_TIMES_EQUALS_F"	},
	{	MATRIX3X3_DIVIDE_F,	"MATRIX3X3_DIVIDE_F"	},
	{	MATRIX3X3_DIVIDE_EQUALS_F,	"MATRIX3X3_DIVIDE_EQUALS_F"	},
	{	MATRIX3X3_PLUS_M3X3,	"MATRIX3X3_PLUS_M3X3"	},
	{	MATRIX3X3_PLUS_EQUALS_M3X3,	"MATRIX3X3_PLUS_EQUALS_M3X3"	},
	{	MATRIX3X3_MINUS_M3X3,	"MATRIX3X3_MINUS_M3X3"	},
	{	MATRIX3X3_MINUS_EQUALS_M3X3,	"MATRIX3X3_MINUS_EQUALS_M3X3"	},
	{	MATRIX3X3_TIMES_M3X3,	"MATRIX3X3_TIMES_M3X3"	},
	{	MATRIX3X3_TIMES_EQUALS_M3X3,	"MATRIX3X3_TIMES_EQUALS_M3X3"	},
	{	MATRIX3X3_TIMES_M4X4,	"MATRIX3X3_TIMES_M4X4"	},
	{	MATRIX3X3_TIMES_G4X4,	"MATRIX3X3_TIMES_G4X4"	},
	{	MATRIX3X3_DIVIDE_C4X4,	"MATRIX3X3_DIVIDE_C4X4"	},
	{	MATRIX3X3_DIVIDE_D3X3,	"MATRIX3X3_DIVIDE_D3X3"	},
	{	MATRIX3X3_DIVIDE_EQUALS_D3X3,	"MATRIX3X3_DIVIDE_EQUALS_D3X3"	},
	{	MATRIX3X3_TIMES_UL_G4X4,	"MATRIX3X3_TIMES_UL_G4X4"	},
	{	MATRIX3X3_TIMES_EQUALS_UL_G4X4,	"MATRIX3X3_TIMES_EQUALS_UL_G4X4"	},
	{	MATRIX3X3_ROW_I,	"MATRIX3X3_ROW_I"	},
	{	MATRIX3X3_COLUMN_I,	"MATRIX3X3_COLUMN_I"	},
	{	MATRIX3X3_SET_ROW_I_V3,	"MATRIX3X3_SET_ROW_I_V3"	},
	{	MATRIX3X3_SET_COLUMN_I_V3,	"MATRIX3X3_SET_COLUMN_I_V3"	},
	{	MATRIX3X3_GET_ROW0_V3,	"MATRIX3X3_GET_ROW0_V3"	},
	{	MATRIX3X3_GET_ROW1_V3,	"MATRIX3X3_GET_ROW1_V3"	},
	{	MATRIX3X3_GET_ROW2_V3,	"MATRIX3X3_GET_ROW2_V3"	},
	{	MATRIX3X3_GET_COLUMN0_V3,	"MATRIX3X3_GET_COLUMN0_V3"	},
	{	MATRIX3X3_GET_COLUMN1_V3,	"MATRIX3X3_GET_COLUMN1_V3"	},
	{	MATRIX3X3_GET_COLUMN2_V3,	"MATRIX3X3_GET_COLUMN2_V3"	},
	{	MATRIX3X3_SET_ROW0_V3,	"MATRIX3X3_SET_ROW0_V3"	},
	{	MATRIX3X3_SET_ROW1_V3,	"MATRIX3X3_SET_ROW1_V3"	},
	{	MATRIX3X3_SET_ROW2_V3,	"MATRIX3X3_SET_ROW2_V3"	},
	{	MATRIX3X3_SET_COLUMN0_V3,	"MATRIX3X3_SET_COLUMN0_V3"	},
	{	MATRIX3X3_SET_COLUMN1_V3,	"MATRIX3X3_SET_COLUMN1_V3"	},
	{	MATRIX3X3_SET_COLUMN2_V3,	"MATRIX3X3_SET_COLUMN2_V3"	},
	{	MATRIX3X3_SET_SCALE_F,	"MATRIX3X3_SET_SCALE_F"	},
	{	MATRIX3X3_SET_XSCALE_F,	"MATRIX3X3_SET_XSCALE_F"	},
	{	MATRIX3X3_SET_YSCALE_F,	"MATRIX3X3_SET_YSCALE_F"	},
	{	MATRIX3X3_SET_ZSCALE_F,	"MATRIX3X3_SET_ZSCALE_F"	},
	{	MATRIX3X3_SET_XROTATION_F,	"MATRIX3X3_SET_XROTATION_F"	},
	{	MATRIX3X3_SET_YROTATION_F,	"MATRIX3X3_SET_YROTATION_F"	},
	{	MATRIX3X3_SET_ZROTATION_F,	"MATRIX3X3_SET_ZROTATION_F"	},
	{	MATRIX3X3_SET_XYZROTATION_V3,	"MATRIX3X3_SET_XYZROTATION_V3"	},
	{	MATRIX3X3_CAT_SCALE_F,	"MATRIX3X3_CAT_SCALE_F"	},
	{	MATRIX3X3_CAT_XSCALE_F,	"MATRIX3X3_CAT_XSCALE_F"	},
	{	MATRIX3X3_CAT_YSCALE_F,	"MATRIX3X3_CAT_YSCALE_F"	},
	{	MATRIX3X3_CAT_ZSCALE_F,	"MATRIX3X3_CAT_ZSCALE_F"	},
	{	MATRIX3X3_CAT_XROTATION_F,	"MATRIX3X3_CAT_XROTATION_F"	},
	{	MATRIX3X3_CAT_YROTATION_F,	"MATRIX3X3_CAT_YROTATION_F"	},
	{	MATRIX3X3_CAT_ZROTATION_F,	"MATRIX3X3_CAT_ZROTATION_F"	},
	{	DIRCOS3X3_INVERT,	"DIRCOS3X3_INVERT"	},
	{	DIRCOS3X3_INVERT_TIMES_M4X4,	"DIRCOS3X3_INVERT_TIMES_M4X4"	},
	{	DIRCOS3X3_INVERT_TIMES_G4X4,	"DIRCOS3X3_INVERT_TIMES_G4X4"	},
	{	DIRCOS3X3_INVERT_TIMES_M3X3,	"DIRCOS3X3_INVERT_TIMES_M3X3"	},
	{	DIRCOS3X3_INVERT_TIMES_EQUALS_D3X3,	"DIRCOS3X3_INVERT_TIMES_EQUALS_D3X3"	},
	{	DIRCOS3X3_INVERT_DIVIDE_C4X4,	"DIRCOS3X3_INVERT_DIVIDE_C4X4"	},
	{	DIRCOS3X3_INVERT_DIVIDE_D3X3,	"DIRCOS3X3_INVERT_DIVIDE_D3X3"	},
	{	DIRCOS3X3_INVERT_DIVIDE_EQUALS_D3X3,	"DIRCOS3X3_INVERT_DIVIDE_EQUALS_D3X3"	},

	/* Mat3x3.cpp */

	{	MATRIX3X3_INVERT_M3X3,	"MATRIX3X3_INVERT_M3X3"	},
	{	DIRCOS3X3_INVERT_D3X3,	"DIRCOS3X3_INVERT_D3X3"	},
	{	DIRCOS3X3_ORTHONORMALIZE,	"DIRCOS3X3_ORTHONORMALIZE"	},
	{	DIRCOS3X3_ORTHOGANALIZE,	"DIRCOS3X3_ORTHOGANALIZE"	},
	{	DIRCOS3X3_DECODE_TO_YXZ_V3,	"DIRCOS3X3_DECODE_TO_YXZ_V3"	},
	{	DIRCOS3X3_DECODE_TO_XZY_V3,	"DIRCOS3X3_DECODE_TO_XZY_V3"	},
	{	DIRCOS3X3_DECODE_TO_ZYX_V3,	"DIRCOS3X3_DECODE_TO_ZYX_V3"	},
	{	DIRCOS3X3_BUILD_FROM_VECTOR_V3,	"DIRCOS3X3_BUILD_FROM_VECTOR_V3"	},
	{	MATRIX3X3_DECONSTRUCT,	"MATRIX3X3_DECONSTRUCT"	},

	/* Mat4x4.hpp */

	{	MATRIX4X4_CONSTRUCT_F,	"MATRIX4X4_CONSTRUCT_F"	},
	{	MATRIX4X4_ASSIGN_M4X4,	"MATRIX4X4_ASSIGN_M4X4"	},
	{	MATRIX4X4_SET_F,	"MATRIX4X4_SET_F"	},
	{	MATRIX4X4_IDENTITY,	"MATRIX4X4_IDENTITY"	},
	{	MATRIX4X4_IS_IDENTITY,	"MATRIX4X4_IS_IDENTITY"	},
	{	MATRIX4X4_INVERT,	"MATRIX4X4_INVERT"	},
	{	MATRIX4X4_TRANSPOSE_M4X4,	"MATRIX4X4_TRANSPOSE_M4X4"	},
	{	MATRIX4X4_TRANSPOSE,	"MATRIX4X4_TRANSPOSE"	},
	{	MATRIX4X4_DET_M4X4,	"MATRIX4X4_DET_M4X4"	},
	{	MATRIX4X4_DET,	"MATRIX4X4_DET"	},
	{	MATRIX4X4_COF_M4X4,	"MATRIX4X4_COF_M4X4"	},
	{	MATRIX4X4_COF,	"MATRIX4X4_COF"	},
	{	MATRIX4X4_ADJ_M4X4,	"MATRIX4X4_ADJ_M4X4"	},
	{	MATRIX4X4_ADJ,	"MATRIX4X4_ADJ"	},
	{	MATRIX4X4_EQUALS_M4X4,	"MATRIX4X4_EQUALS_M4X4"	},
	{	MATRIX4X4_NOT_EQUAL_M4X4,	"MATRIX4X4_NOT_EQUAL_M4X4"	},
	{	MATRIX4X4_TIMES_F,	"MATRIX4X4_TIMES_F"	},
	{	MATRIX4X4_DIVIDE_F,	"MATRIX4X4_DIVIDE_F"	},
	{	MATRIX4X4_TIMES_EQUALS_F,	"MATRIX4X4_TIMES_EQUALS_F"	},
	{	MATRIX4X4_DIVIDE_EQUALS_F,	"MATRIX4X4_DIVIDE_EQUALS_F"	},
	{	MATRIX4X4_PLUS_M4X4,	"MATRIX4X4_PLUS_M4X4"	},
	{	MATRIX4X4_PLUS_EQUALS_M4X4,	"MATRIX4X4_PLUS_EQUALS_M4X4"	},
	{	MATRIX4X4_MINUS_M4X4,	"MATRIX4X4_MINUS_M4X4"	},
	{	MATRIX4X4_MINUS_EQUALS_M4X4,	"MATRIX4X4_MINUS_EQUALS_M4X4"	},
	{	MATRIX4X4_FAST_MULTIPLY,	"MATRIX4X4_FAST_MULTIPLY"	},
	{	MATRIX4X4_TIMES_M4X4,	"MATRIX4X4_TIMES_M4X4"	},
	{	MATRIX4X4_TIMES_EQUALS_M4X4,	"MATRIX4X4_TIMES_EQUALS_M4X4"	},
	{	MATRIX4X4_TIMES_G4X4,	"MATRIX4X4_TIMES_G4X4"	},
	{	MATRIX4X4_TIMES_EQUALS_G4X4,	"MATRIX4X4_TIMES_EQUALS_G4X4"	},
	{	MATRIX4X4_DIVIDE_C4X4,	"MATRIX4X4_DIVIDE_C4X4"	},
	{	MATRIX4X4_DIVIDE_EQUALS_C4X4,	"MATRIX4X4_DIVIDE_EQUALS_C4X4"	},
	{	MATRIX4X4_TIMES_M3X3,	"MATRIX4X4_TIMES_M3X3"	},
	{	MATRIX4X4_TIMES_EQUALS_M3X3,	"MATRIX4X4_TIMES_EQUALS_M3X3"	},
	{	MATRIX4X4_DIVIDE_D3X3,	"MATRIX4X4_DIVIDE_D3X3"	},
	{	MATRIX4X4_DIVIDE_EQUALS_D3X3,	"MATRIX4X4_DIVIDE_EQUALS_D3X3"	},
	{	MATRIX4X4_ROW_I,	"MATRIX4X4_ROW_I"	},
	{	MATRIX4X4_COLUMN_I,	"MATRIX4X4_COLUMN_I"	},
	{	MATRIX4X4_SET_ROW_I_V3,	"MATRIX4X4_SET_ROW_I_V3"	},
	{	MATRIX4X4_SET_COLUMN_I_V3,	"MATRIX4X4_SET_COLUMN_I_V3"	},
	{	MATRIX4X4_GET_ROW0_V3,	"MATRIX4X4_GET_ROW0_V3"	},
	{	MATRIX4X4_GET_ROW1_V3,	"MATRIX4X4_GET_ROW1_V3"	},
	{	MATRIX4X4_GET_ROW2_V3,	"MATRIX4X4_GET_ROW2_V3"	},
	{	MATRIX4X4_GET_ROW3_V3,	"MATRIX4X4_GET_ROW3_V3"	},
	{	MATRIX4X4_GET_COLUMN0_V3,	"MATRIX4X4_GET_COLUMN0_V3"	},
	{	MATRIX4X4_GET_COLUMN1_V3,	"MATRIX4X4_GET_COLUMN1_V3"	},
	{	MATRIX4X4_GET_COLUMN2_V3,	"MATRIX4X4_GET_COLUMN2_V3"	},
	{	MATRIX4X4_GET_COLUMN3_V3,	"MATRIX4X4_GET_COLUMN3_V3"	},
	{	MATRIX4X4_SET_ROW0_V3,	"MATRIX4X4_SET_ROW0_V3"	},
	{	MATRIX4X4_SET_ROW1_V3,	"MATRIX4X4_SET_ROW1_V3"	},
	{	MATRIX4X4_SET_ROW2_V3,	"MATRIX4X4_SET_ROW2_V3"	},
	{	MATRIX4X4_SET_ROW3_V3,	"MATRIX4X4_SET_ROW3_V3"	},
	{	MATRIX4X4_SET_COLUMN0_V3,	"MATRIX4X4_SET_COLUMN0_V3"	},
	{	MATRIX4X4_SET_COLUMN1_V3,	"MATRIX4X4_SET_COLUMN1_V3"	},
	{	MATRIX4X4_SET_COLUMN2_V3,	"MATRIX4X4_SET_COLUMN2_V3"	},
	{	MATRIX4X4_SET_COLUMN3_V3,	"MATRIX4X4_SET_COLUMN3_V3"	},
	{	GRAPHICS4X4_CONSTRUCT_M3X3_V3,	"GRAPHICS4X4_CONSTRUCT_M3X3_V3"	},
	{	GRAPHICS4X4_CONSTRUCT_F,	"GRAPHICS4X4_CONSTRUCT_F"	},
	{	GRAPHICS4X4_ASSIGN_M3X3,	"GRAPHICS4X4_ASSIGN_M3X3"	},
	{	GRAPHICS4X4_SET_M3X3,	"GRAPHICS4X4_SET_M3X3"	},
	{	GRAPHICS4X4_DET_G4X4,	"GRAPHICS4X4_DET_G4X4"	},
	{	GRAPHICS4X4_DET,	"GRAPHICS4X4_DET"	},
	{	GRAPHICS4X4_COF_M4X4,	"GRAPHICS4X4_COF_M4X4"	},
	{	GRAPHICS4X4_ADJ_M4X4,	"GRAPHICS4X4_ADJ_M4X4"	},
	{	GRAPHICS4X4_INVERT,	"GRAPHICS4X4_INVERT"	},
	{	GRAPHICS4X4_EQUALS_G4X4,	"GRAPHICS4X4_EQUALS_G4X4"	},
	{	GRAPHICS4X4_NOT_EQUAL_G4X4,	"GRAPHICS4X4_NOT_EQUAL_G4X4"	},
	{	GRAPHICS4X4_FAST_MULTIPLY,	"GRAPHICS4X4_FAST_MULTIPLY"	},
	{	GRAPHICS4X4_TIMES_M4X4,	"GRAPHICS4X4_TIMES_M4X4"	},
	{	GRAPHICS4X4_TIMES_G4X4,	"GRAPHICS4X4_TIMES_G4X4"	},
	{	GRAPHICS4X4_TIMES_EQUALS_G4X4,	"GRAPHICS4X4_TIMES_EQUALS_G4X4"	},
	{	GRAPHICS4X4_DIVIDE_C4X4,	"GRAPHICS4X4_DIVIDE_C4X4"	},
	{	GRAPHICS4X4_DIVIDE_EQUALS_C4X4,	"GRAPHICS4X4_DIVIDE_EQUALS_C4X4"	},
	{	GRAPHICS4X4_TRANSFORM_F,	"GRAPHICS4X4_TRANSFORM_F"	},
	{	GRAPHICS4X4_SET_SCALE_F,	"GRAPHICS4X4_SET_SCALE_F"	},
	{	GRAPHICS4X4_SET_XSCALE_F,	"GRAPHICS4X4_SET_XSCALE_F"	},
	{	GRAPHICS4X4_SET_YSCALE_F,	"GRAPHICS4X4_SET_YSCALE_F"	},
	{	GRAPHICS4X4_SET_ZSCALE_F,	"GRAPHICS4X4_SET_ZSCALE_F"	},
	{	GRAPHICS4X4_SET_XROTATION_F,	"GRAPHICS4X4_SET_XROTATION_F"	},
	{	GRAPHICS4X4_SET_YROTATION_F,	"GRAPHICS4X4_SET_YROTATION_F"	},
	{	GRAPHICS4X4_SET_ZROTATION_F,	"GRAPHICS4X4_SET_ZROTATION_F"	},
	{	GRAPHICS4X4_SET_XYZROTATION_V3,	"GRAPHICS4X4_SET_XYZROTATION_V3"	},
	{	GRAPHICS4X4_SET_XYZROTATION_DEG_V3,	"GRAPHICS4X4_SET_XYZROTATION_DEG_V3"	},
	{	GRAPHICS4X4_SET_TRANSLATION_F,	"GRAPHICS4X4_SET_TRANSLATION_F"	},
	{	GRAPHICS4X4_SET_TRANSLATION_V3,	"GRAPHICS4X4_SET_TRANSLATION_V3"	},
	{	GRAPHICS4X4_SET_XTRANSLATION_F,	"GRAPHICS4X4_SET_XTRANSLATION_F"	},
	{	GRAPHICS4X4_SET_YTRANSLATION_F,	"GRAPHICS4X4_SET_YTRANSLATION_F"	},
	{	GRAPHICS4X4_SET_ZTRANSLATION_F,	"GRAPHICS4X4_SET_ZTRANSLATION_F"	},
	{	GRAPHICS4X4_POKE_TRANSLATION_F,	"GRAPHICS4X4_POKE_TRANSLATION_F"	},
	{	GRAPHICS4X4_POKE_TRANSLATION_V3,	"GRAPHICS4X4_POKE_TRANSLATION_V3"	},
	{	GRAPHICS4X4_POKE_XTRANSLATION_F,	"GRAPHICS4X4_POKE_XTRANSLATION_F"	},
	{	GRAPHICS4X4_POKE_YTRANSLATION_F,	"GRAPHICS4X4_POKE_YTRANSLATION_F"	},
	{	GRAPHICS4X4_POKE_ZTRANSLATION_F,	"GRAPHICS4X4_POKE_ZTRANSLATION_F"	},
	{	GRAPHICS4X4_CAT_SCALE_F,	"GRAPHICS4X4_CAT_SCALE_F"	},
	{	GRAPHICS4X4_CAT_XSCALE_F,	"GRAPHICS4X4_CAT_XSCALE_F"	},
	{	GRAPHICS4X4_CAT_YSCALE_F,	"GRAPHICS4X4_CAT_YSCALE_F"	},
	{	GRAPHICS4X4_CAT_ZSCALE_F,	"GRAPHICS4X4_CAT_ZSCALE_F"	},
	{	GRAPHICS4X4_CAT_XROTATION_F,	"GRAPHICS4X4_CAT_XROTATION_F"	},
	{	GRAPHICS4X4_CAT_YROTATION_F,	"GRAPHICS4X4_CAT_YROTATION_F"	},
	{	GRAPHICS4X4_CAT_ZROTATION_F,	"GRAPHICS4X4_CAT_ZROTATION_F"	},
	{	GRAPHICS4X4_CAT_TRANSLATION_F,	"GRAPHICS4X4_CAT_TRANSLATION_F"	},
	{	GRAPHICS4X4_CAT_XTRANSLATION_F,	"GRAPHICS4X4_CAT_XTRANSLATION_F"	},
	{	GRAPHICS4X4_CAT_YTRANSLATION_F,	"GRAPHICS4X4_CAT_YTRANSLATION_F"	},
	{	GRAPHICS4X4_CAT_ZTRANSLATION_F,	"GRAPHICS4X4_CAT_ZTRANSLATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_SCALE_F,	"GRAPHICS4X4_REVERSE_CAT_SCALE_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_XSCALE_F,	"GRAPHICS4X4_REVERSE_CAT_XSCALE_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_YSCALE_F,	"GRAPHICS4X4_REVERSE_CAT_YSCALE_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_ZSCALE_F,	"GRAPHICS4X4_REVERSE_CAT_ZSCALE_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_XROTATION_F,	"GRAPHICS4X4_REVERSE_CAT_XROTATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_YROTATION_F,	"GRAPHICS4X4_REVERSE_CAT_YROTATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_ZROTATION_F,	"GRAPHICS4X4_REVERSE_CAT_ZROTATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_TRANSLATION_F,	"GRAPHICS4X4_REVERSE_CAT_TRANSLATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_XTRANSLATION_F,	"GRAPHICS4X4_REVERSE_CAT_XTRANSLATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_YTRANSLATION_F,	"GRAPHICS4X4_REVERSE_CAT_YTRANSLATION_F"	},
	{	GRAPHICS4X4_REVERSE_CAT_ZTRANSLATION_F,	"GRAPHICS4X4_REVERSE_CAT_ZTRANSLATION_F"	},
	{	GRAPHICS4X4_GET_ORIENTATION_M3X3,	"GRAPHICS4X4_GET_ORIENTATION_M3X3"	},
	{	GRAPHICS4X4_POKE_ORIENTATION_M3X3,	"GRAPHICS4X4_POKE_ORIENTATION_M3X3"	},
	{	GRAPHICS4X4_COMPOSE_M3X3_V3,	"GRAPHICS4X4_COMPOSE_M3X3_V3"	},
	{	GRAPHICS4X4_DECOMPOSE_M3X3_V3,	"GRAPHICS4X4_DECOMPOSE_M3X3_V3"	},
	{	CARTESIAN4X4_CONSTRUCT_M3X3_V3,	"CARTESIAN4X4_CONSTRUCT_M3X3_V3"	},
	{	CARTESIAN4X4_INVERT,	"CARTESIAN4X4_INVERT"	},
	{	CARTESIAN4X4_INVERT_TIMES_M4X4,	"CARTESIAN4X4_INVERT_TIMES_M4X4"	},
	{	CARTESIAN4X4_INVERT_TIMES_G4X4,	"CARTESIAN4X4_INVERT_TIMES_G4X4"	},
	{	CARTESIAN4X4_INVERT_TIMES_EQUALS_C4X4,	"CARTESIAN4X4_INVERT_TIMES_EQUALS_C4X4"	},
	{	CARTESIAN4X4_INVERT_TIMES_M3X3,	"CARTESIAN4X4_INVERT_TIMES_M3X3"	},
	{	CARTESIAN4X4_INVERT_TIMES_EQUALS_D3X3,	"CARTESIAN4X4_INVERT_TIMES_EQUALS_D3X3"	},
	{	CARTESIAN4X4_INVERT_DIVIDE_C4X4,	"CARTESIAN4X4_INVERT_DIVIDE_C4X4"	},
	{	CARTESIAN4X4_INVERT_DIVIDE_EQUALS_C4X4,	"CARTESIAN4X4_INVERT_DIVIDE_EQUALS_C4X4"	},
	{	CARTESIAN4X4_INVERT_DIVIDE_D3X3,	"CARTESIAN4X4_INVERT_DIVIDE_D3X3"	},
	{	CARTESIAN4X4_INVERT_DIVIDE_EQUALS_D3X3,	"CARTESIAN4X4_INVERT_DIVIDE_EQUALS_D3X3"	},

	/* Mat4x4.cpp */

	{	MATRIX4X4_INVERT_M4X4,	"MATRIX4X4_INVERT_M4X4"	},
	{	GRAPHICS4X4_INVERT_M4X4,	"GRAPHICS4X4_INVERT_M4X4"	},
	{	CARTESIAN4X4_INVERT_M4X4,	"CARTESIAN4X4_INVERT_M4X4"	},
	{	GRAPHICS4X4_DECODE_TO_YXZ_V3,	"GRAPHICS4X4_DECODE_TO_YXZ_V3"	},
	{	GRAPHICS4X4_DECODE_TO_XZY_V3,	"GRAPHICS4X4_DECODE_TO_XZY_V3"	},
	{	GRAPHICS4X4_DECODE_TO_ZYX_V3,	"GRAPHICS4X4_DECODE_TO_ZYX_V3"	},
	{	GRAPHICS4X4_SET_INTERMEDIATE_F_G4X4,	"GRAPHICS4X4_SET_INTERMEDIATE_F_G4X4"	},
	{	GRAPHICS4X4_BUILD_FROM_QUAT_F,	"GRAPHICS4X4_BUILD_FROM_QUAT_F"	},
	{	GRAPHICS4X4_BUILD_FROM_VECTOR_V3,	"GRAPHICS4X4_BUILD_FROM_VECTOR_V3"	},
	{	MATRIX4X4_DECONSTRUCT,	"MATRIX4X4_DECONSTRUCT"	},
	{	GRAPHICS4X4_DECONSTRUCT,	"GRAPHICS4X4_DECONSTRUCT"	},
	{	GRAPHICS4X4_TRANSFORM_ARRAY_V3_V3_I,	"GRAPHICS4X4_TRANSFORM_ARRAY_V3_V3_I"	},
	{	GRAPHICS4X4_TRANSFORM_ARRAY_V4_V4_I,	"GRAPHICS4X4_TRANSFORM_ARRAY_V4_V4_I"	},
	{	GRAPHICS4X4_BASIS_TRANSFORM_ARRAY_V3_V3_I,	"GRAPHICS4X4_BASIS_TRANSFORM_ARRAY_V3_V3_I"	},
	{	GRAPHICS4X4_BASIS_TRANSFORM_ARRAY_V4_V4_I,	"GRAPHICS4X4_BASIS_TRANSFORM_ARRAY_V4_V4_I"	},

	/* miscellaneous matrix routines from Matrix.hpp */

	{	F_TIMES_MATRIX3X3,	"F_TIMES_MATRIX3X3"	},
	{	F_TIMES_MATRIX4X4,	"F_TIMES_MATRIX4X4"	},

	/* must be last */

	{	-1,	"Not found"}
};

/* simple routines */

void MathStats__Clear(void)
{
	memset(nMathStats, 0, MATH_STATS_COUNT * sizeof(int));
}

void MathStats__Report(void)
{
#ifdef WIN32
	static int nFileCount = 0;
	char FileName[100];
	sprintf(FileName, "c:\\temp\\MathStats%d.log", nFileCount++);	// make it easy to capture multiple snapshots
	FILE *pFile = fopen(FileName, "wt");
	if (pFile == NULL)
	{
		ASSERT(FALSE);	// file name is hard-coded-- you may have to change it
		return;
	}

	/* find highest entry in name list */

	int nHighIndex = 0;
	while (MathStatsName[nHighIndex].nIndex != -1)
		nHighIndex++;

	/* report stat for each math routine */

	for (int i = 0; i < MATH_STATS_COUNT; i++)
	{
		/* find name in pairing list-- likely to be near index... */

		char *pName = NULL;
		if (MathStatsName[i].nIndex == i)
			pName = MathStatsName[i].pName;
		else
		{
			/* look a bit on both sides of index */

			int j = i - 10;
			if (j < 0)
				j = 0;
			if (j >= nHighIndex)
				j = nHighIndex - 1;
			while ((j < i + 10) && (MathStatsName[j].nIndex != -1) && (MathStatsName[j].nIndex != i))
				j++;
			if (MathStatsName[j].nIndex == i)
				pName = MathStatsName[j].pName;
			else
			{
				/* search the whole list */

				j = 0;
				while ((MathStatsName[j].nIndex != -1) && (MathStatsName[j].nIndex != i))
					j++;
				ASSERT(MathStatsName[j].nIndex != -1);	// add the new math routine to the name list!
				pName = MathStatsName[j].pName;	// either the correct name or "not found" at end of list
			}
		}

		/* write out stat */

		fprintf(pFile, "%08d\t%s\n", nMathStats[i], pName);
	}
#endif //WIN32
}
#endif //MATH_STATS


