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