// __author__ = Juan Carlos De Abreu (jcabreur@gmail.com)

#ifndef MATH_VEC2_INL_H__
#define MATH_VEC2_INL_H__

#include "Vec2.h"

BEGIN_TEG_NAMESPACE();

// 
namespace math {

// Operdor de casting entre un Vec3 y un flotante
template<class _T>
__forceinline void Vec2<_T>::operator =(const _T& _param) {
	// Se actualizan los valores de las componentes del vector
	x = y = _param;
}

// Operador de casting entre dos Vec3
template<class _T>
__forceinline void Vec2<_T>::operator =(const Vec2<_T>& _param) {
	// Se actualizan los valores de las componentes del vector
	memcpy(values, _param.values, sizeof(values));
}

// Operador para obtener un elemento del vector
template<class _T>
__forceinline _T Vec2<_T>::operator [](const int &_index) const {
	// Se retorna el elemento i del vector
	return values[_index];
}

// Operador para incrementar las componentes del vector
template<class _T>
__forceinline void Vec2<_T>::operator ++() {
	// Se actualizan los valores de las componentes del vector
	x++;	y++;
}

// Operador para decrementar las componentes del vector
template<class _T>
__forceinline void Vec2<_T>::operator --() {
	// Se actualizan los valores de las componentes del vector
	x--;	y--;
}

// Operador para negar el vector
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator - () {
	return Vec2<_T> (-x, -y);
}

// Operador de suma entre dos Vec3
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator +(const Vec2<_T>& _param) const {
	// Se calcula el vector resultante y se retorna
	return Vec2<_T>(x + _param.x, y + _param.y);
}

// Operdor de suma y asignacion entre dos Vec3
template<class _T>
__forceinline void Vec2<_T>::operator +=(const Vec2<_T>& _param) {
	// Se actualizan los valores de las componentes del vector
	x += _param.x;	y += _param.y;
}

// Operdor de suma entre un Vec3 y flotante 
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator +(const _T& _param) const {
	// Se calcula el vector resultante y se retorna
	return Vec2<_T>(x + _param, y + _param);
}

// 
template<class _T>
__forceinline void Vec2<_T>::operator +=(const _T& _param) {
	// Se actualizan los valores de las componentes del vector
	x += _param;	y += _param;
}

// Operadores de resta entre dos vectores
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator -(const Vec2<_T>& _param) const {
	// Se calcula el vector resultante y se retorna
	return Vec2<_T>(x - _param.x, y - _param.y);
}

// 
template<class _T>
__forceinline void Vec2<_T>::operator -=(const Vec2<_T>& _param) {
	// Se actualizan los valores de las componentes del vector
	x -= _param.x;	y -= _param.y;
}

// Operadores para restarle un flotante a todas las componentes del vector
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator -(const _T& _param) const {
	// Se calcula el vector resultante y se retorna
	return Vec2<_T>(x - _param, y - _param);
}

// 
template<class _T>
__forceinline void Vec2<_T>::operator -=(const _T& _param) {
	// Se actualizan los valores de las componentes del vector
	x -= _param;	y -= _param;
}


// Operadores para el producto entre un vector y un escalar
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator *(const _T& _param) const {
	// Se calcula el vector resultante y se retorna
	return Vec2<_T>(x * _param, y * _param);
}

// 
template<class _T>
__forceinline void Vec2<_T>::operator *=(const _T& _param) {
	// Se actualizan los valores de las componentes del vector
	x *= _param;	y *= _param;
}

// Operadores para la division entre un vector y un escalar
template<class _T>
__forceinline Vec2<_T> Vec2<_T>::operator /(const _T& _param) const {
	// Se calcula el vector resultante y se retorna
	const _T _t = static_cast<_T>(1) / _param;
	return Vec3<_T>(x * _t, y * _t);
}

// 
template<class _T>
__forceinline void Vec2<_T>::operator /=(const _T& _param) {
	// Se actualizan los valores de las componentes del vector
	const _T _t = static_cast<_T>(1) / _param;
	x *= _t;	y *= _t;
}

// Operadores de comparacion entre vectores
template<class _T>
__forceinline bool Vec2<_T>::operator ==(const Vec2<_T>& _param) const {
	return x == _param.x && y == _param.y;
}

template<class _T>
__forceinline bool Vec2<_T>::operator !=(const Vec2<_T>& _param) const {
	return x != _param.x || y != _param.y;
}

template<class _T>
__forceinline bool Vec2<_T>::operator <(const Vec2<_T>& _param) const {
	return x < _param.x && y < _param.y;
}

template<class _T>
__forceinline bool Vec2<_T>::operator >(const Vec2<_T>& _param) const {
	return x > _param.x && y > _param.y;
}

template<class _T>
__forceinline bool Vec2<_T>::operator <=(const Vec2<_T>& _param) const {
	return x <= _param.x && y <= _param.y;
}

template<class _T>
__forceinline bool Vec2<_T>::operator >=(const Vec2<_T>& _param) const {
	return x >= _param.x && y >= _param.y;
}

// Operadores de comparacion entre un vector y un flotante
template<class _T>
__forceinline bool Vec2<_T>::operator <(const _T& _param) const {
	return x < _param && y < _param;
}

template<class _T>
__forceinline bool Vec2<_T>::operator >(const _T& _param) const {
	return x > _param && y > _param;
}

template<class _T>
__forceinline bool Vec2<_T>::operator <=(const _T& _param) const {
	return x <= _param && y <= _param;
}

template<class _T>
__forceinline bool Vec2<_T>::operator >=(const _T& _param) const {
	return x >= _param && y >= _param;
}

template<class _T>
__forceinline bool Vec2<_T>::operator ==(const _T& _param) const {
	return x == _param && y == _param;
}

template<class _T>
__forceinline bool Vec2<_T>::operator !=(const _T& _param) const {
	return x != _param && y != _param;
}

// Metodo para inicializar el vector
template<class _T>
void Vec2<_T>::init() {
	// Se iniicializan los valores de las componentes del vector
	memset(values, 0, sizeof(values));
}

// Metodo para obtener el modulo del vector
template<class _T>
_T Vec2<_T>::module() const {
	return sqrt(x*x + y*y);
}

// Metodo para normalizar el vector
template<class _T>
void Vec2<_T>::normalize() {
	const _T mod = static_cast<_T> (1) / module();
	x *= mod;	y *= mod;
}

// Metodo para ajustar las componentes del vector
template<class _T>
void Vec2<_T>::set(const _T& _tx) {
	// Se actualizan los valores de las componentes del vector
	x = _tx;
}

// Metodo para ajustar las componentes del vector
template<class _T>
void Vec2<_T>::set(const _T& _tx, const _T& _ty) {
	// Se actualizan los valores de las componentes del vector
	x = _tx;	y = _ty;
}

// Metodo para calcular el producto punto entre dos vectores
template<class _T>
_T dot(const Vec2<_T>& v1, const Vec2<_T>& v2) {
	return (v1.x*v2.x + v1.y*v2.y);
}

};	// Math namespace

END_TEG_NAMESPACE();

#endif  // MATH_VEC2_INL_H__
