//Jacek Matulewski, e-mail: jacek@fizyka.umk.pl

#ifndef WEKTOR_H
#define WEKTOR_H

#include <stdexcept>

template<typename T> struct TWektor
{
    public:
        //pola
		T X,Y,Z;
		
		//konstruktor
        TWektor()
        {
            this->X=0;
            this->Y=0;
            this->Z=0;
        };
        TWektor(T X,T Y,T Z)
        {
            this->X=X;
            this->Y=Y;
            this->Z=Z;
        }

		//operatory
        TWektor operator+(const TWektor& w)
        {
            return TWektor(X+w.X,Y+w.Y,Z+w.Z);
        };
		TWektor operator+=(const TWektor& w)
        {            
			X+=w.X;
            Y+=w.Y;
            Z+=w.Z;
            return *this;
        };
		TWektor operator-()
		{
			return TWektor(-X,-Y,-Z);
		}
		TWektor operator-(const TWektor& w)
        {
            return TWektor(X-w.X,Y-w.Y,Z-w.Z);
        };
		TWektor operator-=(const TWektor& w)
        {
            X-=w.X;
            Y-=w.Y;
            Z-=w.Z;
            return *this;
        };
        TWektor operator*(const T a)
        {
            return TWektor(a*X,a*Y,a*Z);
        };
		TWektor operator*=(const T a)
        {
            X*=a;
            Y*=a;
            Z*=a;
            return *this;
        };
        TWektor operator/(const T a)
        {
            return TWektor(X/a,Y/a,Z/a);
        };
		TWektor operator/=(const T a)
        {
			if(a==0.0) throw std::invalid_argument("Dzielenie przez zero");
            X/=a;
            Y/=a;
            Z/=a;
            return *this;
        };		
		T operator*(const TWektor& w) //iloczyn skalarny
        {
			return X*w.X+Y*w.Y+Z*w.Z;
        };
		bool operator==(const TWektor& w)
		{
			return X==w.X && Y==w.Y && Z==w.Z;
		}

		//metody
		T Dlugosc() const
        {
            return sqrt(X*X+Y*Y+Z*Z);
        }
		void Normuj()
		{
			T dlugosc=Dlugosc();
			if (dlugosc!=0) *this/=dlugosc;
			else throw std::invalid_argument("Nie mozna unormowac zerowego wektora");
		}

		T* ZapiszWTablicy(T tablica[3])
		{
			tablica[0]=X;
			tablica[1]=Y;
			tablica[2]=Z;
			return tablica;
		}

};

template<typename T> TWektor<T> operator*(const T a,const TWektor<T> &w)
{
    return TWektor<T>(a*w.X,a*w.Y,a*w.Z);	
}

template<typename T> TWektor<T> IloczynWektorowy(TWektor<T> a,TWektor<T> b)
{
	TWektor<T> wynik;
	wynik.X=  a.Y*b.Z-a.Z*b.Y;
	wynik.Y=-(a.X*b.Z-a.Z*b.X);
	wynik.Z=  a.X*b.Y-a.Y*b.X;
	return wynik;
}

typedef TWektor<double> Wektor;

const Wektor WektorZero=Wektor(0,0,0);
const Wektor WersorX=Wektor(1,0,0);
const Wektor WersorY=Wektor(0,1,0);
const Wektor WersorZ=Wektor(0,0,1);

#endif