diff --git a/vectors.hpp b/vectors.hpp new file mode 100644 index 0000000..2ce0c24 --- /dev/null +++ b/vectors.hpp @@ -0,0 +1,333 @@ +/** Vector type and functionality + * + * This file defines the Vector type which defines some + * basic operations on a vector + * + * @file vectors.cpp + * @author Valentin Gehrke + * @version 0.1 + * @date Friday, 11. December 2015 16:09 + */ + +#pragma once + +#include +#include + +/** Vector type for N dimensions + * + * This class defines the Vector type + * with basic operations for vectors + * + * TElem must have add, subtract and multiplication defined. + * + * @tparam NDim dimension of the Vector + * @tparam TElem type of the coordinates + */ +template< + unsigned int NDim, + typename TElem +> +class Vector +{ + static_assert( NDim > 0 , "The Vector must atleast have one dimension." ); +private: + TElem coord[ NDim ]; +public: + /** Empty constructor + * + * This constructor just creates a Vector + * that doesn't have to be initialized + * + */ + Vector() {} + + /** Constructor for one value + * + * This constructor takes one value and + * initializes all coordinates with it + * + * @param initialElement Value for initialization + */ + Vector(const TElem initialElement) + { + for( unsigned int i = 0; i < NDim; i++ ) + { + this->coord[ i ] = initialElement; + } + } + + /** constructor for initialization with array + * + * This constructor initializes the coordinates with the + * contents of an array + * + * @tparam template parameter + * @param parameter + * @return return value + */ + Vector( const TElem initialData[ NDim ] ) + { + for( unsigned int i = 0; i < NDim; i++ ) + { + this->coord[ i ] = initialData[ i ]; + } + } + + /** constructor for brace enclosed initializer list + * + * this constructor initializes the coordinates with a + * brace enclosed initializer list which enables the object + * to be initialized like the following code example + * + * @code + * Vector<3,int> v{1,2,3}; + * @end-code + * + * @tparam template parameter + * @param parameter + * @return return value + */ + Vector( std::initializer_list initialData ) + { + assert( initialData.size() == NDim ); + std::copy( initialData.begin(), initialData.end(), this->coord ); + } + + /** return the length of the vector + * + * This method calculates the length of the vector using + * the Pythagorean Theorem + * + * @return length of the vector + */ + auto + length( ) const + -> decltype( sqrt( coord[0] ) ) + { + TElem len = 0; + for( unsigned int index = 0; index < NDim; index++ ) + { + len += this->coord[ index ] * this->coord[ index ]; + } + return sqrt( len ); + } + + /** vector normalization + * + * This method normalizes the vector by dividing its + * coordinates by the length of the vector + * + * @return normalized vector + */ + auto + normalize( ) const + -> Vector + { + return (*this) / this->length(); + } + + template< + typename TElemOther + > + auto + operator=( Vector const & other ) + -> Vector< NDim, TElem >& + { + for(unsigned int index = 0; index < NDim; index++) { + this->coord[ index ] = (TElem) other[ index ]; + } + return *this; + } + + /** division by scalar + * + * This method divides the coordinates of the vector + * by a scalar elementwise + * + * @param other divisor + * @return vector divided by divisor + */ + template< + typename TFactor + > + auto + operator/( const TFactor other ) const + -> Vector + { + Vector< NDim, decltype( coord[0]/other ) > result; + for( unsigned int index = 0; index < NDim; index++ ) + { + result[ index ] = this->coord[ index ] / other; + } + return result; + } + + /** + operator for Vector + * + * This operator adds 2 vectors together + * by adding their coordinates elementwise + * + * @param other Vector which is added to this vector + * @return A new Vector containing the result + */ + template< + typename TElemOther + > + auto + operator+ ( const Vector other ) const + -> Vector + { + Vector< NDim, decltype( coord[0] + other[0] ) > result; + for( unsigned int i = 0 ; i < NDim ; i++ ) { + result[ i ] = this->coord[ i ] + other[ i ]; + } + return result; + } + + /** += operator for Vector + * + * This operator adds another vector to the current + * vector without creating a new vector + * + * @param other The vector to be added + * @return The current vector after the addition + */ + template< + typename TElemOther + > + auto + operator+= ( const Vector< NDim, TElemOther >& other ) + -> Vector& + { + for( unsigned int i = 0; i < NDim; i++ ) { + this->coord[ i ] = ( TElem )( this->coord[ i ] + other[ i ] ); + } + return *this; + } + + /** - operator for Vector + * + * This operator subtract another vector from the + * current vector resulting in a new Vector object + * + * @param other The vector to subtract + * @return A new vector containing the result + */ + template< + typename TElemOther + > + auto + operator- ( const Vector other ) const + -> Vector< + NDim, + decltype( coord[0] - other[0] ) + > + { + Vector< NDim, decltype( coord[0] - other[0] ) > result; + for(unsigned int i = 0; i < NDim; i++) + { + result[ i ] = this->coord[ i ] - other[ i ]; + } + return result; + } + + /** negation operator for Vector + * + * This operator negates the current vector and + * returns the result as a new Vector + * + * @return A new vector containing the result + */ + auto + operator- ( ) const + -> Vector< + NDim, + TElem + > + { + Vector< NDim , TElem > result; + for( unsigned int i = 0; i < NDim; i++ ) + { + result[i] = - this->coord[ i ]; + } + return result; + } + + /** multiplication operator for multiplication with a scalar + * + * This operator multiplys every coordinate with a factor + * + * @param factor factor used for the multiplication + * @return A new vector containing the result + */ + template< + typename TFactor + > + auto + operator*( TFactor factor ) const + -> Vector< + NDim, + decltype( factor * coord[0] ) + > + { + Vector< NDim , decltype( factor * coord[0] ) > result; + for( unsigned int i = 0; i < NDim; i++ ) { + result[i] = this->coord[ i ] * factor; + } + return result; + } + + /** subscript operator + * + * This operator is used to read or write single coordinates + * of the vector + * + * @param index The index of the coordinate to be read or written + * @return A reference to the coordinate specified by index + */ + TElem& + operator[]( const unsigned int index ) + { + assert( index >= 0 && index <= NDim ); + return this->coord[ index ]; + } + + /** subscript operator for constant use + * + * This operator is used to read a single coordinate as a constant value + * + * @param index The index of the coordinate to be read + * @return The value of the coordinate specified by index + */ + const TElem + operator[]( const unsigned int index ) const + { + assert( index >= 0 && index <= NDim ); + return this->coord[ index ]; + } +}; + +/** reverse definition for multiplikation with a scalar + * + * This function defines the multiplication operator + * for TElem * Vector as the same as + * Vector * TElem + * + * @tparam template parameter + * @param parameter + * @return return value + */ +template< + unsigned int NDim, + typename TElem, + typename TFactor +> +Vector< + NDim, + TElem +> +operator*( const TFactor factor, const Vector vector ) +{ + return vector.operator*( factor ); +}