/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#ifndef __GEVECTOR_H
#define __GEVECTOR_H

#include "ge_math.h"

enum _DONTCONSTRUCT{DC};

struct Vector
{
	Real x,y,z;

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

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

	friend const 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);
	}

	friend const Vector operator ! (const Vector &v)
	{
		Real l=Sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
		if (l==0.0) return 0.0;
		l = 1.0f/l;
		return Vector(v.x*l,v.y*l,v.z*l);
	}

	void Normalize(void)
	{
		Real l=Sqrt(x*x+y*y+z*z);
		if (l!=0.0)
		{
			l = 1.0f/l;
			x*=l;
			y*=l;
			z*=l;
		}
	}

	friend Real Len(const Vector &v)
	{
		return Sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
	}

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

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

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

	const Vector & operator *= (Real s)
	{
		x*=s; y*=s; z*=s;

		return *this;
	}

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

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

		return *this;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	friend Bool operator > (const Vector &v1,const Vector &v2)
	{
		// Mindestens eine Komponente groesser, die anderen groesser gleich
		return v1>=v2 && v1!=v2;
	}

	friend Bool operator < (const Vector &v1,const Vector &v2)
	{
		// Mindestens eine Komponente kleiner, die anderen kleiner gleich
		return v1<=v2 && v1!=v2;
	}

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

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

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

	inline const Vector & operator *= (const Matrix &m);

	inline const Vector & operator ^= (const Matrix &m);
}; // Vector

#endif
