#include <iostream>
#include <sstream>
#include <utility>
#include <cmath>


using namespace std::rel_ops;

template <class T>class C3_tpl {
public:
	T x,y,z;

	C3_tpl() {x=0;y=0;z=0;}
	C3_tpl(T nx,T ny,T nz) {
		x=nx;y=ny;z=nz;
	}
	C3_tpl(T nx,T ny) {
		x=nx;y=ny;z=0;
	}
	C3_tpl(T n) {
		x=n;y=n;z=n;
	}

	T dot(C3_tpl <T> p) { return x*p.x+y*p.y+z*p.z; }
	T dot() { return x*x + y*y + z*z; }
	double magnitude() { return sqrt(dot()); }

	void normalize() {
		double mag=magnitude();
		x/=(T)mag;
		y/=(T)mag;
		z/=(T)mag;
	}
	void min() {
		x=std::numeric_limits<T>::min();
		y=std::numeric_limits<T>::min();
		z=std::numeric_limits<T>::min();
	}
	void max() {
		x=std::numeric_limits<T>::max();
		y=std::numeric_limits<T>::max();
		z=std::numeric_limits<T>::max();
	}

	T sum() { return fabs(x)+fabs(y)+fabs(z); }
	bool isnull() {
		if (z!=0) return false;
		if (y!=0) return false;
		if (x!=0) return false;
		return true;
	}
	bool exceeds(T min,T max) {
		if (x<min) return true;
		if (x>max) return true;
		if (y<min) return true;
		if (y>max) return true;
		if (z<min) return true;
		if (z>max) return true;
		return false;
	}

	C3_tpl <int> toint() {
		C3_tpl <int> i;

		i.x=static_cast<int>(x);
		i.y=static_cast<int>(y);
		i.z=static_cast<int>(z);
		return i;
	}
	C3_tpl <float> tofloat() {
		C3_tpl <float> i;

		i.x=static_cast<float>(x);
		i.y=static_cast<float>(y);
		i.z=static_cast<float>(z);
		return i;
	}



	C3_tpl <T> rotforward() {
		C3_tpl <T> r;
		static const float degtorad = M_PI/180;

		r.x=cosf(y*degtorad);
		r.y=sinf(x*degtorad);
		r.z=sinf(y*degtorad);
		return r;
	}

	float dist(C3_tpl <T>a) {
		float c;

		c=(a.x-x)*(a.x-x);
		c+=(a.y-y)*(a.y-y);
		c+=(a.z-z)*(a.z-z);
		c=sqrtf(c);
		return c;
	}

	bool too_far(C3_tpl <T>a,T max) {
		T n;
		n=a.x-x;
		if (n>max) return true;
		if (n<-max) return true;
		n=a.y-y;
		if (n>max) return true;
		if (n<-max) return true;
		n=a.z-z;
		if (n>max) return true;
		if (n<-max) return true;
		return false;
	}
	bool dist_below(C3_tpl <T>a,T b) {
		float c;

		c=(a.x-x)*(a.x-x);
		c+=(a.y-y)*(a.y-y);
		c+=(a.z-z)*(a.z-z);
		if (c<b) return true;
		return false;
	}

/////////
//Operators:
////////
	friend bool operator<(const C3_tpl &a,const C3_tpl &b) {
		unsigned int ia,ib;
		ia=a.x+a.y*100+a.z*10000;
		ib=b.x+b.y*100+b.z*10000;
		if (ia<ib) return true;
		return false;
	}
	
	friend bool operator==(const C3_tpl &a,const C3_tpl &b) {
		if (a.x!=b.x) return false;
		if (a.y!=b.y) return false;
		if (a.z!=b.z) return false;
		return true;
	}

	C3_tpl & operator+=(const C3_tpl &a) {
		x+=a.x;
		y+=a.y;
		z+=a.z;
		return (*this);	
	}
	C3_tpl & operator+=(const T &a) {
		x+=a;
		y+=a;
		z+=a;
		return (*this);	
	}
	C3_tpl operator+(T b) {
		C3_tpl <T> c;

		c.x=x+b;
		c.y=y+b;
		c.z=z+b;
		return c;
	}
	C3_tpl operator+(C3_tpl <T>a) {
		C3_tpl <T> c;
		c.x=a.x+x;
		c.y=a.y+y;
		c.z=a.z+z;
		return c;
	}


	C3_tpl & operator-=(const C3_tpl &a) {
		x-=a.x;
		y-=a.y;
		z-=a.z;
		return (*this);	
	}
	C3_tpl & operator-=(const T &a) {
		x-=a;
		y-=a;
		z-=a;
		return (*this);	
	}
	C3_tpl operator-(T b) {
		C3_tpl <T> c;

		c.x=x-b;
		c.y=y-b;
		c.z=z-b;
		return c;
	}
	C3_tpl operator-(C3_tpl <T>a) {
		C3_tpl <T> c;
		c.x=x-a.x;
		c.y=y-a.y;
		c.z=z-a.z;
		return c;
	}
	
	C3_tpl operator*(C3_tpl <T> b) {
		C3_tpl <T> c;

		c.x=x*b.x;
		c.y=y*b.y;
		c.z=z*b.z;
		return c;
	}
	C3_tpl operator*(T b) {
		C3_tpl <T> c;

		c.x=x*b;
		c.y=y*b;
		c.z=z*b;
		return c;
	}
	C3_tpl operator*=(T b) {
		x*=b;
		y*=b;
		z*=b;
		return (*this);
	}
	C3_tpl operator*=(C3_tpl <T> b) {
		x*=b.x;
		y*=b.y;
		z*=b.z;
		return (*this);
	}
	C3_tpl operator/=(C3_tpl <T> b) {
		x/=b.x;
		y/=b.y;
		z/=b.z;
		return (*this);
	}

	C3_tpl<T> operator/(T b) {
		C3_tpl <T> c;
		c.x=x/b;
		c.y=y/b;
		c.z=z/b;
		return c;
	}
	C3_tpl<T> operator/(C3_tpl <T> b) {
		C3_tpl <T> c;
		c.x=x/b.x;
		c.y=y/b.y;
		c.z=z/b.z;
		return c;
	}
	C3_tpl operator/=(T b) {
		x/=b;
		y/=b;
		z/=b;
		return (*this);
	}
};

template <class T> std::ostream& operator<< (std::ostream& s, C3_tpl <T>& v) {
   return s << v.x << " " << v.y << " " << v.z ;
}
