Blob Blame Raw
#ifndef VECTOR_H
#define VECTOR_H


#include <cassert>

#include <string>
#include <sstream>
#include <utility>

#include "common.h"


template<typename T>
inline bool coord_less(const T &a, const T &b)
	{ return a < b; }

template<>
inline bool coord_less(const Real &a, const Real &b)
	{ return real_less(a, b); }



template<typename ST, typename LT>
class VectorBase2T {
public:
	typedef VectorBase2T<ST, LT> SelfTypeArg;
	typedef ST SelfType;
	typedef LT LowerType;

	typedef SelfType Vector2;
	typedef LowerType Coord;

	enum { Count = 2 };
	
	union {
		struct { Coord coords[Count]; };
		struct { Coord x, y; };
	};
	
	inline explicit VectorBase2T(const Coord &x = Coord(), const Coord &y = Coord()):
		x(x), y(y) { }
	
	inline SelfType perp() const
		{ return SelfType(-y, x); }
	inline SelfType yx() const
		{ return SelfType(y, x); }
};


template<typename ST, typename LT>
class VectorBase3T {
public:
	typedef VectorBase3T<ST, LT> SelfTypeArg;
	typedef ST SelfType;
	typedef LT LowerType;

	typedef SelfType Vector3;
	typedef LowerType Vector2;
	typedef typename LowerType::Coord Coord;

	enum { Count = 3 };

	union {
		struct { Coord coords[Count]; };
		struct { Coord x, y, z; };
	};
	
	inline explicit VectorBase3T(const Coord &x = Coord(), const Coord &y = Coord(), const Coord &z = Coord()):
		x(x), y(y), z(z) { }
	inline VectorBase3T(const Vector2 &v, const Coord &z):
		x(v.x), y(v.y), z(z) { }
	
	inline SelfType cross(const SelfTypeArg &other) const
		{ return SelfType(y*other.z - z*other.y, z*other.x - x*other.z, x*other.y - y*other.x); }

	inline Vector2& vec2()
		{ return *(Vector2*)this; };
	inline const Vector2& vec2() const
		{ return *(const Vector2*)this; };
	
	inline SelfType xzy() const
		{ return SelfType(x, z, y); }
	inline SelfType zxy() const
		{ return SelfType(z, x, y); }
	inline SelfType zyx() const
		{ return SelfType(z, y, x); }
	inline SelfType yxz() const
		{ return SelfType(y, x, z); }
	inline SelfType yzx() const
		{ return SelfType(y, z, x); }
};


template<typename ST, typename LT>
class VectorBase4T {
public:
	typedef VectorBase4T<ST, LT> SelfTypeArg;
	typedef ST SelfType;
	typedef LT LowerType;

	typedef SelfType Vector4;
	typedef LowerType Vector3;
	typedef typename LowerType::Vector2 Vector2;
	typedef typename LowerType::Coord Coord;

	enum { Count = 4 };

	union {
		struct { Coord coords[Count]; };
		struct { Coord x, y, z, w; };
	};
	
	inline explicit VectorBase4T(const Coord &x = Coord(), const Coord &y = Coord(), const Coord &z = Coord(), const Coord &w = Coord()):
		x(x), y(y), z(z), w(w) { }
	inline VectorBase4T(const Vector2 &v, const Coord &z, const Coord &w = Coord()):
		x(v.x), y(v.y), z(z), w(w) { }
	inline VectorBase4T(const Vector3 &v, const Coord &w):
		x(v.x), y(v.y), z(v.z), w(w) { }
	
	inline Vector3& vec3()
		{ return *(Vector3*)this; };
	inline const Vector3& vec3() const
		{ return *(const Vector3*)this; };

	inline Vector2& vec2()
		{ return *(Vector2*)this; };
	inline const Vector2& vec2() const
		{ return *(const Vector2*)this; };
};


template<typename T>
class VectorT: public T {
public:
	typedef VectorT<T> SelfTypeArg;
	typedef T ParentType;
	using ParentType::Count;
	using typename ParentType::Coord;
	using typename ParentType::SelfType;
	using ParentType::coords;
	using ParentType::ParentType; // contructors
	
	
	static inline bool coord_less(const Coord &a, const Coord &b)
		{ return ::coord_less(a, b); }
	
	
	inline VectorT() { }
	
	inline explicit VectorT(const Coord *c) {
		assert(c);
		for(int i = 0; i < Count; ++i) coords[i] = c[i];
	}
	
