A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
containers/matrix.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_MATRIX_H_
2 #define GENESIS_UTILS_CONTAINERS_MATRIX_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2018 Lucas Czech and HITS gGmbH
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
36 
37 #include <stdexcept>
38 #include <string>
39 #include <vector>
40 
41 namespace genesis {
42 namespace utils {
43 
44 // =================================================================================================
45 // Matrix
46 // =================================================================================================
47 
48 template <typename T>
49 class Matrix
50 {
51 public:
52 
53  // -------------------------------------------------------------
54  // Typedefs
55  // -------------------------------------------------------------
56 
58  using value_type = T;
59 
60  using container_type = std::vector<T>;
61  using iterator = typename container_type::iterator;
62  using const_iterator = typename container_type::const_iterator;
63 
64  // -------------------------------------------------------------
65  // Constructors and Rule of Five
66  // -------------------------------------------------------------
67 
69  : rows_(0)
70  , cols_(0)
71  , data_()
72  {}
73 
74  Matrix (size_t rows, size_t cols)
75  : rows_( rows )
76  , cols_( cols )
77  , data_( rows * cols )
78  {}
79 
80  Matrix (size_t rows, size_t cols, T init)
81  : rows_( rows )
82  , cols_( cols )
83  , data_( rows * cols, init )
84  {}
85 
86  Matrix( size_t rows, size_t cols, std::vector<T> const& data )
87  : rows_( rows )
88  , cols_( cols )
89  , data_( data )
90  {
91  if( rows * cols != data_.size() ) {
92  throw std::length_error(
93  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
94  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
95  std::to_string( rows * cols ) + " elements, but provided data contains " +
96  std::to_string( data_.size() ) + " elements."
97  );
98  }
99  }
100 
101  Matrix( size_t rows, size_t cols, std::vector<T>&& data )
102  : rows_( rows )
103  , cols_( cols )
104  , data_( std::move( data ))
105  {
106  if( rows * cols != data_.size() ) {
107  throw std::length_error(
108  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
109  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
110  std::to_string( rows * cols ) + " elements, but provided data contains " +
111  std::to_string( data_.size() ) + " elements."
112  );
113  }
114  }
115 
116  Matrix (size_t rows, size_t cols, std::initializer_list<T> const& init_list)
117  : rows_(rows)
118  , cols_(cols)
119  , data_(rows * cols)
120  {
121  if (init_list.size() != size()) {
122  throw std::length_error(
123  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
124  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
125  std::to_string( rows * cols ) + " elements, but provided data contains " +
126  std::to_string( init_list.size() ) + " elements."
127  );
128  }
129 
130  size_t i = 0;
131  for (T const& v : init_list) {
132  data_[i] = v;
133  ++i;
134  }
135  }
136 
137  ~Matrix() = default;
138 
139  Matrix(Matrix const&) = default;
140  Matrix(Matrix&&) = default;
141 
142  Matrix& operator= (Matrix const&) = default;
143  Matrix& operator= (Matrix&&) = default;
144 
145  void swap (Matrix& other)
146  {
147  using std::swap;
148  swap(rows_, other.rows_);
149  swap(cols_, other.cols_);
150  swap(data_, other.data_);
151  }
152 
153  friend void swap( Matrix& lhs, Matrix& rhs )
154  {
155  lhs.swap( rhs );
156  }
157 
158  // -------------------------------------------------------------
159  // Properties
160  // -------------------------------------------------------------
161 
162  size_t rows() const
163  {
164  return rows_;
165  }
166 
167  size_t cols() const
168  {
169  return cols_;
170  }
171 
172  size_t size() const
173  {
174  return rows_ * cols_;
175  }
176 
177  bool empty() const
178  {
179  return size() == 0;
180  }
181 
182  container_type const& data() const
183  {
184  return data_;
185  }
186 
187  // -------------------------------------------------------------
188  // Element Access
189  // -------------------------------------------------------------
190 
191  T& at (const size_t row, const size_t col)
192  {
193  if (row >= rows_ || col >= cols_) {
194  throw std::out_of_range( "Matrix index out of range." );
195  }
196  return data_[row * cols_ + col];
197  }
198 
199  T const& at (const size_t row, const size_t col) const
200  {
201  if (row >= rows_ || col >= cols_) {
202  throw std::out_of_range( "Matrix index out of range." );
203  }
204  return data_[row * cols_ + col];
205  }
206 
207  T& operator () (const size_t row, const size_t col)
208  {
209  return data_[row * cols_ + col];
210  }
211 
212  T const& operator () (const size_t row, const size_t col) const
213  {
214  return data_[row * cols_ + col];
215  }
216 
217  // -------------------------------------------------------------
218  // Slicing
219  // -------------------------------------------------------------
220 
222  {
223  if( row >= rows_ ) {
224  throw std::out_of_range( "Matrix row index out of range." );
225  }
226 
227  return MatrixRow<self_type, value_type>( *this, row );
228  }
229 
231  {
232  if( row >= rows_ ) {
233  throw std::out_of_range( "Matrix row index out of range." );
234  }
235 
237  }
238 
240  {
241  if( col >= cols_ ) {
242  throw std::out_of_range( "Matrix column index out of range." );
243  }
244 
245  return MatrixCol<self_type, value_type>( *this, col );
246  }
247 
249  {
250  if( col >= cols_ ) {
251  throw std::out_of_range( "Matrix column index out of range." );
252  }
253 
255  }
256 
257  // -------------------------------------------------------------
258  // Iterators
259  // -------------------------------------------------------------
260 
262  {
263  return data_.begin();
264  }
265 
267  {
268  return data_.end();
269  }
270 
272  {
273  return data_.begin();
274  }
275 
277  {
278  return data_.end();
279  }
280 
282  {
283  return data_.cbegin();
284  }
285 
287  {
288  return data_.cend();
289  }
290 
291  // -------------------------------------------------------------
292  // Operators
293  // -------------------------------------------------------------
294 
295  bool operator == ( Matrix<T> const& other ) const
296  {
297  return rows_ == other.rows_
298  && cols_ == other.cols_
299  && data_ == other.data_;
300  }
301 
302  bool operator != ( Matrix<T> const& other ) const
303  {
304  return !(*this == other);
305  }
306 
307  // -------------------------------------------------------------
308  // Data Members
309  // -------------------------------------------------------------
310 
311 private:
312 
313  size_t rows_;
314  size_t cols_;
315  container_type data_;
316 };
317 
318 } // namespace utils
319 } // namespace genesis
320 
321 #endif // include guard
typename container_type::iterator iterator
View into a Matrix column.
Definition: col.hpp:60
std::vector< size_t > container_type
const_iterator cbegin() const
void swap(SequenceSet &lhs, SequenceSet &rhs)
MatrixCol< const self_type, const value_type > col(size_t col) const
Matrix(size_t rows, size_t cols, std::initializer_list< T > const &init_list)
T & at(const size_t row, const size_t col)
Matrix(size_t rows, size_t cols, T init)
std::string to_string(T const &v)
Return a string representation of a given value.
Definition: string.hpp:381
View into a Matrix row.
Definition: row.hpp:60
void swap(Matrix &other)
container_type const & data() const
const_iterator end() const
bool operator==(Matrix< T > const &other) const
MatrixCol< self_type, value_type > col(size_t col)
MatrixRow< const self_type, const value_type > row(size_t row) const
MatrixRow< self_type, value_type > row(size_t row)
friend void swap(Matrix &lhs, Matrix &rhs)
bool operator!=(Matrix< T > const &other) const
const_iterator cend() const
Matrix(size_t rows, size_t cols, std::vector< T > const &data)
Matrix(size_t rows, size_t cols)
T const & at(const size_t row, const size_t col) const
Matrix(size_t rows, size_t cols, std::vector< T > &&data)
const_iterator begin() const
typename container_type::const_iterator const_iterator
Matrix & operator=(Matrix const &)=default
T & operator()(const size_t row, const size_t col)