VISR  0.11.7
Versatile Interactive Scene Renderer
basic_matrix.hpp
Go to the documentation of this file.
1 /* Copyright Institute of Sound and Vibration Research - All rights reserved */
2 
3 #ifndef VISR_EFL_BASIC_MATRIX_HPP_INCLUDED
4 #define VISR_EFL_BASIC_MATRIX_HPP_INCLUDED
5 
6 // avoid annoying warning about unsafe STL functions.
7 #ifdef _MSC_VER
8 #pragma warning(disable: 4996)
9 #endif
10 
11 #include "aligned_array.hpp"
12 #include "alignment.hpp"
13 #include "error_codes.hpp"
14 #include "export_symbols.hpp"
15 #include "vector_functions.hpp" // for vectorZero
16 
17 #include <algorithm>
18 #include <ciso646> // should not be necessary in C++11, but MSVC requires it for whatever reason.
19 #include <stdexcept>
20 #include <utility> // for std::swap
21 
22 namespace visr
23 {
24 namespace efl
25 {
26 
31 template< typename ElementType >
32 class VISR_EFL_LIBRARY_SYMBOL BasicMatrix
33 {
34 public:
35  explicit BasicMatrix( std::size_t alignmentElements = 0 )
36  : mStride( 0 )
37  , mNumberOfRows( 0 )
38  , mNumberOfColumns( 0 )
39  , mData( alignmentElements )
40  {
41  }
42 
43  explicit BasicMatrix( std::size_t numberOfRows, std::size_t numberOfColumns, std::size_t alignmentElements = 0 )
44  : mStride( nextAlignedSize( numberOfColumns, alignmentElements ) )
45  , mNumberOfRows( numberOfRows )
46  , mNumberOfColumns( numberOfColumns )
47  , mData( mStride*mNumberOfRows, alignmentElements )
48  {
49  zeroFill();
50  }
51 
52  explicit BasicMatrix( std::size_t numberOfRows, std::size_t numberOfColumns,
53  std::initializer_list< std::initializer_list< ElementType > > const & initialValues,
54  std::size_t alignmentElements = 0 )
55  : mStride( nextAlignedSize( numberOfColumns, alignmentElements ) )
56  , mNumberOfRows( numberOfRows )
57  , mNumberOfColumns( numberOfColumns )
58  , mData( mStride*mNumberOfRows, alignmentElements )
59  {
60  if( initialValues.size() != numberOfRows )
61  {
62  throw std::invalid_argument( "BasicMatrix constructor: The number of lists in the initializer list does not match the number of rows." );
63  }
64  std::size_t rowIdx( 0 );
65  for( auto rowIt = initialValues.begin(); rowIt != initialValues.end(); ++rowIt, ++rowIdx )
66  {
67  std::initializer_list< ElementType > const & colInitialiser = *rowIt;
68  if( colInitialiser.size() != numberOfColumns )
69  {
70  throw std::invalid_argument( "BasicMatrix constructor: The number of elements for each list within the initializer list must match the number of columns." );
71  }
72  std::copy( colInitialiser.begin(), colInitialiser.end(), row( rowIdx ) );
73  }
74  }
75 
76  BasicMatrix( BasicMatrix<ElementType> && rhs ) = default;
77 
78  BasicMatrix<ElementType> & operator=( BasicMatrix<ElementType> && rhs ) = default;
79 
81  {
82  }
83 
89  void resize( std::size_t newNumberOfRows, std::size_t newNumberOfColumns )
90  {
91  // Ensure strong exception safety by doing the swap() trick
92  std::size_t newStride = nextAlignedSize( newNumberOfColumns, alignmentElements() );
93  AlignedArray<ElementType> newData( newStride*newNumberOfRows, alignmentElements() );
94  ErrorCode const res = vectorZero( newData.data(), newStride*newNumberOfRows );
95  if( res != noError )
96  {
97  throw std::runtime_error( "Zeroing of matrix failed" );
98  }
99  // the rest of the function is non-throwing
100  mStride = newStride;
101  mNumberOfRows = newNumberOfRows;
102  mNumberOfColumns = newNumberOfColumns;
103  mData.swap( newData );
104  }
105 
106  void zeroFill()
107  {
108  ErrorCode const res = vectorZero( data(), stride()*numberOfRows() );
109  if( res != noError )
110  {
111  throw std::runtime_error( "Zeroing of matrix failed" );
112  }
113  }
114 
115  void fillValue( ElementType val )
116  {
117  ErrorCode const res = vectorFill( val, data(), stride()*numberOfRows() );
118  if( res != noError )
119  {
120  throw std::runtime_error( "Filling of matrix failed" );
121  }
122  }
123 
131  {
132  if( (numberOfRows() != rhs.numberOfRows()) or( numberOfColumns() != rhs.numberOfColumns() )
133  or( stride() != rhs.stride() ) or( alignmentElements() != rhs.alignmentElements() ) )
134  {
135  throw std::logic_error( "BasicMatrix::swap(): Matrix layout must be consistent for swapping" );
136  }
137  mData.swap( rhs.mData );
138  }
139 
145  void copy( BasicMatrix<ElementType> const & rhs )
146  {
147  const std::size_t minAlignment = std::min( alignmentElements(), rhs.alignmentElements() );
148  if( (numberOfRows() != rhs.numberOfRows()) or( numberOfColumns() != rhs.numberOfColumns() ) )
149  {
150  throw std::invalid_argument( "BasicMatrix::copy(): Matrix size inconsistent." );
151  }
152  if( rhs.stride() == stride() )
153  {
154  if( vectorCopy( rhs.data( ), data( ), numberOfRows( ) * stride( ), minAlignment ) != noError )
155  {
156  throw std::runtime_error( "BasicMatrix::copy() failed: " );
157  }
158  }
159  else
160  {
161  for( std::size_t rowIdx( 0 ); rowIdx < numberOfRows(); ++rowIdx )
162  {
163  if( vectorCopy( rhs.row( rowIdx ), row( rowIdx ), numberOfColumns( ), minAlignment ) != noError )
164  {
165  throw std::runtime_error( "BasicMatrix::copy() failed: " );
166  }
167  }
168  }
169  }
170 
171  std::size_t alignmentElements() const { return mData.alignmentElements(); }
172 
173  std::size_t stride() const { return mStride; }
174 
175  std::size_t numberOfRows() const { return mNumberOfRows; }
176 
177  std::size_t numberOfColumns( ) const { return mNumberOfColumns; }
178 
179  ElementType& operator()( std::size_t rowIdx, std::size_t colIdx )
180  {
181  return mData[rowIdx * stride() + colIdx];
182  }
183 
184  ElementType const & operator()( std::size_t rowIdx, std::size_t colIdx ) const
185  {
186  return mData[rowIdx * stride( ) + colIdx];
187  }
188 
189  ElementType& at( std::size_t rowIdx, std::size_t colIdx )
190  {
191  if( (rowIdx >= numberOfRows()) or( colIdx >= numberOfColumns()) )
192  {
193  throw std::out_of_range( "Matrix indices exceed dimensions." );
194  }
195  return operator()( rowIdx, colIdx );
196  }
197 
198  ElementType const & at( std::size_t rowIdx, std::size_t colIdx ) const
199  {
200  if( (rowIdx >= numberOfRows() ) or ( colIdx >= numberOfColumns()) )
201  {
202  throw std::out_of_range( "Matrix indices exceed dimensions." );
203  }
204  return operator()( rowIdx, colIdx );
205  }
206 
207  ElementType * data( ) { return mData.data( ); }
208 
209  ElementType const * data() const { return mData.data(); }
210 
211  ElementType * row( std::size_t rowIdx ) { return data() + rowIdx * stride(); }
212 
213  ElementType const * row( std::size_t rowIdx ) const { return data( ) + rowIdx * stride( ); }
214 
215  void setRow( std::size_t rowIdx, ElementType const * values )
216  {
217  efl::vectorCopy( values, row( rowIdx), numberOfColumns() );
218  }
219 
220  void setColumn( std::size_t colIdx, ElementType const * values )
221  {
222  // TODO: Should we provide a 'strided copy' function?
223  for( std::size_t rowIdx( 0 ); rowIdx < numberOfRows(); ++rowIdx )
224  {
225  (*this)(rowIdx, colIdx) = values[rowIdx];
226  }
227  }
228 
229 private:
230  BasicMatrix( const BasicMatrix< ElementType>& ) = delete;
231 
232  std::size_t mStride;
233 
234  std::size_t mNumberOfRows;
235  std::size_t mNumberOfColumns;
236 
238 };
239 
240 } // namespace efl
241 } // namespace visr
242 
243 #endif // #ifndef VISR_EFL_BASIC_MATRIX_HPP_INCLUDED
ElementType * data()
Definition: aligned_array.hpp:108
ElementType * data()
Definition: basic_matrix.hpp:207
void setColumn(std::size_t colIdx, ElementType const *values)
Definition: basic_matrix.hpp:220
std::size_t nextAlignedSize(std::size_t size, std::size_t alignment)
Definition: alignment.hpp:70
std::size_t alignmentElements() const
Definition: basic_matrix.hpp:171
std::size_t numberOfRows() const
Definition: basic_matrix.hpp:175
ElementType const & at(std::size_t rowIdx, std::size_t colIdx) const
Definition: basic_matrix.hpp:198
void copy(BasicMatrix< ElementType > const &rhs)
Definition: basic_matrix.hpp:145
Definition: error_codes.hpp:15
ErrorCode vectorZero(T *const dest, std::size_t numElements, std::size_t alignment)
Definition: vector_functions.cpp:40
BasicMatrix(std::size_t numberOfRows, std::size_t numberOfColumns, std::initializer_list< std::initializer_list< ElementType > > const &initialValues, std::size_t alignmentElements=0)
Definition: basic_matrix.hpp:52
void fillValue(ElementType val)
Definition: basic_matrix.hpp:115
ElementType const * data() const
Definition: basic_matrix.hpp:209
Definition: options.cpp:10
BasicMatrix(std::size_t alignmentElements=0)
Definition: basic_matrix.hpp:35
~BasicMatrix()
Definition: basic_matrix.hpp:80
void resize(std::size_t newNumberOfRows, std::size_t newNumberOfColumns)
Definition: basic_matrix.hpp:89
ErrorCode vectorFill(const T value, T *const dest, std::size_t numElements, std::size_t alignment)
Definition: vector_functions.cpp:51
ErrorCode vectorCopy(T const *const source, T *const dest, std::size_t numElements, std::size_t alignment)
Definition: vector_functions.cpp:73
BasicMatrix(std::size_t numberOfRows, std::size_t numberOfColumns, std::size_t alignmentElements=0)
Definition: basic_matrix.hpp:43
ElementType & operator()(std::size_t rowIdx, std::size_t colIdx)
Definition: basic_matrix.hpp:179
void zeroFill()
Definition: basic_matrix.hpp:106
ElementType * row(std::size_t rowIdx)
Definition: basic_matrix.hpp:211
std::size_t numberOfColumns() const
Definition: basic_matrix.hpp:177
ElementType const * row(std::size_t rowIdx) const
Definition: basic_matrix.hpp:213
ErrorCode
Definition: error_codes.hpp:13
ElementType const & operator()(std::size_t rowIdx, std::size_t colIdx) const
Definition: basic_matrix.hpp:184
ElementType & at(std::size_t rowIdx, std::size_t colIdx)
Definition: basic_matrix.hpp:189
std::size_t stride() const
Definition: basic_matrix.hpp:173
Definition: aligned_array.hpp:33
void setRow(std::size_t rowIdx, ElementType const *values)
Definition: basic_matrix.hpp:215
Definition: init_filter_matrix.hpp:15
void swap(BasicMatrix< ElementType > &rhs)
Definition: basic_matrix.hpp:130