 #ifndef __M_VECTOR3_H__
 #define __M_VECTOR3_H__

#include "maths_defs.h"

/// Classe Vector
/// Elle permet de manipuler les vecteurs en tant que types.
 class Vector
 {
 public:

   float x;	//< la première composante 
   float y;
   float z;

 public:

   Vector ()	 : x(0), y(0), z(0)												{}; //< nos oncstructeurs ... avec différentes méthodes de construction
   Vector (float m) : x(m), y(m), z(m)									{};
   Vector (float ix, float iy, float iz = 0) : x(ix), y(iy), z(iz)	{};
   Vector (const Vector& v) : x(v.x), y(v.y), z(v.z)				{};

	
   void Init() 
   {
	   x = 0, y = 0, z = 0;
   }


   inline friend Vector operator+ (const Vector& v1, const Vector& v2)
   {
		return Vector(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); 
   }

   inline friend Vector operator- (const Vector& v1, const Vector& v2)
   { 
	   return Vector(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z);
   }

   inline friend float operator* (const Vector& v1, const Vector& v2)
   { 
	   return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; 
   }

   inline friend Vector operator% (const Vector& v1, const Vector& v2)
   {
     return Vector (v1.y*v2.z-v1.z*v2.y,
                          v1.z*v2.x-v1.x*v2.z,
                          v1.x*v2.y-v1.y*v2.x);
   }
 
   void Cross (const Vector & px, const Vector & py);
 
   inline  friend Vector operator* (const Vector& v, float f)
   { 
	   return Vector(v.x*f, v.y*f, v.z*f);
   }

   inline  friend Vector operator* (float f, const Vector& v)
   { 
	   return Vector(v.x*f, v.y*f, v.z*f); 
   }

   inline  friend Vector operator* (const Vector& v, double f)
   { 
	   return Vector(v) * f; 
   }

   inline  friend Vector operator* (double f, const Vector& v)
   { 
	   return Vector(v) * f; 
   }
   inline  friend Vector operator* (const Vector& v, int f)
   { 
	   return v * (float)f; 
   }

   inline  friend Vector operator* (int f, const Vector& v)
   { 
	   return v * (float)f; 
   }

   inline  friend Vector operator/ (const Vector& v, float f)
   { 
	   f = 1.0f/f; 
	   return Vector(v.x*f, v.y*f, v.z*f); 
   }

   inline  friend Vector operator/ (const Vector& v, double f)
   { 
	   return Vector(v) / f;
   }
   inline  friend Vector operator/ (const Vector& v, int f)
   { 
	   return v / (float)f; 
   }

   inline  friend bool operator== (const Vector& v1, const Vector& v2)
   { 
	   return v1.x==v2.x && v1.y==v2.y && v1.z==v2.z; 
   }

   inline  friend bool operator!= (const Vector& v1, const Vector& v2)
   { 
	   return v1.x!=v2.x || v1.y!=v2.y || v1.z!=v2.z; 
   }

   inline friend Vector operator>> (const Vector& v1, const Vector& v2)
   { 
	   return v2*(v1*v2)/(v2*v2); 
   }

   inline friend Vector operator<< (const Vector& v1, const Vector& v2)
   { 
	   return v1*(v1*v2)/(v1*v1); 
   }

   inline friend bool operator< (const Vector& v, float f)
   { 
	   return ABS(v.x)<f && ABS(v.y)<f && ABS(v.z)<f; 
   }

   inline  friend bool operator> (float f, const Vector& v)
   { 
	   return ABS(v.x)<f && ABS(v.y)<f && ABS(v.z)<f; 
   }
 
   inline float operator[] (int n) const { return !n?x:n&1?y:z; }

   inline float & operator[] (int n) 
   { 
	   //return !n?x:n&1?y:z; 
		return *((&(x) + n));
   }
 
   inline Vector& operator+= (const Vector& v)
   {
     x += v.x;
     y += v.y;
     z += v.z;
     return *this;
   }

   inline Vector& operator-= (const Vector& v)
   {
     x -= v.x;
     y -= v.y;
     z -= v.z;
     return *this;
   }

   inline Vector& operator*= (float f)
   { 
	   x *= f; 
	   y *= f; 
	   z *= f; 
	   return *this; 
   }

   inline Vector& operator/= (float f)
   { 
	   f = 1.0f / f; 
	   x *= f; 
	   y *= f; 
	   z *= f; 
	   return *this; 
   }

   inline  Vector operator+ () const { return *this; }
   inline  Vector operator- () const { return Vector(-x,-y,-z); }

   inline void Set (float sx, float sy, float sz) { x = sx; y = sy; z = sz; }
   inline void Set (const Vector& v) { x = v.x; y = v.y; z = v.z; }

   float Norm () const
   {
	   float f = x * x + y * y + z * z;
	   __asm
	   {
        movss   xmm0, f
        sqrtss   xmm0, xmm0
		movss   f, xmm0
	   }
	   return f;
   }
   float SquaredNorm () const
   { 
	   return x * x + y * y + z * z; 
   }
   Vector Unit () const { return (*this)/(this->Norm()); }
   inline static float    Norm (const Vector& v) { return v.Norm(); }
   inline static Vector Unit   (const Vector& v) { return v.Unit();   }

   void Normalize ();

   inline bool IsZero (float precision) const;

	void out() const;


 };
 
 #endif 
