OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2013 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WMATRIXSYM_H 00026 #define WMATRIXSYM_H 00027 00028 #include <algorithm> 00029 #include <cassert> 00030 #include <iomanip> 00031 #include <sstream> 00032 #include <string> 00033 #include <vector> 00034 00035 #include <boost/shared_ptr.hpp> 00036 00037 #include "../exceptions/WOutOfBounds.h" 00038 00039 /** 00040 * Symmetric square matrix, storing only the elements of the triangular matrix without the main 00041 * diagonal. So in case of a NxN matrix there are only (N^2-N)/2 elements stored. 00042 * 00043 * \note There exists also a WWriter and WReader for storing/reading the matrix in VTK file format. 00044 */ 00045 template< typename T > 00046 class WMatrixSym 00047 { 00048 friend class WMatrixSymTest; 00049 public: 00050 /** 00051 * Type of stored elements. 00052 */ 00053 typedef T value_type; 00054 00055 /** 00056 * Shorthand for shared pointers. 00057 */ 00058 typedef boost::shared_ptr< WMatrixSym < T > > SPtr; 00059 00060 /** 00061 * Generates new symmetric matrix. 00062 * 00063 * \param n number of rows and cols 00064 */ 00065 explicit WMatrixSym( size_t n ); 00066 00067 /** 00068 * Default constructor leaving all empty. 00069 */ 00070 WMatrixSym(); 00071 00072 /** 00073 * Element acces operator as if the elements where stored as a normal matrix. 00074 * 00075 * \warning Acessing elements of the main diagonal is forbidden! 00076 * 00077 * \param i The i'th row 00078 * \param j The j'th column 00079 * 00080 * \return reference to the (i,j) element of the table 00081 */ 00082 T& operator()( size_t i, size_t j ) throw( WOutOfBounds ); 00083 00084 /** 00085 * Const version of the element access. 00086 * 00087 * \warning Acessing elements of the main diagonal is forbidden! 00088 * 00089 * \param i The i'th row 00090 * \param j The j'th column 00091 * 00092 * \return Const reference to the (i,j) element of the table 00093 */ 00094 const T& operator()( size_t i, size_t j ) const throw( WOutOfBounds ); 00095 00096 /** 00097 * Returns the number of elements stored in this matrix. 00098 * \return the number of elements stored in this matrix. 00099 */ 00100 size_t numElements() const; 00101 00102 /** 00103 * Returns the number of rows and cols of the matrix. 00104 * \return The number of rows and cols of the matrix. 00105 */ 00106 size_t size() const; 00107 00108 /** 00109 * Returns the elements stored inside of this container. 00110 * 00111 * \return Read-only reference to the elements stored inside this container. 00112 */ 00113 const std::vector< T >& getData() const; 00114 00115 /** 00116 * Resets the internal data to the given vector of elements. 00117 * 00118 * \param data new data in row major arrangement 00119 */ 00120 void setData( const std::vector< T > &data ) throw( WOutOfBounds ); 00121 00122 /** 00123 * Renders the matrix to a full nxn matrix, where the main diagonal is set to 0.0 and the m(i,j) == m(j,i). 00124 * Each column is separated by exactly one space and each row is separated by a newline. 00125 * 00126 * @return Multiline string containing the nxn symmetric matrix. 00127 */ 00128 std::string toString( void ) const; 00129 00130 private: 00131 /** 00132 * Internal data structure to store the elements. The order is row major. 00133 */ 00134 std::vector< T > m_data; 00135 00136 /** 00137 * Number of rows and cols. 00138 */ 00139 size_t m_n; 00140 }; 00141 00142 template< typename T > 00143 inline WMatrixSym< T >::WMatrixSym( size_t n ) 00144 : m_data( ( n * ( n - 1 ) ) / 2, 0.0 ), 00145 m_n( n ) 00146 { 00147 } 00148 00149 template< typename T > 00150 inline WMatrixSym< T >::WMatrixSym() 00151 : m_n( 0 ) 00152 { 00153 } 00154 00155 template< typename T > 00156 inline const T& WMatrixSym< T >::operator()( size_t i, size_t j ) const throw( WOutOfBounds ) 00157 { 00158 if( i == j || i >= m_n || j >= m_n ) 00159 { 00160 std::stringstream ss; 00161 ss << "Invalid Element Access ( " << i << ", " << j << " ). No diagonal elements or indices bigger than " << m_n << " are allowed."; 00162 throw WOutOfBounds( ss.str() ); 00163 } 00164 if( i > j ) 00165 { 00166 std::swap( i, j ); 00167 } 00168 return m_data[( i * m_n + j - ( i + 1 ) * ( i + 2 ) / 2 )]; 00169 } 00170 00171 00172 template< typename T > 00173 inline T& WMatrixSym< T >::operator()( size_t i, size_t j ) throw( WOutOfBounds ) 00174 { 00175 if( i == j || i >= m_n || j >= m_n ) 00176 { 00177 std::stringstream ss; 00178 ss << "Invalid Element Access ( " << i << ", " << j << " ). No diagonal elements or indices bigger than " << m_n << " are allowed."; 00179 throw WOutOfBounds( ss.str() ); 00180 } 00181 if( i > j ) 00182 { 00183 std::swap( i, j ); 00184 } 00185 return m_data[( i * m_n + j - ( i + 1 ) * ( i + 2 ) / 2 )]; 00186 } 00187 00188 00189 template< typename T > 00190 inline std::string WMatrixSym< T >::toString( void ) const 00191 { 00192 std::stringstream ss; 00193 ss << std::setprecision( 9 ) << std::fixed; 00194 ss << *this; 00195 return ss.str(); 00196 } 00197 00198 /** 00199 * Compares two matrix elementwise. First tested their size, if equal elementwisely further tests. 00200 * 00201 * \tparam T Element type 00202 * \param lhs Left symmetric matrix operand 00203 * \param rhs Right symmetric matrix operand 00204 * 00205 * \return True if and only if all elements are equal. 00206 */ 00207 template< typename T > 00208 inline bool operator==( WMatrixSym< T > const& lhs, WMatrixSym< T > const& rhs ) 00209 { 00210 std::vector< T > l = lhs.getData(); 00211 std::vector< T > r = rhs.getData(); 00212 return l == r; 00213 } 00214 00215 /** 00216 * Output operator for symmetric Matrix producing full square matrix. Each row in separate line. 00217 * 00218 * \tparam T Element type 00219 * \param os Output stream 00220 * \param m Matrix to put to output stream 00221 * 00222 * \return Output stream 00223 */ 00224 template< typename T > 00225 inline std::ostream& operator<<( std::ostream& os, const WMatrixSym< T >& m ) 00226 { 00227 size_t n = m.size(); 00228 for( size_t i = 0; i < n; ++i ) 00229 { 00230 for( size_t j = 0; j < n; ++j ) 00231 { 00232 if( i != j ) 00233 { 00234 os << m( i, j ); 00235 } 00236 else 00237 { 00238 os << 0.0; 00239 } 00240 if( ( j + 1 ) < n ) 00241 { 00242 os << " "; 00243 } 00244 } 00245 if( ( i + 1 ) < n ) 00246 { 00247 os << std::endl; 00248 } 00249 } 00250 return os; 00251 } 00252 00253 /** 00254 * Read elemnts of full square matrix into symmetric matrix. Only elements of the upper triangle matrix will be used. 00255 * First all elements separated by white space are read and then dimension check is performed, to ensure all 00256 * elements fit into sym Matrix then. 00257 * 00258 * \throw WOutOfBounds exception if element number missmatch occours. 00259 * 00260 * \tparam T Element type 00261 * \param is Input Stream 00262 * \param m Sym. Matrix to populate 00263 * 00264 * \return Input Stream 00265 */ 00266 template< typename T > 00267 inline std::istream& operator>>( std::istream& is, WMatrixSym< T >& m ) 00268 { 00269 std::vector< T > elements; 00270 T elm; 00271 while( is >> elm ) 00272 { 00273 elements.push_back( elm ); 00274 } 00275 if( m.size() * m.size() != elements.size() ) 00276 { 00277 std::stringstream ss; 00278 ss << "Error: Input stream has: " << elements.size() << " elements, while matrix given to accommodate expected: "; 00279 ss << m.size() * m.size() << " elements."; 00280 throw WOutOfBounds( ss.str() ); 00281 } 00282 typename std::vector< T >::const_iterator it = elements.begin(); 00283 for( size_t i = 0; i < m.size(); ++i ) 00284 { 00285 for( size_t j = 0; j < m.size(); ++j ) 00286 { 00287 if( j > i ) 00288 { 00289 m( i, j ) = *it; 00290 } 00291 ++it; 00292 } 00293 } 00294 return is; 00295 } 00296 00297 template< typename T > 00298 inline size_t WMatrixSym< T >::numElements() const 00299 { 00300 return m_data.size(); 00301 } 00302 00303 template< typename T > 00304 inline size_t WMatrixSym< T >::size() const 00305 { 00306 return m_n; 00307 } 00308 00309 template< typename T > 00310 inline const typename std::vector< T >& WMatrixSym< T >::getData() const 00311 { 00312 return m_data; 00313 } 00314 00315 template< typename T > 00316 inline void WMatrixSym< T >::setData( const std::vector< T > &data ) throw( WOutOfBounds ) 00317 { 00318 if( m_n * ( m_n - 1 ) / 2 != data.size() ) 00319 { 00320 std::stringstream ss; 00321 ss << "Data vector length: " << data.size() << " doesn't fit to number of rows and cols: " << m_n; 00322 throw WOutOfBounds( ss.str() ); 00323 } 00324 m_data = std::vector< T >( data ); // copy content 00325 } 00326 00327 typedef WMatrixSym< double > WMatrixSymDBL; 00328 typedef WMatrixSym< float > WMatrixSymFLT; 00329 00330 #endif // WMATRIXSYM_H