OpenWalnut  1.4.0
WMatrixSym.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2013 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WMATRIXSYM_H
26 #define WMATRIXSYM_H
27 
28 #include <algorithm>
29 #include <cassert>
30 #include <iomanip>
31 #include <sstream>
32 #include <string>
33 #include <vector>
34 
35 #ifndef Q_MOC_RUN
36 #include <boost/shared_ptr.hpp>
37 #endif
38 
39 #include "../exceptions/WOutOfBounds.h"
40 
41 /**
42  * Symmetric square matrix, storing only the elements of the triangular matrix without the main
43  * diagonal. So in case of a NxN matrix there are only (N^2-N)/2 elements stored.
44  *
45  * \note There exists also a WWriter and WReader for storing/reading the matrix in VTK file format.
46  */
47 template< typename T >
49 {
50 friend class WMatrixSymTest;
51 public:
52  /**
53  * Type of stored elements.
54  */
55  typedef T value_type;
56 
57  /**
58  * Shorthand for shared pointers.
59  */
60  typedef boost::shared_ptr< WMatrixSym < T > > SPtr;
61 
62  /**
63  * Generates new symmetric matrix.
64  *
65  * \param n number of rows and cols
66  */
67  explicit WMatrixSym( size_t n );
68 
69  /**
70  * Default constructor leaving all empty.
71  */
72  WMatrixSym();
73 
74  /**
75  * Element acces operator as if the elements where stored as a normal matrix.
76  *
77  * \warning Acessing elements of the main diagonal is forbidden!
78  *
79  * \param i The i'th row
80  * \param j The j'th column
81  *
82  * \return reference to the (i,j) element of the table
83  */
84  T& operator()( size_t i, size_t j ) throw( WOutOfBounds );
85 
86  /**
87  * Const version of the element access.
88  *
89  * \warning Acessing elements of the main diagonal is forbidden!
90  *
91  * \param i The i'th row
92  * \param j The j'th column
93  *
94  * \return Const reference to the (i,j) element of the table
95  */
96  const T& operator()( size_t i, size_t j ) const throw( WOutOfBounds );
97 
98  /**
99  * Returns the number of elements stored in this matrix.
100  * \return the number of elements stored in this matrix.
101  */
102  size_t numElements() const;
103 
104  /**
105  * Returns the number of rows and cols of the matrix.
106  * \return The number of rows and cols of the matrix.
107  */
108  size_t size() const;
109 
110  /**
111  * Returns the elements stored inside of this container.
112  *
113  * \return Read-only reference to the elements stored inside this container.
114  */
115  const std::vector< T >& getData() const;
116 
117  /**
118  * Resets the internal data to the given vector of elements.
119  *
120  * \param data new data in row major arrangement
121  */
122  void setData( const std::vector< T > &data ) throw( WOutOfBounds );
123 
124  /**
125  * 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).
126  * Each column is separated by exactly one space and each row is separated by a newline.
127  *
128  * @return Multiline string containing the nxn symmetric matrix.
129  */
130  std::string toString( void ) const;
131 
132 private:
133  /**
134  * Internal data structure to store the elements. The order is row major.
135  */
136  std::vector< T > m_data;
137 
138  /**
139  * Number of rows and cols.
140  */
141  size_t m_n;
142 };
143 
144 template< typename T >
145 inline WMatrixSym< T >::WMatrixSym( size_t n )
146  : m_data( ( n * ( n - 1 ) ) / 2, 0.0 ),
147  m_n( n )
148 {
149 }
150 
151 template< typename T >
153  : m_n( 0 )
154 {
155 }
156 
157 template< typename T >
158 inline const T& WMatrixSym< T >::operator()( size_t i, size_t j ) const throw( WOutOfBounds )
159 {
160  if( i == j || i >= m_n || j >= m_n )
161  {
162  std::stringstream ss;
163  ss << "Invalid Element Access ( " << i << ", " << j << " ). No diagonal elements or indices bigger than " << m_n << " are allowed.";
164  throw WOutOfBounds( ss.str() );
165  }
166  if( i > j )
167  {
168  std::swap( i, j );
169  }
170  return m_data[( i * m_n + j - ( i + 1 ) * ( i + 2 ) / 2 )];
171 }
172 
173 
174 template< typename T >
175 inline T& WMatrixSym< T >::operator()( size_t i, size_t j ) throw( WOutOfBounds )
176 {
177  if( i == j || i >= m_n || j >= m_n )
178  {
179  std::stringstream ss;
180  ss << "Invalid Element Access ( " << i << ", " << j << " ). No diagonal elements or indices bigger than " << m_n << " are allowed.";
181  throw WOutOfBounds( ss.str() );
182  }
183  if( i > j )
184  {
185  std::swap( i, j );
186  }
187  return m_data[( i * m_n + j - ( i + 1 ) * ( i + 2 ) / 2 )];
188 }
189 
190 
191 template< typename T >
192 inline std::string WMatrixSym< T >::toString( void ) const
193 {
194  std::stringstream ss;
195  ss << std::setprecision( 9 ) << std::fixed;
196  ss << *this;
197  return ss.str();
198 }
199 
200 /**
201  * Compares two matrix elementwise. First tested their size, if equal elementwisely further tests.
202  *
203  * \tparam T Element type
204  * \param lhs Left symmetric matrix operand
205  * \param rhs Right symmetric matrix operand
206  *
207  * \return True if and only if all elements are equal.
208  */
209 template< typename T >
210 inline bool operator==( WMatrixSym< T > const& lhs, WMatrixSym< T > const& rhs )
211 {
212  std::vector< T > l = lhs.getData();
213  std::vector< T > r = rhs.getData();
214  return l == r;
215 }
216 
217 /**
218  * Output operator for symmetric Matrix producing full square matrix. Each row in separate line.
219  *
220  * \tparam T Element type
221  * \param os Output stream
222  * \param m Matrix to put to output stream
223  *
224  * \return Output stream
225  */
226 template< typename T >
227 inline std::ostream& operator<<( std::ostream& os, const WMatrixSym< T >& m )
228 {
229  size_t n = m.size();
230  for( size_t i = 0; i < n; ++i )
231  {
232  for( size_t j = 0; j < n; ++j )
233  {
234  if( i != j )
235  {
236  os << m( i, j );
237  }
238  else
239  {
240  os << 0.0;
241  }
242  if( ( j + 1 ) < n )
243  {
244  os << " ";
245  }
246  }
247  if( ( i + 1 ) < n )
248  {
249  os << std::endl;
250  }
251  }
252  return os;
253 }
254 
255 /**
256  * Read elemnts of full square matrix into symmetric matrix. Only elements of the upper triangle matrix will be used.
257  * First all elements separated by white space are read and then dimension check is performed, to ensure all
258  * elements fit into sym Matrix then.
259  *
260  * \throw WOutOfBounds exception if element number missmatch occours.
261  *
262  * \tparam T Element type
263  * \param is Input Stream
264  * \param m Sym. Matrix to populate
265  *
266  * \return Input Stream
267  */
268 template< typename T >
269 inline std::istream& operator>>( std::istream& is, WMatrixSym< T >& m )
270 {
271  std::vector< T > elements;
272  T elm;
273  while( is >> elm )
274  {
275  elements.push_back( elm );
276  }
277  if( m.size() * m.size() != elements.size() )
278  {
279  std::stringstream ss;
280  ss << "Error: Input stream has: " << elements.size() << " elements, while matrix given to accommodate expected: ";
281  ss << m.size() * m.size() << " elements.";
282  throw WOutOfBounds( ss.str() );
283  }
284  typename std::vector< T >::const_iterator it = elements.begin();
285  for( size_t i = 0; i < m.size(); ++i )
286  {
287  for( size_t j = 0; j < m.size(); ++j )
288  {
289  if( j > i )
290  {
291  m( i, j ) = *it;
292  }
293  ++it;
294  }
295  }
296  return is;
297 }
298 
299 template< typename T >
300 inline size_t WMatrixSym< T >::numElements() const
301 {
302  return m_data.size();
303 }
304 
305 template< typename T >
306 inline size_t WMatrixSym< T >::size() const
307 {
308  return m_n;
309 }
310 
311 template< typename T >
312 inline const typename std::vector< T >& WMatrixSym< T >::getData() const
313 {
314  return m_data;
315 }
316 
317 template< typename T >
318 inline void WMatrixSym< T >::setData( const std::vector< T > &data ) throw( WOutOfBounds )
319 {
320  if( m_n * ( m_n - 1 ) / 2 != data.size() )
321  {
322  std::stringstream ss;
323  ss << "Data vector length: " << data.size() << " doesn't fit to number of rows and cols: " << m_n;
324  throw WOutOfBounds( ss.str() );
325  }
326  m_data = std::vector< T >( data ); // copy content
327 }
328 
331 
332 #endif // WMATRIXSYM_H
Unit test this LookUp table class.
size_t m_n
Number of rows and cols.
Definition: WMatrixSym.h:141
T value_type
Type of stored elements.
Definition: WMatrixSym.h:55
Symmetric square matrix, storing only the elements of the triangular matrix without the main diagonal...
Definition: WMatrixSym.h:48
std::vector< T > m_data
Internal data structure to store the elements.
Definition: WMatrixSym.h:136
Indicates invalid element access of a container.
Definition: WOutOfBounds.h:36
const std::vector< T > & getData() const
Returns the elements stored inside of this container.
Definition: WMatrixSym.h:312
T & operator()(size_t i, size_t j)
Element acces operator as if the elements where stored as a normal matrix.
Definition: WMatrixSym.h:175
void setData(const std::vector< T > &data)
Resets the internal data to the given vector of elements.
Definition: WMatrixSym.h:318
WMatrixSym()
Default constructor leaving all empty.
Definition: WMatrixSym.h:152
boost::shared_ptr< WMatrixSym< T > > SPtr
Shorthand for shared pointers.
Definition: WMatrixSym.h:60
std::string toString(void) const
Renders the matrix to a full nxn matrix, where the main diagonal is set to 0.0 and the m(i...
Definition: WMatrixSym.h:192
size_t numElements() const
Returns the number of elements stored in this matrix.
Definition: WMatrixSym.h:300
size_t size() const
Returns the number of rows and cols of the matrix.
Definition: WMatrixSym.h:306