A library for working with phylogenetic and population genetic data.
v0.32.0
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-2023 Lucas Czech
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 <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
36 
37 #include <cassert>
38 #include <stdexcept>
39 #include <string>
40 #include <vector>
41 
42 namespace genesis {
43 namespace utils {
44 
45 // =================================================================================================
46 // Forward declarations
47 // =================================================================================================
48 
49 template <typename T>
50 class Matrix;
51 
52 template <typename T>
53 void transpose_inplace( Matrix<T>& mat );
54 
55 // =================================================================================================
56 // Matrix
57 // =================================================================================================
58 
59 template <typename T>
60 class Matrix
61 {
62 public:
63 
64  // -------------------------------------------------------------
65  // Typedefs
66  // -------------------------------------------------------------
67 
69  using value_type = T;
70 
71  using container_type = std::vector<T>;
72  using iterator = typename container_type::iterator;
73  using const_iterator = typename container_type::const_iterator;
74 
75  // -------------------------------------------------------------
76  // Constructors and Rule of Five
77  // -------------------------------------------------------------
78 
80  : rows_(0)
81  , cols_(0)
82  , data_()
83  {}
84 
85  Matrix (size_t rows, size_t cols)
86  : rows_( rows )
87  , cols_( cols )
88  , data_( rows * cols )
89  {}
90 
91  Matrix (size_t rows, size_t cols, T init)
92  : rows_( rows )
93  , cols_( cols )
94  , data_( rows * cols, init )
95  {}
96 
97  Matrix( size_t rows, size_t cols, std::vector<T> const& data )
98  : rows_( rows )
99  , cols_( cols )
100  , data_( data )
101  {
102  if( rows * cols != data_.size() ) {
103  throw std::length_error(
104  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
105  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
106  std::to_string( rows * cols ) + " elements, but provided data contains " +
107  std::to_string( data_.size() ) + " elements."
108  );
109  }
110  }
111 
112  Matrix( size_t rows, size_t cols, std::vector<T>&& data )
113  : rows_( rows )
114  , cols_( cols )
115  , data_( std::move( data ))
116  {
117  if( rows * cols != data_.size() ) {
118  throw std::length_error(
119  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
120  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
121  std::to_string( rows * cols ) + " elements, but provided data contains " +
122  std::to_string( data_.size() ) + " elements."
123  );
124  }
125  }
126 
127  Matrix (size_t rows, size_t cols, std::initializer_list<T> const& init_list)
128  : rows_(rows)
129  , cols_(cols)
130  , data_(rows * cols)
131  {
132  if (init_list.size() != size()) {
133  throw std::length_error(
134  std::string(__PRETTY_FUNCTION__) + ": length_error. Expecting " +
135  std::to_string( rows ) + " * " + std::to_string( cols ) + " = " +
136  std::to_string( rows * cols ) + " elements, but provided data contains " +
137  std::to_string( init_list.size() ) + " elements."
138  );
139  }
140 
141  size_t i = 0;
142  for (T const& v : init_list) {
143  data_[i] = v;
144  ++i;
145  }
146  }
147 
148  ~Matrix() = default;
149 
150  Matrix(Matrix const&) = default;
151  Matrix(Matrix&&) = default;
152 
153  Matrix& operator= (Matrix const&) = default;
154  Matrix& operator= (Matrix&&) = default;
155 
156  void swap (Matrix& other)
157  {
158  using std::swap;
159  swap(rows_, other.rows_);
160  swap(cols_, other.cols_);
161  swap(data_, other.data_);
162  }
163 
164  friend void swap( Matrix& lhs, Matrix& rhs )
165  {
166  lhs.swap( rhs );
167  }
168 
169  // Transpose inplace needs access to our internals.
170  friend void transpose_inplace<>( Matrix<T>& );
171 
172  // -------------------------------------------------------------
173  // Properties
174  // -------------------------------------------------------------
175 
176  size_t rows() const
177  {
178  return rows_;
179  }
180 
181  size_t cols() const
182  {
183  return cols_;
184  }
185 
186  size_t size() const
187  {
188  return rows_ * cols_;
189  }
190 
191  bool empty() const
192  {
193  return size() == 0;
194  }
195 
196  container_type const& data() const
197  {
198  return data_;
199  }
200 
201  // -------------------------------------------------------------
202  // Element Access
203  // -------------------------------------------------------------
204 
205  T& at (const size_t row, const size_t col)
206  {
207  if (row >= rows_ || col >= cols_) {
208  throw std::out_of_range(
209  "Matrix index out of range. Accessing [" + std::to_string(row) + "," +
210  std::to_string( col ) + "] of a Matrix with dimensions [" +
211  std::to_string( rows_ ) + "," + std::to_string( cols_ ) + "]"
212  );
213  }
214  return data_[row * cols_ + col];
215  }
216 
217  T const& at (const size_t row, const size_t col) const
218  {
219  if (row >= rows_ || col >= cols_) {
220  throw std::out_of_range(
221  "Matrix index out of range. Accessing [" + std::to_string(row) + "," +
222  std::to_string( col ) + "] of a Matrix with dimensions [" +
223  std::to_string( rows_ ) + "," + std::to_string( cols_ ) + "]"
224  );
225  }
226  return data_[row * cols_ + col];
227  }
228 
229  T& operator () (const size_t row, const size_t col)
230  {
231  assert( row < rows_ );
232  assert( col < cols_ );
233  return data_[row * cols_ + col];
234  }
235 
236  T const& operator () (const size_t row, const size_t col) const
237  {
238  assert( row < rows_ );
239  assert( col < cols_ );
240  return data_[row * cols_ + col];
241  }
242 
243  // -------------------------------------------------------------
244  // Slicing
245  // -------------------------------------------------------------
246 
248  {
249  if( row >= rows_ ) {
250  throw std::out_of_range(
251  "Matrix row index out of range. Accessing row " + std::to_string( row ) +
252  " of a Matrix with " + std::to_string( rows_ ) + " rows."
253  );
254  }
255 
256  return MatrixRow<self_type, value_type>( *this, row );
257  }
258 
260  {
261  if( row >= rows_ ) {
262  throw std::out_of_range(
263  "Matrix row index out of range. Accessing row " + std::to_string( row ) +
264  " of a Matrix with " + std::to_string( rows_ ) + " rows."
265  );
266  }
267 
269  }
270 
272  {
273  if( col >= cols_ ) {
274  throw std::out_of_range(
275  "Matrix column index out of range. Accessing column " + std::to_string( col ) +
276  " of a Matrix with " + std::to_string( cols_ ) + " columns."
277  );
278  }
279 
280  return MatrixCol<self_type, value_type>( *this, col );
281  }
282 
284  {
285  if( col >= cols_ ) {
286  throw std::out_of_range(
287  "Matrix column index out of range. Accessing column " + std::to_string( col ) +
288  " of a Matrix with " + std::to_string( cols_ ) + " columns."
289  );
290  }
291 
293  }
294 
295  // -------------------------------------------------------------
296  // Iterators
297  // -------------------------------------------------------------
298 
300  {
301  return data_.begin();
302  }
303 
305  {
306  return data_.end();
307  }
308 
310  {
311  return data_.begin();
312  }
313 
315  {
316  return data_.end();
317  }
318 
320  {
321  return data_.cbegin();
322  }
323 
325  {
326  return data_.cend();
327  }
328 
329  // -------------------------------------------------------------
330  // Operators
331  // -------------------------------------------------------------
332 
333  bool operator == ( Matrix<T> const& other ) const
334  {
335  return rows_ == other.rows_
336  && cols_ == other.cols_
337  && data_ == other.data_;
338  }
339 
340  bool operator != ( Matrix<T> const& other ) const
341  {
342  return !(*this == other);
343  }
344 
345  // -------------------------------------------------------------
346  // Data Members
347  // -------------------------------------------------------------
348 
349 private:
350 
351  size_t rows_;
352  size_t cols_;
353  container_type data_;
354 };
355 
356 } // namespace utils
357 } // namespace genesis
358 
359 #endif // include guard
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::utils::Matrix::empty
bool empty() const
Definition: containers/matrix.hpp:191
genesis::utils::Matrix::swap
friend void swap(Matrix &lhs, Matrix &rhs)
Definition: containers/matrix.hpp:164
genesis::utils::Matrix::end
const_iterator end() const
Definition: containers/matrix.hpp:314
genesis::utils::Matrix::operator!=
bool operator!=(Matrix< T > const &other) const
Definition: containers/matrix.hpp:340
genesis::utils::Matrix::cols
size_t cols() const
Definition: containers/matrix.hpp:181
genesis::utils::Matrix::~Matrix
~Matrix()=default
genesis::utils::Matrix::Matrix
Matrix(size_t rows, size_t cols, std::initializer_list< T > const &init_list)
Definition: containers/matrix.hpp:127
genesis::utils::transpose_inplace
void transpose_inplace(Matrix< T > &mat)
Transpose a Matrix inplace, without allocating a new Matrix.
Definition: utils/containers/matrix/operators.hpp:146
genesis::utils::Matrix::end
iterator end()
Definition: containers/matrix.hpp:304
genesis::utils::Matrix::swap
void swap(Matrix &other)
Definition: containers/matrix.hpp:156
genesis::utils::Matrix::col
MatrixCol< self_type, value_type > col(size_t col)
Definition: containers/matrix.hpp:271
genesis::utils::Matrix::Matrix
Matrix(size_t rows, size_t cols, std::vector< T > &&data)
Definition: containers/matrix.hpp:112
genesis::utils::Matrix::at
T const & at(const size_t row, const size_t col) const
Definition: containers/matrix.hpp:217
genesis::utils::Matrix< size_t >
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: function/genome_locus.hpp:52
genesis::utils::Matrix::operator()
T & operator()(const size_t row, const size_t col)
Definition: containers/matrix.hpp:229
genesis::utils::Matrix::cend
const_iterator cend() const
Definition: containers/matrix.hpp:324
genesis::utils::Matrix::Matrix
Matrix(size_t rows, size_t cols, std::vector< T > const &data)
Definition: containers/matrix.hpp:97
genesis::utils::Matrix::operator==
bool operator==(Matrix< T > const &other) const
Definition: containers/matrix.hpp:333
genesis::utils::Matrix::at
T & at(const size_t row, const size_t col)
Definition: containers/matrix.hpp:205
genesis::utils::Matrix< size_t >::const_iterator
typename container_type::const_iterator const_iterator
Definition: containers/matrix.hpp:73
genesis::utils::Matrix::data
container_type const & data() const
Definition: containers/matrix.hpp:196
col.hpp
genesis::utils::MatrixCol
View into a Matrix column.
Definition: col.hpp:60
genesis::utils::Matrix::operator=
Matrix & operator=(Matrix const &)=default
genesis::utils::Matrix::col
MatrixCol< const self_type, const value_type > col(size_t col) const
Definition: containers/matrix.hpp:283
genesis::utils::Matrix::Matrix
Matrix(size_t rows, size_t cols)
Definition: containers/matrix.hpp:85
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
row.hpp
genesis::utils::Matrix< size_t >::value_type
size_t value_type
Definition: containers/matrix.hpp:69
genesis::utils::Matrix< size_t >::iterator
typename container_type::iterator iterator
Definition: containers/matrix.hpp:72
genesis::utils::Matrix::Matrix
Matrix(size_t rows, size_t cols, T init)
Definition: containers/matrix.hpp:91
genesis::utils::Matrix::Matrix
Matrix()
Definition: containers/matrix.hpp:79
genesis::utils::Matrix::begin
iterator begin()
Definition: containers/matrix.hpp:299
genesis::utils::Matrix::cbegin
const_iterator cbegin() const
Definition: containers/matrix.hpp:319
genesis::utils::Matrix< size_t >::container_type
std::vector< size_t > container_type
Definition: containers/matrix.hpp:71
genesis::utils::Matrix::row
MatrixRow< self_type, value_type > row(size_t row)
Definition: containers/matrix.hpp:247
genesis::utils::MatrixRow
View into a Matrix row.
Definition: row.hpp:60
genesis::utils::Matrix::row
MatrixRow< const self_type, const value_type > row(size_t row) const
Definition: containers/matrix.hpp:259
genesis::utils::Matrix::rows
size_t rows() const
Definition: containers/matrix.hpp:176
genesis::utils::Matrix::size
size_t size() const
Definition: containers/matrix.hpp:186
genesis::utils::Matrix::begin
const_iterator begin() const
Definition: containers/matrix.hpp:309