one-file-projects/vectors.hpp

334 lines
8.1 KiB
C++

/** 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 <cassert>
#include <cmath>
/** 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<TElem> 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<NDim, decltype( coord[ 0 ] / sqrt( coord[ 0 ] ) ) >
{
return (*this) / this->length();
}
template<
typename TElemOther
>
auto
operator=( Vector<NDim,TElemOther> 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<NDim, decltype( coord[0]/other ) >
{
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<NDim, TElemOther> 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;
}
/** += 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<NDim, TElem>&
{
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<NDim,TElemOther> 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<NDim, TElem> as the same as
* Vector<NDim, TElem> * 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<NDim, TElem> vector )
{
return vector.operator*( factor );
}