A toolkit for working with phylogenetic data.
v0.24.0
utils/containers/matrix/operators.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_MATRIX_OPERATORS_H_
2 #define GENESIS_UTILS_CONTAINERS_MATRIX_OPERATORS_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 
34 #include <cassert>
35 #include <ostream>
36 #include <sstream>
37 #include <stdexcept>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
44 
45 namespace genesis {
46 namespace utils {
47 
48 // =================================================================================================
49 // Helpful Functions
50 // =================================================================================================
51 
82 std::pair<size_t, size_t> triangular_indices( size_t k, size_t n );
83 
95 size_t triangular_index( size_t i, size_t j, size_t n );
96 
116 size_t triangular_size( size_t n );
117 
118 // =================================================================================================
119 // General Matrix Operators
120 // =================================================================================================
121 
125 template <typename T>
127 {
128  auto res = Matrix<T>( data.cols(), data.rows() );
129  for( size_t r = 0; r < data.rows(); ++r ) {
130  for( size_t c = 0; c < data.cols(); ++c ) {
131  res( c, r ) = data( r, c );
132  }
133  }
134  return res;
135 }
136 
141 template <typename T>
142 bool is_square( Matrix<T> const& data )
143 {
144  return data.rows() == data.cols();
145 }
146 
151 template <typename T>
152 bool is_symmetric( Matrix<T> const& data )
153 {
154  if( data.rows() != data.cols() ) {
155  return false;
156  }
157 
158  // We only need to check the upper triangle, and compare it to the lower triangle.
159  // Also, we use early stopping. Of course we do. Who wouldn't.
160  for( size_t i = 0; i < data.rows(); ++i ) {
161  for( size_t j = i + 1; j < data.cols(); ++j ) {
162  if( data( i, j ) != data( j, i ) ) {
163  return false;
164  }
165  }
166  }
167 
168  return true;
169 }
170 
174 template <typename T>
175 std::ostream& operator<< (std::ostream& os, const Matrix<T>& matrix)
176 {
177  for (size_t i = 0; i < matrix.rows(); ++i) {
178  for (size_t j = 0; j < matrix.cols(); ++j) {
179  os << matrix(i, j);
180  if (j < matrix.cols() - 1) {
181  os << " ";
182  }
183  }
184  os << "\n";
185  }
186  return os;
187 }
188 
192 template<>
193 std::ostream& operator<< (std::ostream& os, const Matrix<signed char>& matrix);
194 
198 template<>
199 std::ostream& operator<< (std::ostream& os, const Matrix<unsigned char>& matrix);
200 
205 template <typename T>
206 void print( std::ostream& out, Matrix<T> const& matrix, size_t rows = 10, size_t cols = 10 )
207 {
208  // If the user does not want limits, or uses wrong ones, just use everything!
209  if( rows == 0 || rows >= matrix.rows() ) {
210  rows = matrix.rows();
211  }
212  if( cols == 0 || cols >= matrix.cols() ) {
213  cols = matrix.cols();
214  }
215 
216  // Print as many rows and cols as wanted.
217  for (size_t i = 0; i < rows; ++i) {
218  for (size_t j = 0; j < cols; ++j) {
219  out << matrix(i, j);
220  if (j < matrix.cols() - 1) {
221  out << " ";
222  }
223  }
224  if( cols < matrix.cols() ) {
225  out << " ...";
226  }
227  out << "\n";
228  }
229  if( rows < matrix.rows() ) {
230  out << "...\n";
231  }
232 }
233 
242 template <typename T>
243 std::string print( Matrix<T> const& matrix, size_t rows = 10, size_t cols = 10 )
244 {
245  std::ostringstream out;
246  print( out, matrix, rows, cols );
247  return out.str();
248 }
249 
250 // =================================================================================================
251 // Swapping
252 // =================================================================================================
253 
257 template <typename T>
258 void swap_rows( Matrix<T>& data, size_t row_a, size_t row_b )
259 {
260  if( row_a >= data.rows() || row_b >= data.rows() ) {
261  throw std::invalid_argument( "Invalid row index for swap_rows()." );
262  }
263 
264  using std::swap;
265  for( size_t c = 0; c < data.cols(); ++c ) {
266  swap( data( row_a, c ), data( row_b, c ) );
267  }
268 }
269 
273 template <typename T>
274 void swap_cols( Matrix<T>& data, size_t col_a, size_t col_b )
275 {
276  if( col_a >= data.rows() || col_b >= data.rows() ) {
277  throw std::invalid_argument( "Invalid column index for swap_cols()." );
278  }
279 
280  using std::swap;
281  for( size_t r = 0; r < data.rows(); ++r ) {
282  swap( data( r, col_a ), data( r, col_b ) );
283  }
284 }
285 
286 } // namespace utils
287 } // namespace genesis
288 
289 #endif // include guard
Provides some valuable algorithms that are not part of the C++ 11 STL.
void swap(SequenceSet &lhs, SequenceSet &rhs)
Container namespace for all symbols of genesis in order to keep them separate when used as a library...
void swap_cols(Matrix< T > &data, size_t col_a, size_t col_b)
Swap (interchange) two columns of a Matrix, given their indices.
bool is_square(Matrix< T > const &data)
Return whether a Matrix is a square matrix, that is, whether its number of rows and number of columns...
void swap(NexusTaxa &lhs, NexusTaxa &rhs)
Definition: taxa.hpp:209
size_t triangular_size(size_t n)
Calculate the number of linear indices needed for a triangular Matrix of size n.
void swap_rows(Matrix< T > &data, size_t row_a, size_t row_b)
Swap (interchange) two rows of a Matrix, given their indices.
size_t triangular_index(size_t i, size_t j, size_t n)
Given indices i and j in a quadratic Matrix, find the corresponding linear index. ...
std::pair< size_t, size_t > triangular_indices(size_t k, size_t n)
Given a linear index in a upper triangular Matrix, find the corresponding Matrix indices.
void print(std::ostream &out, Matrix< T > const &matrix, size_t rows=10, size_t cols=10)
Print a Matrix to an out stream. See print( Matrix<T> const&, size_t, size_t ) for details...
bool is_symmetric(Matrix< T > const &data)
Return whether a Matrix is symmetric, i.e., whether it is square and m[ i, j ] == m[ j...
Matrix< T > transpose(Matrix< T > const &data)
Transpose a Matrix.