#include #include #include template vec::vec() { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] = 0.0; } } template vec::vec( double s ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] = s; } } template vec::vec( vec const &v ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] = v.entries_[k]; } } template vec::vec( std::initializer_list init ) { std::size_t k{0}; for ( std::initializer_list::iterator itr{init.begin()}; itr != init.end(); ++itr ) { entries_[k] = *itr; ++k; } assert( k <= N ); for ( ; k < N; ++k ) { entries_[k] = 0.0; } } template vec vec::operator =( vec const &v ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] = v.entries_[k]; } return *this; } template vec &vec::operator *=( double s ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] *= s; } return *this; } template vec vec::operator *( double s ) const { vec ret; for ( std::size_t k{0}; k < N; ++k ) { ret.entries_[k] = entries_[k]*s; } return ret; } template vec &vec::operator +=( vec const &v ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] += v.entries_[k]; } return *this; } template vec vec::operator +( vec const &v ) const { vec ret; for ( std::size_t k{0}; k < N; ++k ) { ret.entries_[k] = entries_[k] + v.entries_[k]; } return ret; } template vec &vec::operator -=( vec const &v ) { for ( std::size_t k{0}; k < N; ++k ) { entries_[k] -= v.entries_[k]; } return *this; } template vec vec::operator -( vec const &v ) const { vec ret; for ( std::size_t k{0}; k < N; ++k ) { ret.entries_[k] = entries_[k] - v.entries_[k]; } return ret; } template vec vec::operator +() const { vec ret; for ( std::size_t k{0}; k < N; ++k ) { ret.entries_[k] = entries_[k]; } return ret; } template vec vec::operator -() const { vec ret; for ( std::size_t k{0}; k < N; ++k ) { ret.entries_[k] = -entries_[k]; } return ret; } template double vec::operator * ( vec const &v ) const { double ret{0.0}; for ( std::size_t k{0}; k < N; ++k ) { ret += entries_[k] * v.entries_[k]; } return ret; } template double &vec::operator []( std::size_t k ) { return entries_[k]; } template double vec::operator []( std::size_t k ) const { return entries_[k]; } template bool vec::operator ==( vec const &v ) const { for ( std::size_t k{0}; k < N; ++k ) { if ( v.entries_[k] != entries_[k] ) { return false; } } return true; } template bool vec::operator !=( vec const &v ) const { for ( std::size_t k{0}; k < N; ++k ) { if ( v.entries_[k] != entries_[k] ) { return true; } } return false; } /*************************************************************** * The 1-norm is the sum of the * absolute values of the entries: * * N * ----- * \ * ||u|| = ) |u | * 1 / k * ----- * k = 1 * * The 2-norm is the square-root of the * sum of the squares of the entries: * _________ * / N * / ----- * / \ 2 * ||u|| = / ) u * 2 / / k * \ / ----- * \/ k = 1 * * * The infinity-norm is the maximum entry * in absolute value. * ( ) * ||u|| = max < |u | > * oo k = 1..N ( k ) * ***************************************************************/ template double vec::norm( int p ) const { switch( p ) { case 0: { // The infinity-norm or max length double ret{ std::abs( entries_[0] ) }; for ( std::size_t k{1}; k < N; ++k ) { double absk{ std::abs( entries_[k] ) }; if ( absk > ret ) { ret = absk; } } return ret; } case 1: { // The 1-norm or Manhatten length double ret{ std::abs( entries_[0] ) }; for ( std::size_t k{1}; k < N; ++k ) { ret += std::abs( entries_[k] ); } return ret; } case 2: { // The 2-norm or Euclidean length double ret{ entries_[0]*entries_[0] }; for ( std::size_t k{1}; k < N; ++k ) { ret += entries_[k]*entries_[k]; } return std::sqrt( ret ); } default: throw std::invalid_argument( "Supported p-norms include 1, 2 and 0 (infinity)" ); } } template vec operator *( double s, vec const &v ) { return v * s; } template std::ostream &operator<<( std::ostream &out, vec const &v ) { out << "["; if ( M != 0 ) { out << v[0]; for ( std::size_t k{1}; k < M; ++k ) { out << ", " << v[k]; } } out << "]"; return out; } template double vec::norm( vec const &v, int p ) { return v.norm( p ); }