#ifndef __GELVECTOR_H
#define __GELVECTOR_H

#include "ge_vector.h"

#define LPow(a,b) (LReal(pow 	(double(a),double(b))))
#define LACos(r) 	(LReal(acos (double(r))))
#define LSin(r) 	(LReal(sin 	(double(r))))
#define LCos(r) 	(LReal(cos 	(double(r))))
#define LTan(r) 	(LReal(tan 	(double(r))))
#define LATan(r) 	(LReal(atan	(double(r))))
#define LExp(r)		(LReal(exp 	(double(r))))
#define LLn(r) 		(LReal(log 	(double(r))))
#define LLn10(r) 	(LReal(log10(double(r))))
#define LSqrt(r)	(LReal(sqrt	(double(r))))
#define LCosh(r)	(LReal(cosh	(double(r))))
#define LSinh(r)	(LReal(sinh	(double(r))))
#define LTanh(r)	(LReal(tanh	(double(r))))

struct LVector
{
	LReal x,y,z;

	LVector(){x = y = z = 0.0;}
	LVector(LReal in){x=y=z=in;}
	LVector(LReal ix, LReal iy, LReal iz){x=ix;y=iy;z=iz;}
	LVector(_DONTCONSTRUCT v){}

	friend const LVector operator ^ (const LVector &v1, const LVector &v2)
	{
		return LVector(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
	}
	friend const LVector operator % (const LVector &v1, const LVector &v2)
	{
		return LVector(v1.y*v2.z-v1.z*v2.y,
									v1.z*v2.x-v1.x*v2.z,
									v1.x*v2.y-v1.y*v2.x);
	}

	friend const LVector operator ! (const LVector &v)
	{
		LReal l=LSqrt(v.x*v.x+v.y*v.y+v.z*v.z);
		if (!l) return 0.0;
		l = 1.0/l;
		return LVector(v.x*l,v.y*l,v.z*l);
	}

	friend LReal Len(const LVector &v)
	{
		return LSqrt(v.x*v.x+v.y*v.y+v.z*v.z);
	}

	friend LReal operator * (const LVector &v1, const LVector &v2)
	{
		return(v1.x*v2.x+v1.y*v2.y+v1.z*v2.z);
	}

	friend const LVector operator * (const LVector &v, LReal s)
	{
		return LVector(v.x*s,v.y*s,v.z*s);
	}

	friend const LVector operator * (LReal s, const LVector &v)
	{
		return LVector(v.x*s,v.y*s,v.z*s);
	}

	const LVector & operator *= (LReal s)
	{
		x*=s; y*=s; z*=s;

		return *this;
	}

	friend const LVector operator / (LReal s, const LVector &v)
	{
		if(s) return LVector(v.x/s,v.y/s,v.z/s);
		else return 0.0;
	}

	friend const LVector operator / (const LVector &v, LReal s)
	{
		if(s) return LVector(v.x/s,v.y/s,v.z/s);
		else return 0.0;
	}

	const LVector & operator /= (LReal s)
	{
		if (s)
		{
			x/=s; y/=s; z/=s;
		}
		else x = y = z = 0;

		return *this;
	}

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

	friend const LVector operator + (const LVector &v, LReal s)
	{
		return LVector(v.x+s,v.y+s,v.z+s);
	}

	friend const LVector operator + (LReal s, const LVector &v)
	{
		return LVector(v.x+s,v.y+s,v.z+s);
	}

	const LVector & operator += (LReal s)
	{
		x+=s; y+=s; z+=s;
		return *this;
	}

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

	friend const LVector operator - (const LVector &v)
	{
		return LVector(-v.x,-v.y,-v.z);
	}

	friend const LVector operator - (const LVector &v, LReal s)
	{
		return LVector(v.x-s,v.y-s,v.z-s);
	}

	friend const LVector operator - (LReal s, const LVector &v)
	{
		return LVector(s-v.x,s-v.y,s-v.z);
	}

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

	const LVector & operator -= (LReal s)
	{
		x-=s; y-=s; z-=s;
		return *this;
	}

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

	friend Bool operator == (const LVector &v1, const LVector &v2)
	{
		return ((v1.x==v2.x)&&(v1.y==v2.y)&&(v1.z==v2.z));
	}

	friend Bool operator == (const LVector &v1, LReal r)
	{
		return ((v1.x==r)&&(v1.y==r)&&(v1.z==r));
	}

	friend Bool operator != (const LVector &v1, LReal r)
	{
		return ((v1.x!=r) || (v1.y!=r) || (v1.z!=r));
	}

	friend Bool operator != (const LVector &v1, const LVector &v2)
	{
		return ((v1.x!=v2.x)||(v1.y!=v2.y)||(v1.z!=v2.z));
	}
}; // LVector

inline const LVector LV(const Vector  &v) {return LVector(v.x,v.y,v.z);}
inline const Vector  SV(const LVector &v) {return Vector(v.x,v.y,v.z);}

#endif