	template<typename TT>
	inline explicit VectorT(const VectorT<TT> &v) {
		const int cnt = (int)TT::Count < (int)Count ? (int)TT::Count : (int)Count;
		for(int i = 0; i < cnt; ++i) coords[i] = Coord(v.coords[i]);
		for(int i = cnt; i < Count; ++i) coords[i] = Coord();
	}
	
	Coord& operator[] (int i)
		{ assert(i >= 0 && i < Count); return coords[i]; }
	const Coord& operator[] (int i) const
		{ assert(i >= 0 && i < Count); return coords[i]; }

	inline bool operator< (const SelfTypeArg &other) const {
		for(int i = 0; i < Count; ++i)
			if (coord_less(coords[i], other.coords[i])) return true; else
				if (coord_less(other.coords[i], coords[i])) return false;
		return false;
	}

	inline bool operator== (const SelfTypeArg &other) const {
		for(int i = 0; i < Count; ++i)
			if ( coord_less(coords[i], other.coords[i])
			  || coord_less(other.coords[i], coords[i]) ) return false;
		return true;
	}

	inline bool operator!= (const SelfTypeArg &other) const
		{ return !(*(const SelfType*)this == other); }

	inline SelfType& operator+= (const SelfTypeArg &other) {
		for(int i = 0; i < Count; ++i) coords[i] += other.coords[i];
		return *(SelfType*)this;
	}
	inline SelfType& operator-= (const SelfTypeArg &other) {
		for(int i = 0; i < Count; ++i) coords[i] -= other.coords[i];
		return *(SelfType*)this;
	}
	inline SelfType& operator*= (const Coord &c) {
		for(int i = 0; i < Count; ++i) coords[i] *= c;
		return *(SelfType*)this;
	}
	inline SelfType operator- () const {
		SelfType v;
		for(int i = 0; i < Count; ++i) v.coords[i] = -coords[i];
		return v;
	}
	inline Coord operator* (const SelfTypeArg &other) const {
		Coord r = Coord();
		for(int i = 0; i < Count; ++i) r += coords[i]*other.coords[i];
		return r;
	}

	inline SelfType operator+ (const SelfTypeArg &other) const
		{ return SelfType(*this) += other; }
	inline SelfType operator- (const SelfTypeArg &other) const
		{ return SelfType(*this) -= other; }
	inline SelfType operator* (const Coord &c) const
		{ return SelfType(*this) *= c; }
	inline Coord square() const
		{ return *this * *this; }
		
	inline static SelfType& cast(Coord *c)
		{ return *(SelfType*)c; }
	inline static const SelfType& cast(const Coord *c)
		{ return *(const SelfType*)c; }
	
	std::string to_string() const {
		std::stringstream stream;
		stream << "(" << coords[0];
		for(int i = 1; i < Count; ++i) stream << ", " << coords[i];
		stream << ")";
		return stream.str();
	}
};


template<typename T>
class VectorFT: public VectorT<T> {
public:
	typedef VectorT<T> ParentType;
	using typename ParentType::Coord;
	using typename ParentType::SelfType;
	using ParentType::Count;
	using ParentType::coords;
	using ParentType::ParentType; // contructors
	

	inline SelfType& operator/= (const Coord &c)
		{ return *this *= Coord(1)/c; }
	inline SelfType operator/ (const Coord &c) const
		{ return SelfType(*this) /= c; }
	inline Coord length() const
		{ return Coord(sqrt(ParentType::square())); }
	
	inline SelfType normalized() const {
		Coord len = length();
		return ParentType::coord_less(Coord(), len)
		     ? *this / len : SelfType();
	}
	inline SelfType normalize() const
		{ *this = normalized(); return *(SelfType)this; }

	inline SelfType persp_divide() const
		{ return *this / coords[Count - 1]; }
};

template<typename T>
class PairT {
public:
	typedef T Vector;
	Vector p0;
	Vector p1;
	
	explicit inline PairT(const Vector &p = Vector()):
		p0(p), p1(p) { }
	inline PairT(const Vector &p0, const Vector &p1):
		p0(p0), p1(p1) { }

	template<typename TT>
	inline explicit PairT(const VectorT<TT> &p):
		p0(p), p1(p) { }
	template<typename TT>
	inline explicit PairT(const VectorT<TT> &p0, const VectorT<TT> &p1):
		p0(p0), p1(p1) { }

	template<typename TT>
	inline explicit PairT(const PairT<TT> &other):
		PairT(other.p0, other.p1) { }
		
