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


		MCMath.h


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


		Author:	Sree
		Date:	12/15/97

		Revision History

		when		who			what & why
		==========	==========	======================================================

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

#ifndef __MCMath__
#define __MCMath__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"

// =================================================================================================================
// Math Macros / Constants / Misc Functions
// =================================================================================================================

const int32		_L0						= 0;						//faster loading from memory to register for compares
const int32		_L1						= 1;	
const int32		_L2						= 2;	
const int32		_LNeg					= -1;	
const real32	_0						= (real32)(0.0);
const real32	_1						= (real32)(1.0);
const int32		_shiftamt				= 16;						//16.16 fixed point representation,
																	//only used for adding and shifting,
																	//(no muls or divs)

const int32		_byteshift				= _shiftamt - 8;			//reduce shift so the 0-1 = 0-255										
const int32		_fixhalf				= (_L1<<(_shiftamt-_L1));	//.5
const int32		_int2fix				= (_L1<<_shiftamt);			//(1<<shiftAmt)
const int32		_fixunder1				= _int2fix - 1;				//(just under one - useful for ceil
const int32		_fixover1				= ~_fixunder1;				//inverse of mask above
const real32	_real2fix				= (real32)_int2fix;			//(1<<shiftAmt)
const real32	_fix2real				= _1/_real2fix;				//1.0/(1<<shiftAmt)

#define			ceilfix(a)				((a+_fixunder1)&_fixover1)
#define			floorfix(a)				((a)&_fixover1)
#define			ceilfix2int(a)			((a+_fixunder1)>>_shiftamt)
#define			floorfix2int(a)			((a)>>_shiftamt)

#define			MC_Clamp(val,a,b)		(MC_Min (MC_Max (val,a), b))
#define			MC_AbsL(a)				((a)<_L0?(-(a)):(a))		//absolute long value
#define			MC_AbsF(a)				((a)<_0?(-(a)):(a))			//absolute float value
#define			MC_SgnL(a)				((a)<_L0?(-(a)):(a))		//sign of long
#define			MC_SgnF(a)				((a)<_0?(-(a)):(a))			//sign of float
#define			MC_Between(val,b,c)		((val>=b)&&(val<c))			//val is between a and b [...val...)?



// =================================================================================================================
// Min and Max
// =================================================================================================================

// __________ You will NEVER have to write another "min/max" procedure for the rest of your life! d:))

// Expressions passed as arguments to inline functions are evaluated once. In some cases, expressions
// passed as arguments to macros can be evaluated more than once. Therefore, we use inlines for the following.

inline int8			MC_Max	(int8	a,	int8	b)					{ return a > b ? a : b;	}
inline uint8		MC_Max	(uint8	a,	uint8	b)					{ return a > b ? a : b;	}
inline int16		MC_Max	(int16	a,	int16	b)					{ return a > b ? a : b;	}
inline uint16		MC_Max	(uint16	a,	uint16	b)					{ return a > b ? a : b;	}
inline int32		MC_Max	(int32	a,	int32	b)					{ return a > b ? a : b;	}
inline uint32		MC_Max	(uint32	a,	uint32	b)					{ return a > b ? a : b;	}
inline real32		MC_Max	(real32	a,	real32	b)					{ return a > b ? a : b;	}
inline real64		MC_Max	(real64	a,	real64	b)					{ return a > b ? a : b;	}

inline int8			MC_Min	(int8	a,	int8	b)					{ return a < b ? a : b;	}
inline uint8		MC_Min	(uint8	a,	uint8	b)					{ return a < b ? a : b;	}
inline int16		MC_Min	(int16	a,	int16	b)					{ return a < b ? a : b;	}
inline uint16		MC_Min	(uint16	a,	uint16	b)					{ return a < b ? a : b;	}
inline int32		MC_Min	(int32	a,	int32	b)					{ return a < b ? a : b;	}
inline uint32		MC_Min	(uint32	a,	uint32	b)					{ return a < b ? a : b;	}
inline real32		MC_Min	(real32	a,	real32	b)					{ return a < b ? a : b;	}
inline real64		MC_Min	(real64	a,	real64	b)					{ return a < b ? a : b;	}

inline int8			MC_Max	(int8	a,	int8	b,	int8	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline int8			MC_Min	(int8	a,	int8	b,	int8	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline uint8		MC_Max	(uint8	a,	uint8	b,	uint8	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline uint8		MC_Min	(uint8	a,	uint8	b,	uint8	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline int16		MC_Max	(int16	a,	int16	b,	int16	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline int16		MC_Min	(int16	a,	int16	b,	int16	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline uint16		MC_Max	(uint16	a,	uint16	b,	uint16	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline uint16		MC_Min	(uint16	a,	uint16	b,	uint16	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline int32		MC_Max	(int32	a,	int32	b,	int32	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline int32		MC_Min	(int32	a,	int32	b,	int32	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline uint32		MC_Max	(uint32	a,	uint32	b,	uint32	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline uint32		MC_Min	(uint32	a,	uint32	b,	uint32	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline real32		MC_Max	(real32	a,	real32	b,	real32	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline real32		MC_Min	(real32	a,	real32	b,	real32	c)		{ return MC_Min	(MC_Min	(a, b), c); }
inline real64		MC_Max	(real64	a,	real64	b,	real64	c)		{ return MC_Max	(MC_Max	(a, b), c); }
inline real64		MC_Min	(real64	a,	real64	b,	real64	c)		{ return MC_Min	(MC_Min	(a, b), c); }

#endif