//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: vect.inl
//      Краткое описание: классы Vect2, Vect3, Vect4
//

namespace math
{
	// Vect2 class

	inline Vect2::Vect2()
	{
		
	};

	inline Vect2::Vect2(const Vect2& v)
	{
		x = v.x;
		y = v.y;
	};

	inline Vect2::Vect2(float x, float y)
	{
		this->x = x;
		this->y = y;
	};

	inline Vect2::Vect2(const float* xy)
	{
		x = xy[0];
		y = xy[1];
	};

	inline Vect2::Vect2(const Vect3& v)
	{
		x = v.x;
		y = v.y;
	};

	inline Vect2::Vect2(const Vect4& v)
	{
		x = v.x;
		y = v.y;
	};

	inline Vect2::~Vect2()
	{

	};

	inline Vect2& Vect2::operator=(const Vect2& v)
	{
		x = v.x;
		y = v.y;
		return *this;
	};

	inline const float Vect2::operator [](const unsigned int i) const
	{
		return mas[i];
	};

	inline float& Vect2::operator [](const unsigned int i)
	{
		return mas[i];
	};

	inline Vect2 Vect2::operator +(const Vect2& v) const
	{
		return Vect2(x + v.x, y + v.y);
	};

	inline const Vect2& Vect2::operator +=(const Vect2& v)
	{
		x += v.x;
		y += v.y;
		return *this;
	};

	inline Vect2 Vect2::operator -(const Vect2& v) const
	{
		return Vect2(x - v.x, y - v.y);
	};

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

	inline Vect2 Vect2::operator *(const float f) const
	{
		return Vect2(x*f, y*f);
	};

	inline const Vect2& Vect2::operator *=(const float f)
	{
		x *= f;
		y *= f;
		return *this;
	};

	inline Vect2 Vect2::operator /(const float f) const
	{
		float f0 = 1/f;
		return Vect2(x*f0, y*f0);
	};

	inline const Vect2& Vect2::operator /=(const float f)
	{
		float f0 = 1/f;
		x *= f0;
		y *= f0;
		return *this;
	};

	inline Vect2 Vect2::operator -() const
	{
		return Vect2(-x, -y);
	};

	inline bool Vect2::operator ==(const Vect2& v1) const
	{
		return (float_equal(x, v1.x) && float_equal(y, v1.y));
	};

	inline bool Vect2::operator !=(const Vect2& v1) const
	{
		return (float_notequal(x, v1.x) || float_notequal(y, v1.y));
	};

	inline float Vect2::length() const
	{
		return sqrt(x*x + y*y);
	};

	inline float Vect2::sqLength() const
	{
		return x*x + y*y;
	};

	inline const Vect2& Vect2::normalize()
	{
		float l = 1/length();
		x *= l;
		y *= l;
		return *this;
	};

	inline Vect2 Vect2::getNormalize() const
	{
		float l = 1/length();
		return Vect2(x*l, y*l);
	};

	// class Vect3

	inline Vect3::Vect3()
	{

	};

	inline Vect3::Vect3(const Vect3& v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
	};

	inline Vect3::Vect3(float x, float y, float z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	};

	inline Vect3::Vect3(const float* xyz)
	{
		x = xyz[0];
		y = xyz[1];
		z = xyz[2];
	};

	inline Vect3::Vect3(const Vect2& v)
	{
		x = v.x;
		y = v.y;
		z = 0;
	};

	inline Vect3::Vect3(const Vect4& v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
	};

	inline Vect3::Vect3(const float val)
	{
		x = val;
		y = 0;
		z = 0;
	};

	inline Vect3::~Vect3()
	{

	};

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

	inline const float Vect3::operator [](const unsigned int i) const
	{
		return mas[i];
	};

	inline float& Vect3::operator [](const unsigned int i)
	{
		return mas[i];
	};