	inline bool operator< (const PairT &other) const {
		return p0 < other.p0 ? true
			 : other.p0 < p0 ? false
			 : p1 < other.p1;
	}
	inline bool operator== (const PairT &other) const
		{ return !(*this < other) && !(other < *this); }
	inline bool operator!= (const PairT &other) const
		{ return *this < other || other < *this; }
	
	
	inline Vector distance() const
		{ return p1 - p0; }
	inline Vector size() const
		{ return distance(); }

	inline bool empty() const {
		for(int i = 0; i < Vector::Count; ++i)
			if (!Vector::coord_less(p0[i], p1[i]))
				return true;
		return false;
	}
	inline PairT& sort() {
		for(int i = 0; i < Vector::Count; ++i)
			if (p0[i] < p1[i])
				std::swap(p0[i], p1[i]);
		return *this;
	}
	inline PairT sorted() const
		{ return PairT(*this).sort(); }

	inline PairT& expand(const Vector &p) {
		for(int i = 0; i < Vector::Count; ++i) {
			if (p[i] < p0[i]) p0[i] = p[i];
			if (p1[i] < p[i]) p1[i] = p[i];
		}
		return *this;
	}
	inline PairT expanded(const Vector &p) const
		{ return PairT(*this).expand(p); }

	inline PairT& inflate(const Vector &p) {
		if (empty()) return *this;
		p0 -= p; p1 += p;
		return *this;
	}
	inline PairT inflated(const Vector &p) const
		{ return PairT(*this).inflate(p); }
};



template<typename T>
class Vectors {
public:
	typedef T Type;

	class Vector2: public VectorT< VectorBase2T<Vector2, Type> > {
	public:
		typedef VectorT< VectorBase2T<Vector2, Type> > ParentType;
		using ParentType::ParentType; // constructors
	};
	class Vector3: public VectorT< VectorBase3T<Vector3, Vector2> > {
	public:
		typedef VectorT< VectorBase3T<Vector3, Vector2> > ParentType;
		using ParentType::ParentType; // constructors
	};
	class Vector4: public VectorT< VectorBase4T<Vector4, Vector3> > {
	public:
		typedef VectorT< VectorBase4T<Vector4, Vector3> > ParentType;
		using ParentType::ParentType; // constructors
	};
};


template<typename T>
class VectorsFloat {
public:
	typedef T Type;

	class Vector2: public VectorFT< VectorBase2T<Vector2, Type> > {
	public:
		typedef VectorFT< VectorBase2T<Vector2, Type> > ParentType;
		using ParentType::ParentType; // constructors
	};
	class Vector3: public VectorFT< VectorBase3T<Vector3, Vector2> > {
	public:
		typedef VectorFT< VectorBase3T<Vector3, Vector2> > ParentType;
		using ParentType::ParentType; // constructors
	};
	class Vector4: public VectorFT< VectorBase4T<Vector4, Vector3> > {
	public:
		typedef VectorFT< VectorBase4T<Vector4, Vector3> > ParentType;
		using ParentType::ParentType; // constructors
	};
};


typedef VectorsFloat<Real>::Vector2 Vector2;
typedef VectorsFloat<Real>::Vector3 Vector3;
typedef VectorsFloat<Real>::Vector4 Vector4;

typedef VectorsFloat<Int>::Vector2 IntVector2;
typedef VectorsFloat<Int>::Vector3 IntVector3;
typedef VectorsFloat<Int>::Vector4 IntVector4;

typedef VectorsFloat<LongInt>::Vector2 LongIntVector2;
typedef VectorsFloat<LongInt>::Vector3 LongIntVector3;
typedef VectorsFloat<LongInt>::Vector4 LongIntVector4;

typedef VectorsFloat<UInt>::Vector2 UIntVector2;
typedef VectorsFloat<UInt>::Vector3 UIntVector3;
typedef VectorsFloat<UInt>::Vector4 UIntVector4;

typedef VectorsFloat<ULongInt>::Vector2 ULongIntVector2;
typedef VectorsFloat<ULongInt>::Vector3 ULongIntVector3;
typedef VectorsFloat<ULongInt>::Vector4 ULongIntVector4;


typedef PairT<Vector2> Pair2;
typedef PairT<Vector3> Pair3;
typedef PairT<Vector4> Pair4;

typedef PairT<IntVector2> IntPair2;
typedef PairT<IntVector3> IntPair3;
typedef PairT<IntVector4> IntPair4;

typedef PairT<LongIntVector2> LongIntPair2;
typedef PairT<LongIntVector3> LongIntPair3;
typedef PairT<LongIntVector4> LongIntPair4;

typedef PairT<ULongIntVector2> ULongIntPair2;
typedef PairT<ULongIntVector3> ULongIntPair3;
typedef PairT<ULongIntVector4> ULongIntPair4;


#endif