///////////////////////////////////////////////////////////////////// // Linear Math Vectors // © Dan Andersson 2013 ///////////////////////////////////////////////////////////////////// #pragma once #ifndef LINEARALGEBRA_VECTOR_H #define LINEARALGEBRA_VECTOR_H #include namespace LinearAlgebra { template class Vector2 { public: union { struct { ElementType x, y; }; ElementType element[2]; char byte[sizeof(ElementType[2])]; }; static const Vector2 null; static const Vector2 standardUnitX; static const Vector2 standardUnitY; Vector2( ); Vector2( const Vector2 &vector ); Vector2( const ElementType &element ); Vector2( const ElementType element[2] ); Vector2( const ElementType &x, const ElementType &y ); ~Vector2( ); operator ElementType* ( ); operator const ElementType* ( ) const; operator char* ( ); operator const char* ( ) const; ElementType & operator [] ( int i ); const ElementType & operator [] ( int i ) const; Vector2 & operator = ( const Vector2 &vector ); Vector2 & operator = ( const ElementType element[2] ); Vector2 & operator *= ( const ElementType &scalar ); Vector2 & operator /= ( const ElementType &scalar ); Vector2 & operator += ( const Vector2 &vector ); Vector2 & operator -= ( const Vector2 &vector ); Vector2 operator * ( const ElementType &scalar ) const; Vector2 operator / ( const ElementType &scalar ) const; Vector2 operator + ( const Vector2 &vector ) const; Vector2 operator - ( const Vector2 &vector ) const; Vector2 operator - ( ) const; // unary negation bool operator == ( const Vector2 &vector ) const; bool operator != ( const Vector2 &vector ) const; ElementType length( ) const; ElementType dot( const Vector2 &vector ) const; Vector2 & normalize( ); Vector2 getNormalized( ) const; }; template class Vector3 { public: union { struct { ElementType x, y, z; }; struct { Vector2 xy; }; ElementType element[3]; char byte[sizeof(ElementType[3])]; }; static const Vector3 null; static const Vector3 standardUnitX; static const Vector3 standardUnitY; static const Vector3 standardUnitZ; Vector3( ); Vector3( const Vector3 &vector ); Vector3( const Vector2 &vector, const ElementType &z ); Vector3( const ElementType &element ); Vector3( const ElementType element[3] ); Vector3( const ElementType &x, const ElementType &y, const ElementType &z ); ~Vector3( ); operator ElementType* (); operator const ElementType* () const; operator char* ( ); operator const char* ( ) const; ElementType & operator [] ( int i ); const ElementType & operator [] ( int i ) const; Vector3 & operator = ( const Vector3 &vector ); Vector3 & operator = ( const ElementType element[3] ); Vector3 & operator *= ( const ElementType &scalar ); Vector3 & operator /= ( const ElementType &scalar ); Vector3 & operator += ( const Vector3 &vector ); Vector3 & operator -= ( const Vector3 &vector ); Vector3 operator * ( const ElementType &scalar ) const; Vector3 operator / ( const ElementType &scalar ) const; Vector3 operator + ( const Vector3 &vector ) const; Vector3 operator - ( const Vector3 &vector ) const; Vector3 operator - ( ) const; // unary negation bool operator == ( const Vector3 &vector ) const; bool operator != ( const Vector3 &vector ) const; ElementType length( ) const; ElementType dot( const Vector3 &vector ) const; Vector3 cross( const Vector3 &vector ) const; Vector3 & normalize( ); Vector3 getNormalized( ) const; }; template class Vector4 { public: union { struct { ElementType x, y, z, w; }; struct { Vector2 xy; }; struct { Vector3 xyz; }; ElementType element[4]; char byte[sizeof(ElementType[4])]; }; static const Vector4 null; static const Vector4 standardUnitX; static const Vector4 standardUnitY; static const Vector4 standardUnitZ; static const Vector4 standardUnitW; Vector4( ); Vector4( const Vector4 &vector ); Vector4( const Vector3 &vector, const ElementType &w ); Vector4( const Vector2 &vector, const ElementType &z, const ElementType &w ); Vector4( const ElementType &element ); Vector4( const ElementType element[4] ); Vector4( const ElementType &x, const ElementType &y, const ElementType &z, const ElementType &w ); ~Vector4( ); operator ElementType* (); operator const ElementType* () const; operator char* ( ); operator const char* ( ) const; ElementType & operator [] ( int i ); const ElementType & operator [] ( int i ) const; Vector4 & operator = ( const Vector4 &vector ); Vector4 & operator = ( const ElementType element[4] ); Vector4 & operator *= ( const ElementType &scalar ); Vector4 & operator /= ( const ElementType &scalar ); Vector4 & operator += ( const Vector4 &vector ); Vector4 & operator -= ( const Vector4 &vector ); Vector4 operator * ( const ElementType &scalar ) const; Vector4 operator / ( const ElementType &scalar ) const; Vector4 operator + ( const Vector4 &vector ) const; Vector4 operator - ( const Vector4 &vector ) const; Vector4 operator - ( ) const; // unary negation bool operator == ( const Vector4 &vector ) const; bool operator != ( const Vector4 &vector ) const; ElementType length( ) const; ElementType dot( const Vector4 &vector ) const; Vector4 & normalize( ); Vector4 getNormalized( ) const; }; /////////////////////////////////////////////////////////////////////////////////// // Body /////////////////////////////////////////////////////////////////////////////////// // Vector2 /////////////////////////////////////// template const Vector2 Vector2::null = Vector2( ); template const Vector2 Vector2::standardUnitX = Vector2( 1, 0 ); template const Vector2 Vector2::standardUnitY = Vector2( 0, 1 ); template Vector2::Vector2( ) : x(0), y(0) {} template Vector2::Vector2( const Vector2 &vector ) : x(vector.x), y(vector.y) { this->x = vector.x; this->y = vector.y; } template Vector2::Vector2( const ElementType &_element ) : x(_element), y(_element) { this->x = this->y = _element; } template Vector2::Vector2( const ElementType _element[2] ) : x(_element[0]), y(_element[1]) {} template Vector2::Vector2( const ElementType &_x, const ElementType &_y ) : x(_x), y(_y) {} template Vector2::~Vector2( ) { /* Nothing that needs to be done */ } template inline Vector2::operator ElementType* () { return this->element; } template inline Vector2::operator const ElementType* () const { return this->element; } template inline Vector2::operator char* ( ) { return this->byte; } template inline Vector2::operator const char* ( ) const { return this->byte; } template inline ElementType & Vector2::operator [] ( int i ) { return this->element[i]; } template inline const ElementType & Vector2::operator [] ( int i ) const { return this->element[i]; } template Vector2 & Vector2::operator = ( const Vector2 &vector ) { this->element[0] = vector.element[0]; this->element[1] = vector.element[1]; return *this; } template Vector2 & Vector2::operator = ( const ElementType _element[2] ) { this->element[0] = _element[0]; this->element[1] = _element[1]; return *this; } template Vector2 & Vector2::operator *= ( const ElementType &scalar ) { this->element[0] *= scalar; this->element[1] *= scalar; return *this; } template Vector2 & Vector2::operator /= ( const ElementType &scalar ) { this->element[0] /= scalar; this->element[1] /= scalar; return *this; } template Vector2 & Vector2::operator += ( const Vector2 &vector ) { this->element[0] += vector.element[0]; this->element[1] += vector.element[1]; return *this; } template Vector2 & Vector2::operator -= ( const Vector2 &vector ) { this->element[0] -= vector.element[0]; this->element[1] -= vector.element[1]; return *this; } template inline Vector2 Vector2::operator * ( const ElementType &scalar ) const { return Vector2(*this) *= scalar; } template inline Vector2 Vector2::operator / ( const ElementType &scalar ) const { return Vector2(*this) /= scalar; } template inline Vector2 Vector2::operator + ( const Vector2 &vector ) const { return Vector2(*this) += vector; } template inline Vector2 Vector2::operator - ( const Vector2 &vector ) const { return Vector2(*this) -= vector; } template inline Vector2 Vector2::operator - ( ) const { return Vector2(-this->x, -this->y); } template bool Vector2::operator == ( const Vector2 &vector ) const { if( this->x != vector.x ) return false; if( this->y != vector.y ) return false; return true; } template bool Vector2::operator != ( const Vector2 &vector ) const { if( this->x != vector.x ) return true; if( this->y != vector.y ) return true; return false; } template inline ElementType Vector2::length( ) const { return (ElementType) ::sqrt( this->dot(*this) ); } template ElementType Vector2::dot( const Vector2 &vector ) const { ElementType value = 0; value += this->element[0] * vector.element[0]; value += this->element[1] * vector.element[1]; return value; } template inline Vector2 & Vector2::normalize( ) { return (*this) /= this->length(); } template inline Vector2 Vector2::getNormalized( ) const { return Vector2(*this).normalize(); } // Vector3 /////////////////////////////////////// template const Vector3 Vector3::null = Vector3( ); template const Vector3 Vector3::standardUnitX = Vector3( 1, 0, 0 ); template const Vector3 Vector3::standardUnitY = Vector3( 0, 1, 0 ); template const Vector3 Vector3::standardUnitZ = Vector3( 0, 0, 1 ); template Vector3::Vector3( ) : x(0), y(0), z(0) {} template Vector3::Vector3( const Vector3 &vector ) : x(vector.x), y(vector.y), z(vector.z) { this->x = vector.x; this->y = vector.y; this->z = vector.z; } template Vector3::Vector3( const Vector2 &vector, const ElementType &_z ) : x(vector.x), y(vector.y), z(_z) { this->x = vector.x; this->y = vector.y; } template Vector3::Vector3( const ElementType &_element ) : x(_element), y(_element), z(_element) { this->x = this->y = this->z = _element; } template Vector3::Vector3( const ElementType _element[3] ) : x(_element[0]), y(_element[1]), z(_element[2]) {} template Vector3::Vector3( const ElementType &_x, const ElementType &_y, const ElementType &_z ) : x(_x), y(_y), z(_z) { this->x = _x; this->y = _y; this->z = _z; } template Vector3::~Vector3( ) { /* Nothing that needs to be done */ } template inline Vector3::operator ElementType* () { return this->element; } template inline Vector3::operator const ElementType* () const { return this->element; } template inline ElementType & Vector3::operator [] ( int i ) { return this->element[i]; } template inline const ElementType & Vector3::operator [] ( int i ) const { return this->element[i]; } template Vector3 & Vector3::operator = ( const Vector3 &vector ) { for( int i = 0; i < 3; ++i ) this->element[i] = vector.element[i]; return *this; } template Vector3 & Vector3::operator = ( const ElementType element[3] ) { for( int i = 0; i < 3; ++i ) this->element[i] = element[i]; return *this; } template Vector3 & Vector3::operator *= ( const ElementType &scalar ) { for( int i = 0; i < 3; ++i ) this->element[i] *= scalar; return *this; } template Vector3 & Vector3::operator /= ( const ElementType &scalar ) { for( int i = 0; i < 3; ++i ) this->element[i] /= scalar; return *this; } template Vector3 & Vector3::operator += ( const Vector3 &vector ) { for( int i = 0; i < 3; ++i ) this->element[i] += vector.element[i]; return *this; } template Vector3 & Vector3::operator -= ( const Vector3 &vector ) { for( int i = 0; i < 3; ++i ) this->element[i] -= vector.element[i]; return *this; } template inline Vector3 Vector3::operator * ( const ElementType &scalar ) const { return Vector3(*this) *= scalar; } template inline Vector3 Vector3::operator / ( const ElementType &scalar ) const { return Vector3(*this) /= scalar; } template inline Vector3 Vector3::operator + ( const Vector3 &vector ) const { return Vector3(*this) += vector; } template inline Vector3 Vector3::operator - ( const Vector3 &vector ) const { return Vector3(*this) -= vector; } template inline Vector3 Vector3::operator - ( ) const { return Vector3(-this->x, -this->y, -this->z); } template bool Vector3::operator == ( const Vector3 &vector ) const { if( this->x != vector.x ) return false; if( this->y != vector.y ) return false; if( this->z != vector.z ) return false; return true; } template bool Vector3::operator != ( const Vector3 &vector ) const { if( this->x != vector.x ) return true; if( this->y != vector.y ) return true; if( this->z != vector.z ) return true; return false; } template inline ElementType Vector3::length( ) const { return (ElementType) ::sqrt( this->dot(*this) ); } template ElementType Vector3::dot( const Vector3 &vector ) const { ElementType value = 0; for( int i = 0; i < 3; ++i ) value += this->element[i] * vector.element[i]; return value; } template Vector3 Vector3::cross( const Vector3 &vector ) const { return Vector3( (this->y*vector.z) - (this->z*vector.y), (this->z*vector.x) - (this->x*vector.z), (this->x*vector.y) - (this->y*vector.x) ); } template inline Vector3 & Vector3::normalize( ) { return (*this) /= this->length(); } template inline Vector3 Vector3::getNormalized( ) const { return Vector3(*this).normalize(); } // Vector4 /////////////////////////////////////// template const Vector4 Vector4::null = Vector4( ); template const Vector4 Vector4::standardUnitX = Vector4( 1, 0, 0, 0 ); template const Vector4 Vector4::standardUnitY = Vector4( 0, 1, 0, 0 ); template const Vector4 Vector4::standardUnitZ = Vector4( 0, 0, 1, 0 ); template const Vector4 Vector4::standardUnitW = Vector4( 0, 0, 0, 1 ); template Vector4::Vector4( ) : x(0), y(0), z(0), w(0) {} template Vector4::Vector4( const Vector4 &vector ) : x(vector.x), y(vector.y), z(vector.z), w(vector.z) { this->x = vector.x; this->y = vector.y; this->z = vector.z; this->w = vector.w; } template Vector4::Vector4( const Vector3 &vector, const ElementType &_w ) : x(vector.x), y(vector.y), z(vector.z), w(_w) { this->x = vector.x; this->y = vector.y; this->z = vector.z; } template Vector4::Vector4( const Vector2 &vector, const ElementType &_z, const ElementType &_w ) : x(vector.x), y(vector.y), z(_z), w(_w) { this->x = vector.x; this->y = vector.y; this->z = _z; this->w = _w; } template Vector4::Vector4( const ElementType &_element ) : x(_element), y(_element), z(_element), w(_element) { this->x = this->y = this->z = this->w = _element; } template Vector4::Vector4( const ElementType _element[4] ) : x(_element[0]), y(_element[1]), z(_element[2]), w(_element[3]) {} template Vector4::Vector4( const ElementType &_x, const ElementType &_y, const ElementType &_z, const ElementType &_w ) : x(_x), y(_y), z(_z), w(_w) { this->x = _x; this->y = _y; this->z = _z; this->w = _w; } template Vector4::~Vector4( ) { /* Nothing that needs to be done */ } template inline Vector4::operator ElementType* () { return this->element; } template inline Vector4::operator const ElementType* () const { return this->element; } template inline ElementType & Vector4::operator [] ( int i ) { return this->element[i]; } template inline const ElementType & Vector4::operator [] ( int i ) const { return this->element[i]; } template Vector4 & Vector4::operator = ( const Vector4 &vector ) { for( int i = 0; i < 4; ++i ) this->element[i] = vector.element[i]; return *this; } template Vector4 & Vector4::operator = ( const ElementType element[4] ) { for( int i = 0; i < 4; ++i ) this->element[i] = element[i]; return *this; } template Vector4 & Vector4::operator *= ( const ElementType &scalar ) { for( int i = 0; i < 4; ++i ) this->element[i] *= scalar; return *this; } template Vector4 & Vector4::operator /= ( const ElementType &scalar ) { for( int i = 0; i < 4; ++i ) this->element[i] /= scalar; return *this; } template Vector4 & Vector4::operator += ( const Vector4 &vector ) { for( int i = 0; i < 4; ++i ) this->element[i] += vector.element[i]; return *this; } template Vector4 & Vector4::operator -= ( const Vector4 &vector ) { for( int i = 0; i < 4; ++i ) this->element[i] -= vector.element[i]; return *this; } template inline Vector4 Vector4::operator * ( const ElementType &scalar ) const { return Vector4(*this) *= scalar; } template inline Vector4 Vector4::operator / ( const ElementType &scalar ) const { return Vector4(*this) /= scalar; } template inline Vector4 Vector4::operator + ( const Vector4 &vector ) const { return Vector4(*this) += vector; } template inline Vector4 Vector4::operator - ( const Vector4 &vector ) const { return Vector4(*this) -= vector; } template inline Vector4 Vector4::operator - ( ) const { return Vector4(-this->x, -this->y, -this->z, -this->w); } template bool Vector4::operator == ( const Vector4 &vector ) const { if( this->x != vector.x ) return false; if( this->y != vector.y ) return false; if( this->z != vector.z ) return false; if( this->w != vector.w ) return false; return true; } template bool Vector4::operator != ( const Vector4 &vector ) const { if( this->x != vector.x ) return true; if( this->y != vector.y ) return true; if( this->z != vector.z ) return true; if( this->w != vector.w ) return true; return false; } template inline ElementType Vector4::length( ) const { return (ElementType) ::sqrt( this->dot(*this) ); } template ElementType Vector4::dot( const Vector4 &vector ) const { ElementType value = 0; for( int i = 0; i < 4; ++i ) value += this->element[i] * vector.element[i]; return value; } template inline Vector4 & Vector4::normalize( ) { return (*this) /= this->length(); } template inline Vector4 Vector4::getNormalized( ) const { return Vector4(*this).normalize(); } } #endif