	inline Vect3 Vect3::operator +(const Vect3& v) const
	{
		return Vect3(x + v.x, y + v.y, z + v.z);
	};

	inline const Vect3& Vect3::operator +=(const Vect3& v)
	{
		x += v.x;
		y += v.y;
		z += v.z;
		return *this;
	};

	inline Vect3 Vect3::operator -(const Vect3& v) const
	{
		return Vect3(x - v.x, y - v.y, z - v.z);
	};

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

	inline Vect3 Vect3::operator *(const float f) const
	{
		return Vect3(x*f, y*f, z*f);
	};

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

	inline Vect3 Vect3::operator /(const float f) const
	{
		float f0 = 1/f;
		return Vect3(x*f0, y*f0, z*f0);
	};

	inline const Vect3& Vect3::operator /=(const float f)
	{
		float f0 = 1/f;
		x *= f0;
		y *= f0;
		z *= f0;
		return *this;
	};

	inline Vect3 Vect3::operator -() const
	{
		return Vect3(-x, -y, -z);
	};

	inline bool Vect3::operator ==(const Vect3& v) const
	{
		return (float_equal(x, v.x) && float_equal(y, v.y) && float_equal(z, v.z));
	};

	inline bool Vect3::operator !=(const Vect3& v) const
	{
		return (float_notequal(x, v.x) || float_notequal(y, v.y) || float_notequal(z, v.z));
	};

	inline float Vect3::length() const
	{
		return sqrt(x*x + y*y + z*z);
	};

	inline float Vect3::sqLength() const
	{
		return x*x + y*y + z*z;
	};

	inline const Vect3& Vect3::normalize() 
	{
		float l = 1/length();
		x *= l;
		y *= l;
		z *= l;
		return *this;
	};

	inline Vect3 Vect3::getNormalize() const
	{
		float l = 1/length();
		return Vect3(x*l, y*l, z*l);
	};

	// class Vect4

	inline Vect4::Vect4()
	{

	};

	inline Vect4::Vect4(const Vect4& v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
		w = v.w;
	};

	inline Vect4::Vect4(const float x, const float y, const float z, const float w)
	{
		this->x = x;
		this->y = y;
		this->z = z;
		this->w = w;
	};

	inline Vect4::Vect4(const float* xyzw)
	{
		x = xyzw[0];
		y = xyzw[1];
		z = xyzw[2];
		w = xyzw[3];
	};

	inline Vect4::Vect4(const Vect2& v)
	{
		x = v.x;
		y = v.y;
		z = 0;
		w = 1;
	};

	inline Vect4::Vect4(const Vect3& v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
		w = 1;
	};

	inline Vect4::Vect4(const float val)
	{
		x = val;
		y = 0;
		z = 0;
		w = 1;
	};

	inline Vect4::~Vect4()
	{

	};

	inline Vect4& Vect4::operator =(const Vect4& v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
		w = v.w;
		return *this;
	};

	inline const float Vect4::operator [](const unsigned int i) const
	{
		return mas[i];
	};

	inline float& Vect4::operator [](const unsigned int i)
	{
		return mas[i];
	};

	inline Vect4 Vect4::operator +(const Vect4& v) const
	{
		return Vect4(x + v.x, y + v.y, z + v.z, w + v.w);
	};

	inline const Vect4& Vect4::operator +=(const Vect4& v)
	{
		x += v.x;
		y += v.y;
		z += v.z;
		w += v.w;
		return *this;
	};

	inline Vect4 Vect4::operator -(const Vect4& v) const
	{
		return Vect4(x - v.x, y - v.y, z - v.z, w - v.w);
	};

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

	inline Vect4 Vect4::operator *(const float f) const
	{
		return Vect4(x*f, y*f, z*f, w*f);
	};

	inline const Vect4& Vect4::operator *=(const float f)
	{
		x *= f;
		y *= f;
		z *= f;
		w *= f;
		return *this;
	};

