A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 matrix_is_symmetric( Matrix<T> const& data )
143 {
144  if( data.rows() != data.cols() ) {
145  return false;
146  }
147 
148  // We only need to check the upper triangle, and compare it to the lower triangle.
149  // Also, we use early stopping. Of course we do. Who wouldn't.
150  for( size_t i = 0; i < data.rows(); ++i ) {
151  for( size_t j = i + 1; j < data.cols(); ++j ) {
152  if( data( i, j ) != data( j, i ) ) {
153  return false;
154  }
155  }
156  }
157 
158  return true;
159 }
160 
164 template <typename T>
165 std::ostream& operator<< (std::ostream& os, const Matrix<T>& matrix)
166 {
167  for (size_t i = 0; i < matrix.rows(); ++i) {
168  for (size_t j = 0; j < matrix.cols(); ++j) {
169  os << matrix(i, j);
170  if (j < matrix.cols() - 1) {
171  os << " ";
172  }
173  }
174  os << "\n";
175  }
176  return os;
177 }
178 
183 template <typename T>
184 void print( std::ostream& out, Matrix<T> const& matrix, size_t rows = 10, size_t cols = 10 )
185 {
186  // If the user does not want limits, or uses wrong ones, just use everything!
187  if( rows == 0 || rows >= matrix.rows() ) {
188  rows = matrix.rows();
189  }
190  if( cols == 0 || cols >= matrix.cols() ) {
191  cols = matrix.cols();
192  }
193 
194  // Print as many rows and cols as wanted.
195  for (size_t i = 0; i < rows; ++i) {
196  for (size_t j = 0; j < cols; ++j) {
197  out << matrix(i, j);
198  if (j < matrix.cols() - 1) {
199  out << " ";
200  }
201  }
202  if( cols < matrix.cols() ) {
203  out << " ...";
204  }
205  out << "\n";
206  }
207  if( rows < matrix.rows() ) {
208  out << "...\n";
209  }
210 }
211 
220 template <typename T>
221 std::string print( Matrix<T> const& matrix, size_t rows = 10, size_t cols = 10 )
222 {
223  std::ostringstream out;
224  print( out, matrix, rows, cols );
225  return out.str();
226 }
227 
228 // =================================================================================================
229 // Swapping
230 // =================================================================================================
231 
235 template <typename T>
236 void matrix_swap_rows( Matrix<T>& data, size_t row_a, size_t row_b )
237 {
238  if( row_a >= data.rows() || row_b >= data.rows() ) {
239  throw std::invalid_argument( "Invalid row index for swap_rows()." );
240  }
241 
242  using std::swap;
243  for( size_t c = 0; c < data.cols(); ++c ) {
244  swap( data( row_a, c ), data( row_b, c ) );
245  }
246 }
247 
251 template <typename T>
252 void matrix_swap_cols( Matrix<T>& data, size_t col_a, size_t col_b )
253 {
254  if( col_a >= data.rows() || col_b >= data.rows() ) {
255  throw std::invalid_argument( "Invalid column index for swap_cols()." );
256  }
257 
258  using std::swap;
259  for( size_t r = 0; r < data.rows(); ++r ) {
260  swap( data( r, col_a ), data( r, col_b ) );
261  }
262 }
263 
264 } // namespace utils
265 } // namespace genesis
266 
267 #endif // include guard
Provides some valuable algorithms that are not part of the C++ 11 STL.
void matrix_swap_cols(Matrix< T > &data, size_t col_a, size_t col_b)
Swap (interchange) two columns of a Matrix, given their indices.
void swap(SequenceSet &lhs, SequenceSet &rhs)
void matrix_swap_rows(Matrix< T > &data, size_t row_a, size_t row_b)
Swap (interchange) two rows of a Matrix, given their indices.
void swap(NexusTaxa &lhs, NexusTaxa &rhs)
Definition: taxa.hpp:207
size_t triangular_size(size_t n)
Calculate the number of linear indices needed for a triangular Matrix of size n.
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 matrix_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 > matrix_transpose(Matrix< T > const &data)
Transpose a Matrix.