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

		VectorN.h

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

		Vector Math Library, Release 2.0,  1/1/96 
		Copyright 1996 Alec Miller, All Rights Reserved 

		Revision History

		when		who			what & why
		==========	==========	======================================================
		5/21/98		Greg		Fixed double to float warning (again?)
		5/18/98		Joshua		Fixed double to float warning and added binary minus 
								(like TVector2, etc.)
		12/8/97		Ian			Removed iostream stuff altogether it's not compatible with
								Windows or MSL.
		5/15/96		Alec		new today - added vector math library to InfiniD project

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

#ifndef H_VECTORN
#define H_VECTORN

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"

/// \addtogroup Math
/// \{

/// Defines an N dimensional floating point vector.
///
template<class T> class TVectorN: public TMCObject
{
public:
			TVectorN			(void);
			TVectorN			(const uint32 vectorDimension);  // exceptional
			TVectorN			(const TVectorN& v);			 // exceptional
	
	// dynamically grow the vector
	void	SetDimension		(const uint32 vectorDimension);	 // exceptional
	
	// destruction
			~TVectorN			(void);
	void	ReleaseStorage		(void); // eliminates all storage (dimension set to 0)
	


	// current vector dimension access		
	inline		 uint32		GetDimension	(void) const;
	
	// element access using () and [] notation
	inline const T&		operator()			(const uint32 valueNum) const;  // exceptional
	inline		 T&      operator()			(const uint32 valueNum);		// exceptional

	inline const T&		operator[]			(const uint32 valueNum) const;  // exceptional
	inline		 T&      operator[]			(const uint32 valueNum);		// exceptional
	
	// convenience functions to create zero out vectors
				 void		SetValuesToZero		(void);
	
	// vector properties
				 T		GetMagnitude		(void) const;
				 T		GetMagnitudeSquared	(void) const;
				
				 boolean	Normalize			(const real zeroTolerance = 0.0f);

				 boolean	IsEqual				(const TVectorN& compareVec, const real	zeroTolerance = 0.0f ) const;
	
				 void		Negate				(void);
			
	// copy and fast vector operations
				 TVectorN&	operator=			(const TVectorN& v);			// exceptional
				 TVectorN&	operator+=			(const TVectorN& v);			// exceptional
				 TVectorN&	operator-=			(const TVectorN& v);			// exceptional
				 TVectorN&	operator*=			(const T scalar);
				 TVectorN&	operator/=			(const T scalar);
	


public:
	// this is deprecated funtionality from RealVectorN, don't use these
	// in new code.  Use the equivalents directly.
	inline	real GetNorm () const 	{ return GetMagnitude(); }
	inline void Reset    ()			{ SetValuesToZero(); }
	
private:
	uint32 originalDimension;	
	uint32 currentDimension;
	
	T* value;
};

/// \}




// [operator definitions] --------------------------------------------------------------//


template <class T> inline boolean	operator==	(const TVectorN<T>& lhs, const TVectorN<T>& rhs)
	{ return lhs.IsEqual( rhs ); }

template <class T> inline boolean	operator!=	(const TVectorN<T>& lhs, const TVectorN<T>& rhs)
	{ return ! lhs.IsEqual( rhs ); }



// dot product
template <class T> real				operator*	(const TVectorN<T>& v1, const TVectorN<T>& v2);  // exceptional




// [inline implementation] -------------------------------------------------------------//

template <class T> inline const T& TVectorN<T>::operator()		(const uint32 valueNum) const 
	{ return value[valueNum]; }

template <class T> inline		 T& TVectorN<T>::operator()		(const uint32 valueNum)
	{ return value[valueNum]; }

template <class T> inline const T& TVectorN<T>::operator[]		(const uint32 valueNum) const
	{ MCAssert(valueNum<currentDimension); return value[valueNum]; }
	
template <class T> inline		 T& TVectorN<T>::operator[]		(const uint32 valueNum)
	{ MCAssert(valueNum<currentDimension); return value[valueNum]; }
		
template <class T> inline uint32 TVectorN<T>::GetDimension		(void) const
	{ return currentDimension; }
	
template <class T> inline		  TVectorN<T> operator-			(const TVectorN<T>& a, const TVectorN<T>& b)
	{ return (TVectorN<T>(a) -= b); }

#endif /* H_VECTORN */