	inline Vect4 Vect4::operator /(const float f) const
	{
		float f0 = 1/f;
		return Vect4(x*f0, y*f0, z*f0, w*f0);
	};

	inline const Vect4& Vect4::operator /=(const float f)
	{
		float f0 = 1/f;
		x *= f0;
		y *= f0;
		z *= f0;
		w *= f0;
		return *this;
	};

	inline Vect4 Vect4::operator -() const
	{
		return Vect4(-x, -y, -z, -w);
	};

	inline bool Vect4::operator ==(const Vect4& v) const
	{
		return (float_equal(x, v.x) && float_equal(y, v.y) && float_equal(z, v.z) && float_equal(w, v.w));
	};

	inline bool Vect4::operator !=(const Vect4& v) const
	{
		return (float_notequal(x, v.x) || float_notequal(y, v.y) || float_notequal(z, v.z) || float_notequal(w, v.w));
	};

	inline float Vect4::length() const
	{
		return sqrt(x*x + y*y + z*z + w*w);
	};

	inline float Vect4::sqLength() const
	{
		return x*x + y*y + z*z + w*w;
	};

	inline const Vect4& Vect4::normalize()
	{
		float l = 1/length();
		x *= l;
		y *= l;
		z *= l;
		w *= l;
		return *this;
	};

	inline Vect4 Vect4::getNormalize() const
	{
		float l = 1/length();
		return Vect4(x*l, y*l, z*l, w*l);
	};

	// Addition function

	inline float dot(const Vect2& v1, const Vect2& v2)
	{
		return v1.x*v2.x + v1.y*v2.y;
	};

	inline float dot(const Vect3& v1, const Vect3& v2)
	{
		return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
	};

	inline float dot(const Vect4& v1, const Vect4& v2)
	{
		return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w;
	};

	inline Vect3 cross(const Vect3& v1, const Vect3& v2)
	{
		return Vect3(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
	};

	inline float distance(const Vect2& v1, const Vect2& v2)
	{
		return (v1-v2).length();
	};

	inline float distance(const Vect3& v1, const Vect3& v2)
	{
		return (v1-v2).length();
	};

	inline float distance(const Vect4& v1, const Vect4& v2)
	{
		return (v1-v2).length();
	};

	inline float sqDistance(const Vect2& v1, const Vect2& v2)
	{
		return (v1-v2).sqLength();
	};

	inline float sqDistance(const Vect3& v1, const Vect3& v2)
	{
		return (v1-v2).sqLength();
	};

	inline float sqDistance(const Vect4& v1, const Vect4& v2)
	{
		return (v1-v2).sqLength();

	};

	inline std::ostream& operator<<(std::ostream& os, const Vect2& v)
	{
		os << "(" << v.x << "," << v.y << ")";
		return os;
	};

	inline std::ostream& operator<<(std::ostream& os, const Vect3& v)
	{
		os << "(" << v.x << "," << v.y << "," << v.z << ")";
		return os;
	};

	inline std::ostream& operator<<(std::ostream& os, const Vect4& v)
	{
		os << "(" << v.x << "," << v.y << "," << v.z << "," << v.w << ")";
		return os;
	};

	inline std::istream& operator>>(std::istream& is, Vect2& v)
	{
		is >> v.x >> v.y;
		return is;
	};

	inline std::istream& operator>>(std::istream& is, Vect3& v)
	{
		is >> v.x >> v.y >> v.z;
		return is;
	};

	inline std::istream& operator>>(std::istream& is, Vect4& v)
	{
		is >> v.x >> v.y >> v.z >> v.w;
		return is;
	};

	inline Vect2 operator*(const float f, const Vect2& v)
	{
		return v*f;
	};

	inline Vect3 operator*(const float f, const Vect3& v)
	{
		return v*f;
	};

	inline Vect4 operator*(const float f, const Vect4& v)
	{
		return v*f;
	};
};