#include #include #include template vec::vec( double constant ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] = constant; } } template vec::vec( std::initializer_list init ) { unsigned int k{0}; for ( std::initializer_list::iterator itr{ init.begin() }; (itr != init.end()) && (k < n); ++itr, ++k ) { entries_[k] = *itr; } for ( ; k < n; ++k ) { entries_[k] = 0.0; } } template double &vec::operator()( unsigned int k ) { if ( k >= n ) { throw_vector_exception( k ); } return entries_[k]; } template double const &vec::operator()( unsigned int k ) const { if ( k >= n ) { throw_vector_exception( k ); } return entries_[k]; } template void vec::throw_vector_exception( unsigned int k ) const { std::string article{ "a " }; unsigned int en{ n }; while ( en >= 1000 ) { en /= 1000; } if ( (en == 8) || (en == 18) || ((en >= 80) && (en <= 89)) || ((en >= 800) && (en <= 899)) ) { article = "an "; } throw std::out_of_range{ "The index " + std::to_string( k ) + " is beyond the dimension of " + article + std::to_string( n ) + "-dimensional vector" }; } template double vec::norm() const { double sum{ 0.0 }; for ( unsigned int k{0}; k < n; ++k ) { sum += entries_[k]*entries_[k]; } return std::sqrt( sum ); } template double vec::norm( NORM flavor ) const { switch ( flavor ) { case infinity: { double max{ 0.0 }; for ( unsigned int k{0}; k < n; ++k ) { if ( std::abs( entries_[k] ) > max ) { max = std::abs( entries_[k] ); } } return max; } case one: { double sum{ 0.0 }; for ( unsigned int k{0}; k < n; ++k ) { sum += std::abs( entries_[k] ); } return sum; } case two: { double sum{ 0.0 }; for ( unsigned int k{0}; k < n; ++k ) { sum += entries_[k]*entries_[k]; } return std::sqrt( sum ); } } assert( false ); } /*************************************************************** * Scalar multiplication ***************************************************************/ template vec vec::operator*( double s ) const { vec product; for ( unsigned int k{0}; k < n; ++k ) { product.entries_[k] = s*entries_[k]; } return product; } template vec &vec::operator*=( double s ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] *= s; } return *this; } template vec vec::operator/( double s ) const { vec product; for ( unsigned int k{0}; k < n; ++k ) { product.entries_[k] = entries_[k]/s; } return product; } template vec &vec::operator/=( double s ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] /= s; } return *this; } /*************************************************************** * Vector addition ***************************************************************/ template vec vec::operator+( vec const &v ) const { vec sum; for ( unsigned int k{0}; k < n; ++k ) { sum.entries_[k] = entries_[k] + v.entries_[k]; } return sum; } template vec &vec::operator+=( vec const &v ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] += v.entries_[k]; } return *this; } template vec vec::operator-( vec const &v ) const { vec sum; for ( unsigned int k{0}; k < n; ++k ) { sum.entries_[k] = entries_[k] - v.entries_[k]; } return sum; } template vec &vec::operator-=( vec const &v ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] -= v.entries_[k]; } return *this; } /*************************************************************** * Scalar addition ***************************************************************/ template vec vec::operator+( double s ) const { vec sum; for ( unsigned int k{0}; k < n; ++k ) { sum.entries_[k] = entries_[k] + s; } return sum; } template vec &vec::operator+=( double s ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] += s; } return *this; } template vec vec::operator-( double s ) const { vec sum; for ( unsigned int k{0}; k < n; ++k ) { sum.entries_[k] = entries_[k] - s; } return sum; } template vec &vec::operator-=( double s ) { for ( unsigned int k{0}; k < n; ++k ) { entries_[k] -= s; } return *this; } /*************************************************************** * Unary operators ***************************************************************/ template vec vec::operator +() const { return *this; } template vec vec::operator -() const { return *this * (-1.0); } /*************************************************************** * Inner product ***************************************************************/ template double vec::operator *( vec const &v ) const { double sum{ 0 }; for ( unsigned int k{ 0 }; k < n; ++k ) { sum += entries_[k]*v.entries_[k]; } return sum; } /*************************************************************** * Project this vector onto the vector 'v' ***************************************************************/ template vec &vec::project( vec const &v ) { *this -= *this*v; return *this; } template vec operator *( double s, vec const &v ) { return v*s; } template vec operator /( double s, vec const &v ) { vec product{ 0.0 }; for ( unsigned int k{0}; k < n; ++k ) { product( k ) = 1.0/product( k ); } return product; } template std::string vec::to_string() const { if ( n == 0 ) { return std::string{ "[]" }; } else { std::string str{ "[" + std::to_string( entries_[0] ) }; for ( unsigned int k{1}; k < n; ++k ) { str += " " + std::to_string( entries_[k] ); } return str + "]'"; } } template double norm( vec const &v ) { return v.norm(); } template std::ostream &operator<<( std::ostream &out, vec const &rhs ) { return out << rhs.to_string(); }