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

		InlineMath.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Revision History

		when		who			what & why
		==========	==========	======================================================
		9/24/97		Alec		made InlineVectorMatrixMultiply() into macro, eliminated
									math headers from file
		4/7/97		kevin		added InlineVectorMatrixMultiply()
		2/11/97		Alec		macroLerp has interpolant last, added scalar operations
		12/18/96	Alec		new today - repository for math macros/inlines
									
*****************************************************************************************/

#ifndef	H_INLINEMATH
#define	H_INLINEMATH

#pragma once

// This is a collection of useful math macros and inlines pertinant to a wide variety
// of applications.  Added calls should be small.  Please denote const macro
// parameters with 'k'.

// rapidly find the absolute value of a signed number
#define macroAbsoluteValue( x ) \
		(((x) < 0) ? -(x) : (x))

// round a to nearest int, you must include <math.h> to use this macro
#define macroRoundedValue(a) \
		floor((a)+0.5)

// take sign of a, either -1, 0, or 1
#define macroSignOfValue(a)	\
		(((a)<0) ? -1 : (a)>0 ? 1 : 0)

// square a
#define macroSquaredValue(a) \
		((a)*(a))

// linear interpolation betwen kStart(when kInterpolant=0) to kEnd(when kInterpolant=1)
#define macroLerp(kStart,kEnd,kInterpolant) \
		((kStart)+(((kEnd)-(kStart))*(kInterpolant)))


// ------------------


// a collection of general math operation macros use as follows
// macroVector3Op1( vec3_1, +=, vec3_2 );
// macroVector3Op3Scalar( vec3_1, =, vec3_2, +, vec3_3, *, 10.0 );

// for vector2
#define macroVector2Op1( v1, op1, v2 )	\
		{								\
			v1.x op1 v2.x;				\
			v1.y op1 v2.y;				\
		}
#define macroVector2Op2( v1, op1, v2, op2, v3 )	\
		{										\
			v1.x op1 v2.x op2 v3.x;				\
			v1.y op1 v2.y op2 v3.y;				\
		}

#define macroVector2Op2Scalar( v1, op1, v2, op2, kScalar )	\
		{													\
			v1.x op1 v2.x op2 kScalar;						\
			v1.y op1 v2.y op2 kScalar;						\
		}
		
#define macroVector2Op3Scalar( v1, op1, v2, op2, v3, op3, kScalar )	\
		{															\
			v1.x op1 v2.x op2 v3.x op3 kScalar;						\
			v1.y op1 v2.y op2 v3.y op3 kScalar;						\
		}

// for vector3
#define macroVector3Op1( v1, op1, v2 ) 	\
		{								\
			v1.x op1 v2.x;				\
			v1.y op1 v2.y;				\
			v1.z op1 v2.z;				\
		}
#define macroVector3Op2( v1, op1, v2, op2, v3 )	\
		{										\
			v1.x op1 v2.x op2 v3.x;				\
			v1.y op1 v2.y op2 v3.y;				\
			v1.z op1 v2.z op2 v3.z;				\
		}

#define macroVector3Op2Scalar( v1, op1, v2, op2, kScalar )	\
		{													\
			v1.x op1 v2.x op2 kScalar;						\
			v1.y op1 v2.y op2 kScalar;						\
			v1.z op1 v2.z op2 kScalar;						\
		}

#define macroVector3Op3Scalar( v1, op1, v2, op2, v3, op3, kScalar )	\
		{															\
			v1.x op1 v2.x op2 v3.x op3 kScalar;						\
			v1.y op1 v2.y op2 v3.y op3 kScalar;						\
			v1.z op1 v2.z op2 v3.z op3 kScalar;						\
		}

// for vector4		
#define macroVector4Op1( v1, op1, v2 )	\
		{								\
			v1.x op1 v2.x;				\
			v1.y op1 v2.y;				\
			v1.z op1 v2.z;				\
			v1.w op1 v2.w;				\
		}
#define macroVector4Op2( v1, op1, v2, op2, v3 ) \
		{										\
			v1.x op1 v2.x op2 v3.x;				\
			v1.y op1 v2.y op2 v3.y;				\
			v1.z op1 v2.z op2 v3.z;				\
			v1.w op1 v2.w op2 v3.w;				\
		}

#define macroVector4Op2Scalar( v1, op1, v2, op2, kScalar ) \
		{										\
			v1.x op1 v2.x op2 kScalar;			\
			v1.y op1 v2.y op2 kScalar;			\
			v1.z op1 v2.z op2 kScalar;			\
			v1.w op1 v2.w op2 kScalar;			\
		}

#define macroVector4Op3Scalar( v1, op1, v2, op2, v3, op3, kScalar ) \
		{															\
			v1.x op1 v2.x op2 v3.x op3 kScalar;						\
			v1.y op1 v2.y op2 v3.y op3 kScalar;						\
			v1.z op1 v2.z op2 v3.z op3 kScalar;						\
			v1.w op1 v2.w op2 v3.w op3 kScalar;						\
		}

// ------------------


// caller must insure that v and result are not the same to use this
#define macroMultiplyVector4ByAffineRowTfm( kV, kM, result )									\
	{ 																						\
		(result).x = (kV)(0)*kM(0,0) + (kV)(1)*kM(1,0) + (kV)(2)*kM(2,0) + (kV)(3)*kM(3,0);	\
		(result).y = (kV)(0)*kM(0,1) + (kV)(1)*kM(1,1) + (kV)(2)*kM(2,1) + (kV)(3)*kM(3,1);	\
		(result).z = (kV)(0)*kM(0,2) + (kV)(1)*kM(1,2) + (kV)(2)*kM(2,2) + (kV)(3)*kM(3,2);	\
		(result).w = (kV)(0)*kM(0,3) + (kV)(1)*kM(1,3) + (kV)(2)*kM(2,3) + (kV)(3)*kM(3,3);	\
	}

		
#endif // H_INLINEMATH