#ifndef __TUPLE_H__
#define __TUPLE_H__

#ifdef USE_SSE
#include <xmmintrin.h>
#endif

#include "public.h"

namespace xrt
{
	class Color;
	class PUBLIC Tuple
	{
	public:
		union
		{
			struct
			{
				float x, y, z, w;
			};
			float t[4];
#ifdef USE_SSE
			__m128 tuple;
#endif
		};
//	Constructors
		Tuple() {}
		Tuple( float );
		Tuple( float, float, float );
		Tuple( float, float, float, float );
		Tuple( const float * );
		Tuple( const Color& );
#ifdef USE_SSE
		Tuple( __m128 t ) { tuple = t; }
		Tuple ( const Tuple &t ) { tuple = t.tuple; }
#else
		Tuple( const Tuple &t );
#endif
//	Operators
		EXPORT friend Tuple operator+( const Tuple &, const Tuple & );
		EXPORT friend Tuple operator+( const Tuple &, const float );
		Tuple &operator+=( const Tuple & );
		EXPORT friend Tuple operator-( const Tuple &, const Tuple & );
		EXPORT friend Tuple operator-( const Tuple & );
		EXPORT friend Tuple operator-( const Tuple &, const float );
		Tuple &operator-=( const Tuple & );
		EXPORT friend Tuple operator*( const Tuple &, const float );
		EXPORT friend Tuple operator*( const float f, const Tuple &t ) { return t * f; }
		Tuple& operator*=( const float );
		Tuple& operator*=( const Tuple & );
		EXPORT friend Tuple operator*( const Tuple &, const Tuple & );
		EXPORT friend Tuple operator/( const Tuple &, const float );
		EXPORT friend Tuple operator/( const float, const Tuple & );
		EXPORT friend Tuple operator/( const Tuple &, const Tuple & );
		Tuple& operator/=( const float );
		EXPORT friend Tuple operator^( const Tuple &, const Tuple & );
		EXPORT friend bool operator!=( const Tuple &, const Tuple & );
		float operator[] (int i) const { return t[i]; }
		float &operator[] (int i) { return t[i]; }
		inline Tuple &operator=( const Tuple & );
		inline Tuple &operator=( float );
		EXPORT friend bool operator==( const Tuple &, const Tuple & );
		EXPORT friend bool operator!=( const Tuple &, const Tuple & );
	// Others
		float length( void ) const;
		float length2( void ) const;
		EXPORT friend float dot( const Tuple&, const Tuple& );
		Tuple hat( void ) { return *this / length(); }
		void normalize( void ) { *this /= length(); }
		void coordinateSystem( Tuple &v, Tuple &w );
		unsigned int largestAxis() const;
		void sortAxis( int sorted[3] ) const;
	};
};

#endif // __TUPLE_H__
