Blame c++/perspective/src/vector.h

Ivan Mahonin 531f67
#ifndef VECTOR_H
Ivan Mahonin 531f67
#define VECTOR_H
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
#include <cassert>
Ivan Mahonin 531f67
Ivan Mahonin a1942e
#include <string>
Ivan Mahonin a1942e
#include <sstream>
Ivan Mahonin a1942e
Ivan Mahonin 531f67
#include "common.h"
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename ST, typename LT>
Ivan Mahonin 531f67
class VectorBase2T {
Ivan Mahonin 531f67
public:
Ivan Mahonin fdabb2
	typedef VectorBase2T<ST, LT> SelfTypeArg;
Ivan Mahonin 531f67
	typedef ST SelfType;
Ivan Mahonin 531f67
	typedef LT LowerType;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	typedef SelfType Vector2;
Ivan Mahonin 531f67
	typedef LowerType Coord;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	enum { Count = 2 };
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	union {
Ivan Mahonin 531f67
		struct { Coord coords[Count]; };
Ivan Mahonin 531f67
		struct { Coord x, y; };
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline explicit VectorBase2T(const Coord &x = Coord(), const Coord &y = Coord()):
Ivan Mahonin 531f67
		x(x), y(y) { }
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline SelfType perp() const
Ivan Mahonin 531f67
		{ return SelfType(-y, x); }
Ivan Mahonin 531f67
	inline SelfType yx() const
Ivan Mahonin 531f67
		{ return SelfType(y, x); }
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename ST, typename LT>
Ivan Mahonin 531f67
class VectorBase3T {
Ivan Mahonin 531f67
public:
Ivan Mahonin fdabb2
	typedef VectorBase3T<ST, LT> SelfTypeArg;
Ivan Mahonin 531f67
	typedef ST SelfType;
Ivan Mahonin 531f67
	typedef LT LowerType;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	typedef SelfType Vector3;
Ivan Mahonin 531f67
	typedef LowerType Vector2;
Ivan Mahonin 531f67
	typedef typename LowerType::Coord Coord;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	enum { Count = 3 };
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	union {
Ivan Mahonin 531f67
		struct { Coord coords[Count]; };
Ivan Mahonin 531f67
		struct { Coord x, y, z; };
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline explicit VectorBase3T(const Coord &x = Coord(), const Coord &y = Coord(), const Coord &z = Coord()):
Ivan Mahonin 531f67
		x(x), y(y), z(z) { }
Ivan Mahonin 531f67
	inline VectorBase3T(const Vector2 &v, const Coord &z):
Ivan Mahonin 531f67
		x(v.x), y(v.y), z(z) { }
Ivan Mahonin 531f67
	
Ivan Mahonin fdabb2
	inline SelfType cross(const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return SelfType(y*other.z - z*other.y, z*other.x - x*other.z, x*other.y - y*other.x); }
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	inline Vector2& vec2()
Ivan Mahonin 531f67
		{ return *(Vector2*)this; };
Ivan Mahonin 531f67
	inline const Vector2& vec2() const
Ivan Mahonin 531f67
		{ return *(const Vector2*)this; };
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline SelfType xzy() const
Ivan Mahonin 531f67
		{ return SelfType(x, z, y); }
Ivan Mahonin 531f67
	inline SelfType zxy() const
Ivan Mahonin 531f67
		{ return SelfType(z, x, y); }
Ivan Mahonin 531f67
	inline SelfType zyx() const
Ivan Mahonin 531f67
		{ return SelfType(z, y, x); }
Ivan Mahonin 531f67
	inline SelfType yxz() const
Ivan Mahonin 531f67
		{ return SelfType(y, x, z); }
Ivan Mahonin 531f67
	inline SelfType yzx() const
Ivan Mahonin 531f67
		{ return SelfType(y, z, x); }
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename ST, typename LT>
Ivan Mahonin 531f67
class VectorBase4T {
Ivan Mahonin 531f67
public:
Ivan Mahonin fdabb2
	typedef VectorBase4T<ST, LT> SelfTypeArg;
Ivan Mahonin 531f67
	typedef ST SelfType;
Ivan Mahonin 531f67
	typedef LT LowerType;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	typedef SelfType Vector4;
Ivan Mahonin 531f67
	typedef LowerType Vector3;
Ivan Mahonin 531f67
	typedef typename LowerType::Vector2 Vector2;
Ivan Mahonin 531f67
	typedef typename LowerType::Coord Coord;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	enum { Count = 4 };
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	union {
Ivan Mahonin 531f67
		struct { Coord coords[Count]; };
Ivan Mahonin 531f67
		struct { Coord x, y, z, w; };
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline explicit VectorBase4T(const Coord &x = Coord(), const Coord &y = Coord(), const Coord &z = Coord(), const Coord &w = Coord()):
Ivan Mahonin 531f67
		x(x), y(y), z(z), w(w) { }
Ivan Mahonin 531f67
	inline VectorBase4T(const Vector2 &v, const Coord &z, const Coord &w = Coord()):
Ivan Mahonin 531f67
		x(v.x), y(v.y), z(z), w(w) { }
Ivan Mahonin 531f67
	inline VectorBase4T(const Vector3 &v, const Coord &w):
Ivan Mahonin 531f67
		x(v.x), y(v.y), z(v.z), w(w) { }
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline Vector3& vec3()
Ivan Mahonin 531f67
		{ return *(Vector3*)this; };
Ivan Mahonin 531f67
	inline const Vector3& vec3() const
Ivan Mahonin 531f67
		{ return *(const Vector3*)this; };
Ivan Mahonin 531f67
Ivan Mahonin 531f67
		inline Vector2& vec2()
Ivan Mahonin 531f67
		{ return *(Vector2*)this; };
Ivan Mahonin 531f67
	inline const Vector2& vec2() const
Ivan Mahonin 531f67
		{ return *(const Vector2*)this; };
Ivan Mahonin 531f67
	
Ivan Mahonin fdabb2
	inline SelfType cross(const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return SelfType(y*other.z - z*other.y, z*other.x - x*other.z, x*other.y - y*other.x, w); }
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename T>
Ivan Mahonin 531f67
class VectorT: public T {
Ivan Mahonin 531f67
public:
Ivan Mahonin fdabb2
	typedef VectorT<T> SelfTypeArg;
Ivan Mahonin 531f67
	typedef T ParentType;
Ivan Mahonin 531f67
	using ParentType::Count;
Ivan Mahonin 531f67
	using typename ParentType::Coord;
Ivan Mahonin 531f67
	using typename ParentType::SelfType;
Ivan Mahonin 531f67
	using ParentType::coords;
Ivan Mahonin 531f67
	using ParentType::ParentType; // contructors
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	inline VectorT() { }
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	inline explicit VectorT(const Coord *c) {
Ivan Mahonin 531f67
		assert(c);
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) coords[i] = c[i];
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	template<typename TT>
Ivan Mahonin 531f67
	inline explicit VectorT(const VectorT<TT> &v) {
Ivan Mahonin fdabb2
		const int cnt = (int)TT::Count < (int)Count ? (int)TT::Count : (int)Count;
Ivan Mahonin 531f67
		for(int i = 0; i < cnt; ++i) coords[i] = Coord(v.coords[i]);
Ivan Mahonin 531f67
		for(int i = cnt; i < Count; ++i) coords[i] = Coord();
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
	Coord& operator[] (int i)
Ivan Mahonin 531f67
		{ assert(i >= 0 && i < Count); return coords[i]; }
Ivan Mahonin 531f67
	const Coord& operator[] (int i) const
Ivan Mahonin 531f67
		{ assert(i >= 0 && i < Count); return coords[i]; }
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator< (const SelfTypeArg &other) const {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i)
Ivan Mahonin 531f67
			if (coords[i] < other.coords[i]) return true;
Ivan Mahonin 531f67
			else if (other.coords[i] < coords[i]) return false;
Ivan Mahonin 531f67
		return false;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator== (const SelfTypeArg &other) const {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i)
Ivan Mahonin 531f67
			if (coords[i] != other.coords[i]) return false;
Ivan Mahonin 531f67
		return true;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator!= (const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return !(*(const SelfType*)this == other); }
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline SelfType& operator+= (const SelfTypeArg &other) {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) coords[i] += other.coords[i];
Ivan Mahonin 531f67
		return *(SelfType*)this;
Ivan Mahonin 531f67
	}
Ivan Mahonin fdabb2
	inline SelfType& operator-= (const SelfTypeArg &other) {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) coords[i] -= other.coords[i];
Ivan Mahonin 531f67
		return *(SelfType*)this;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
	inline SelfType& operator*= (const Coord &c) {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) coords[i] *= c;
Ivan Mahonin 531f67
		return *(SelfType*)this;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
	inline SelfType operator- () const {
Ivan Mahonin 531f67
		SelfType v;
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) v.coords[i] = -coords[i];
Ivan Mahonin 531f67
		return v;
Ivan Mahonin 531f67
	}
Ivan Mahonin fdabb2
	inline Coord operator* (const SelfTypeArg &other) const {
Ivan Mahonin 531f67
		Coord r = Coord();
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i) r += coords[i]*other.coords[i];
Ivan Mahonin 531f67
		return r;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline SelfType operator+ (const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return SelfType(*this) += other; }
Ivan Mahonin fdabb2
	inline SelfType operator- (const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return SelfType(*this) -= other; }
Ivan Mahonin 531f67
	inline SelfType operator* (const Coord &c) const
Ivan Mahonin 531f67
		{ return SelfType(*this) *= c; }
Ivan Mahonin 531f67
	inline Coord square() const
Ivan Mahonin 531f67
		{ return *this * *this; }
Ivan Mahonin 14f971
		
Ivan Mahonin 14f971
	inline static SelfType& cast(Coord *c)
Ivan Mahonin 14f971
		{ return *(SelfType*)c; }
Ivan Mahonin 14f971
	inline static const SelfType& cast(const Coord *c)
Ivan Mahonin 14f971
		{ return *(const SelfType*)c; }
Ivan Mahonin a1942e
	
Ivan Mahonin a1942e
	std::string to_string() const {
Ivan Mahonin a1942e
		std::stringstream stream;
Ivan Mahonin a1942e
		stream << "(" << coords[0];
Ivan Mahonin a1942e
		for(int i = 1; i < Count; ++i) stream << ", " << coords[i];
Ivan Mahonin a1942e
		stream << ")";
Ivan Mahonin a1942e
		return stream.str();
Ivan Mahonin a1942e
	}
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename T>
Ivan Mahonin 531f67
class VectorFT: public VectorT<T> {
Ivan Mahonin 531f67
public:
Ivan Mahonin fdabb2
	typedef VectorFT<T> SelfTypeArg;
Ivan Mahonin 531f67
	typedef VectorT<T> ParentType;
Ivan Mahonin 531f67
	using ParentType::Count;
Ivan Mahonin 531f67
	using typename ParentType::Coord;
Ivan Mahonin 531f67
	using typename ParentType::SelfType;
Ivan Mahonin 531f67
	using ParentType::coords;
Ivan Mahonin 531f67
	using ParentType::ParentType; // contructors
Ivan Mahonin 531f67
	
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	inline SelfType& operator/= (const Coord &c)
Ivan Mahonin 531f67
		{ return *this *= Coord(1)/c; }
Ivan Mahonin 531f67
	inline SelfType operator/ (const Coord &c)
Ivan Mahonin 531f67
		{ return SelfType(*this) /= c; }
Ivan Mahonin 531f67
	inline Coord length() const
Ivan Mahonin 531f67
		{ return Coord(sqrt(ParentType::square())); }
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator< (const SelfTypeArg &other) const {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i)
Ivan Mahonin a1942e
			if (real_less(coords[i], other.coords[i] - real_precision)) return true;
Ivan Mahonin a1942e
			else if (real_less(other.coords[i], coords[i] - real_precision)) return false;
Ivan Mahonin 531f67
		return false;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator== (const SelfTypeArg &other) const {
Ivan Mahonin 531f67
		for(int i = 0; i < Count; ++i)
Ivan Mahonin a1942e
			if ( real_less(coords[i], other.coords[i] - real_precision)
Ivan Mahonin a1942e
			  || real_less(other.coords[i], coords[i] - real_precision) ) return false;
Ivan Mahonin 531f67
		return true;
Ivan Mahonin 531f67
	}
Ivan Mahonin 531f67
Ivan Mahonin fdabb2
	inline bool operator!= (const SelfTypeArg &other) const
Ivan Mahonin 531f67
		{ return !(*(const SelfType*)this == other); }
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename T>
Ivan Mahonin 531f67
class Vectors {
Ivan Mahonin 531f67
public:
Ivan Mahonin 531f67
	typedef T Type;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	class Vector2: public VectorT< VectorBase2T<Vector2, Type> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorT< VectorBase2T<Vector2, Type> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	class Vector3: public VectorT< VectorBase3T<Vector3, Vector2> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorT< VectorBase3T<Vector3, Vector2> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	class Vector4: public VectorT< VectorBase4T<Vector4, Vector3> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorT< VectorBase4T<Vector4, Vector3> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
template<typename T>
Ivan Mahonin 531f67
class VectorsFloat {
Ivan Mahonin 531f67
public:
Ivan Mahonin 531f67
	typedef T Type;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
	class Vector2: public VectorFT< VectorBase2T<Vector2, Type> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorFT< VectorBase2T<Vector2, Type> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	class Vector3: public VectorFT< VectorBase3T<Vector3, Vector2> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorFT< VectorBase3T<Vector3, Vector2> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
	class Vector4: public VectorFT< VectorBase4T<Vector4, Vector3> > {
Ivan Mahonin 531f67
	public:
Ivan Mahonin 531f67
		typedef VectorFT< VectorBase4T<Vector4, Vector3> > ParentType;
Ivan Mahonin 531f67
		using ParentType::ParentType; // constructors
Ivan Mahonin 531f67
	};
Ivan Mahonin 531f67
};
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
typedef VectorsFloat<Real>::Vector2 Vector2;
Ivan Mahonin 531f67
typedef VectorsFloat<Real>::Vector3 Vector3;
Ivan Mahonin 531f67
typedef VectorsFloat<Real>::Vector4 Vector4;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
typedef VectorsFloat<Int>::Vector2 IntVector2;
Ivan Mahonin 531f67
typedef VectorsFloat<Int>::Vector3 IntVector3;
Ivan Mahonin 531f67
typedef VectorsFloat<Int>::Vector4 IntVector4;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
typedef VectorsFloat<LongInt>::Vector2 LongIntVector2;
Ivan Mahonin 531f67
typedef VectorsFloat<LongInt>::Vector3 LongIntVector3;
Ivan Mahonin 531f67
typedef VectorsFloat<LongInt>::Vector4 LongIntVector4;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
typedef VectorsFloat<UInt>::Vector2 UIntVector2;
Ivan Mahonin 531f67
typedef VectorsFloat<UInt>::Vector3 UIntVector3;
Ivan Mahonin 531f67
typedef VectorsFloat<UInt>::Vector4 UIntVector4;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
typedef VectorsFloat<ULongInt>::Vector2 ULongIntVector2;
Ivan Mahonin 531f67
typedef VectorsFloat<ULongInt>::Vector3 ULongIntVector3;
Ivan Mahonin 531f67
typedef VectorsFloat<ULongInt>::Vector4 ULongIntVector4;
Ivan Mahonin 531f67
Ivan Mahonin 531f67
Ivan Mahonin 531f67
#endif