| 1 | /*! |
|---|
| 2 | * \file |
|---|
| 3 | * \brief Various functions on vectors and matrices - header file |
|---|
| 4 | * \author Tony Ottosson, Adam Piatyszek, Conrad Sanderson, Mark Dobossy |
|---|
| 5 | * and Martin Senst |
|---|
| 6 | * |
|---|
| 7 | * ------------------------------------------------------------------------- |
|---|
| 8 | * |
|---|
| 9 | * IT++ - C++ library of mathematical, signal processing, speech processing, |
|---|
| 10 | * and communications classes and functions |
|---|
| 11 | * |
|---|
| 12 | * Copyright (C) 1995-2007 (see AUTHORS file for a list of contributors) |
|---|
| 13 | * |
|---|
| 14 | * This program is free software; you can redistribute it and/or modify |
|---|
| 15 | * it under the terms of the GNU General Public License as published by |
|---|
| 16 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| 17 | * (at your option) any later version. |
|---|
| 18 | * |
|---|
| 19 | * This program is distributed in the hope that it will be useful, |
|---|
| 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 22 | * GNU General Public License for more details. |
|---|
| 23 | * |
|---|
| 24 | * You should have received a copy of the GNU General Public License |
|---|
| 25 | * along with this program; if not, write to the Free Software |
|---|
| 26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 27 | * |
|---|
| 28 | * ------------------------------------------------------------------------- |
|---|
| 29 | */ |
|---|
| 30 | |
|---|
| 31 | #ifndef MATFUNC_H |
|---|
| 32 | #define MATFUNC_H |
|---|
| 33 | |
|---|
| 34 | #include <itpp/base/mat.h> |
|---|
| 35 | #include <itpp/base/math/log_exp.h> |
|---|
| 36 | #include <itpp/base/math/elem_math.h> |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | namespace itpp { |
|---|
| 40 | |
|---|
| 41 | /*! |
|---|
| 42 | \addtogroup matrix_functions |
|---|
| 43 | \brief Functions on vectors and matrices |
|---|
| 44 | */ |
|---|
| 45 | //!@{ |
|---|
| 46 | |
|---|
| 47 | //! Length of vector |
|---|
| 48 | template<class T> |
|---|
| 49 | int length(const Vec<T> &v) { return v.length(); } |
|---|
| 50 | |
|---|
| 51 | //! Length of vector |
|---|
| 52 | template<class T> |
|---|
| 53 | int size(const Vec<T> &v) { return v.length(); } |
|---|
| 54 | |
|---|
| 55 | //! Sum of all elements in the vector |
|---|
| 56 | template<class T> |
|---|
| 57 | T sum(const Vec<T> &v) |
|---|
| 58 | { |
|---|
| 59 | T M = 0; |
|---|
| 60 | |
|---|
| 61 | for (int i=0;i<v.length();i++) |
|---|
| 62 | M += v[i]; |
|---|
| 63 | |
|---|
| 64 | return M; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | /*! |
|---|
| 68 | * \brief Sum of elements in the matrix \c m, either along columns or rows |
|---|
| 69 | * |
|---|
| 70 | * <tt>sum(m) = sum(m, 1)</tt> returns a vector where the elements are sum |
|---|
| 71 | * over each column, whereas <tt>sum(m, 2)</tt> returns a vector where the |
|---|
| 72 | * elements are sum over each row. |
|---|
| 73 | */ |
|---|
| 74 | template<class T> |
|---|
| 75 | Vec<T> sum(const Mat<T> &m, int dim=1) |
|---|
| 76 | { |
|---|
| 77 | it_assert((dim == 1) || (dim == 2), "sum: dimension need to be 1 or 2"); |
|---|
| 78 | Vec<T> out; |
|---|
| 79 | |
|---|
| 80 | if (dim == 1) { |
|---|
| 81 | out.set_size(m.cols(), false); |
|---|
| 82 | |
|---|
| 83 | for (int i=0; i<m.cols(); i++) |
|---|
| 84 | out(i) = sum(m.get_col(i)); |
|---|
| 85 | } |
|---|
| 86 | else { |
|---|
| 87 | out.set_size(m.rows(), false); |
|---|
| 88 | |
|---|
| 89 | for (int i=0; i<m.rows(); i++) |
|---|
| 90 | out(i) = sum(m.get_row(i)); |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | return out; |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | //! Sum of all elements in the given matrix. Fast version of sum(sum(X)) |
|---|
| 98 | template<class T> |
|---|
| 99 | T sumsum(const Mat<T> &X) |
|---|
| 100 | { |
|---|
| 101 | const T * X_data = X._data(); |
|---|
| 102 | const int X_datasize = X._datasize(); |
|---|
| 103 | T acc = 0; |
|---|
| 104 | |
|---|
| 105 | for(int i=0;i<X_datasize;i++) |
|---|
| 106 | acc += X_data[i]; |
|---|
| 107 | |
|---|
| 108 | return acc; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | |
|---|
| 112 | //! Sum of square of the elements in a vector |
|---|
| 113 | template<class T> |
|---|
| 114 | T sum_sqr(const Vec<T> &v) |
|---|
| 115 | { |
|---|
| 116 | T M=0; |
|---|
| 117 | |
|---|
| 118 | for (int i=0; i<v.length(); i++) |
|---|
| 119 | M += v[i] * v[i]; |
|---|
| 120 | |
|---|
| 121 | return M; |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | /*! |
|---|
| 125 | * \brief Sum of the square of elements in the matrix \c m |
|---|
| 126 | * |
|---|
| 127 | * <tt>sum(m) = sum(m, 1)</tt> returns a vector where the elements are sum |
|---|
| 128 | * squared over each column, whereas <tt>sum(m, 2)</tt> returns a vector |
|---|
| 129 | * where the elements are sum squared over each row |
|---|
| 130 | */ |
|---|
| 131 | template<class T> |
|---|
| 132 | Vec<T> sum_sqr(const Mat<T> &m, int dim=1) |
|---|
| 133 | { |
|---|
| 134 | it_assert((dim == 1) || (dim == 2), "sum_sqr: dimension need to be 1 or 2"); |
|---|
| 135 | Vec<T> out; |
|---|
| 136 | |
|---|
| 137 | if (dim == 1) { |
|---|
| 138 | out.set_size(m.cols(), false); |
|---|
| 139 | |
|---|
| 140 | for (int i=0; i<m.cols(); i++) |
|---|
| 141 | out(i) = sum_sqr(m.get_col(i)); |
|---|
| 142 | } |
|---|
| 143 | else { |
|---|
| 144 | out.set_size(m.rows(), false); |
|---|
| 145 | |
|---|
| 146 | for (int i=0; i<m.rows(); i++) |
|---|
| 147 | out(i) = sum_sqr(m.get_row(i)); |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | return out; |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | //! Cumulative sum of all elements in the vector |
|---|
| 154 | template<class T> |
|---|
| 155 | Vec<T> cumsum(const Vec<T> &v) |
|---|
| 156 | { |
|---|
| 157 | Vec<T> out(v.size()); |
|---|
| 158 | |
|---|
| 159 | out(0)=v(0); |
|---|
| 160 | for (int i=1; i<v.size(); i++) |
|---|
| 161 | out(i) = out(i-1) + v(i); |
|---|
| 162 | |
|---|
| 163 | return out; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | /*! |
|---|
| 167 | * \brief Cumulative sum of elements in the matrix \c m |
|---|
| 168 | * |
|---|
| 169 | * <tt>cumsum(m) = cumsum(m, 1)</tt> returns a matrix where the elements |
|---|
| 170 | * are sums over each column, whereas <tt>cumsum(m, 2)</tt> returns a |
|---|
| 171 | * matrix where the elements are sums over each row |
|---|
| 172 | */ |
|---|
| 173 | template<class T> |
|---|
| 174 | Mat<T> cumsum(const Mat<T> &m, int dim=1) |
|---|
| 175 | { |
|---|
| 176 | it_assert((dim == 1) || (dim == 2), "cumsum: dimension need to be 1 or 2"); |
|---|
| 177 | Mat<T> out(m.rows(), m.cols()); |
|---|
| 178 | |
|---|
| 179 | if (dim == 1) { |
|---|
| 180 | for (int i=0; i<m.cols(); i++) |
|---|
| 181 | out.set_col(i, cumsum(m.get_col(i))); |
|---|
| 182 | } else { |
|---|
| 183 | for (int i=0; i<m.rows(); i++) |
|---|
| 184 | out.set_row(i, cumsum(m.get_row(i))); |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | return out; |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | //! The product of all elements in the vector |
|---|
| 191 | template<class T> |
|---|
| 192 | T prod(const Vec<T> &v) |
|---|
| 193 | { |
|---|
| 194 | it_assert(v.size() >= 1, "prod: size of vector should be at least 1"); |
|---|
| 195 | T out = v(0); |
|---|
| 196 | |
|---|
| 197 | for (int i=1; i<v.size(); i++) |
|---|
| 198 | out *= v(i); |
|---|
| 199 | |
|---|
| 200 | return out; |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | /*! |
|---|
| 204 | * \brief Product of elements in the matrix \c m |
|---|
| 205 | * |
|---|
| 206 | * <tt>prod(m) = prod(m, 1)</tt> returns a vector where the elements are |
|---|
| 207 | * products over each column, whereas <tt>prod(m, 2)</tt> returns a vector |
|---|
| 208 | * where the elements are products over each row |
|---|
| 209 | */ |
|---|
| 210 | template<class T> |
|---|
| 211 | Vec<T> prod(const Mat<T> &m, int dim=1) |
|---|
| 212 | { |
|---|
| 213 | it_assert((dim == 1) || (dim == 2), "prod: dimension need to be 1 or 2"); |
|---|
| 214 | Vec<T> out(m.cols()); |
|---|
| 215 | |
|---|
| 216 | if (dim == 1) { |
|---|
| 217 | it_assert((m.cols() >= 1) && (m.rows() >= 1), |
|---|
| 218 | "prod: number of columns should be at least 1"); |
|---|
| 219 | out.set_size(m.cols(), false); |
|---|
| 220 | |
|---|
| 221 | for (int i=0; i<m.cols(); i++) |
|---|
| 222 | out(i) = prod(m.get_col(i)); |
|---|
| 223 | } |
|---|
| 224 | else { |
|---|
| 225 | it_assert((m.cols() >= 1) && (m.rows() >= 1), |
|---|
| 226 | "prod: number of rows should be at least 1"); |
|---|
| 227 | out.set_size(m.rows(), false); |
|---|
| 228 | |
|---|
| 229 | for (int i=0; i<m.rows(); i++) |
|---|
| 230 | out(i) = prod(m.get_row(i)); |
|---|
| 231 | } |
|---|
| 232 | return out; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | //! Vector cross product. Vectors need to be of size 3 |
|---|
| 236 | template<class T> |
|---|
| 237 | Vec<T> cross(const Vec<T> &v1, const Vec<T> &v2) |
|---|
| 238 | { |
|---|
| 239 | it_assert((v1.size() == 3) && (v2.size() == 3), |
|---|
| 240 | "cross: vectors should be of size 3"); |
|---|
| 241 | |
|---|
| 242 | Vec<T> r(3); |
|---|
| 243 | |
|---|
| 244 | r(0) = v1(1) * v2(2) - v1(2) * v2(1); |
|---|
| 245 | r(1) = v1(2) * v2(0) - v1(0) * v2(2); |
|---|
| 246 | r(2) = v1(0) * v2(1) - v1(1) * v2(0); |
|---|
| 247 | |
|---|
| 248 | return r; |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | |
|---|
| 252 | //! Zero-pad a vector to size n |
|---|
| 253 | template<class T> |
|---|
| 254 | Vec<T> zero_pad(const Vec<T> &v, int n) |
|---|
| 255 | { |
|---|
| 256 | it_assert(n >= v.size(), "zero_pad() cannot shrink the vector!"); |
|---|
| 257 | Vec<T> v2(n); |
|---|
| 258 | v2.set_subvector(0, v.size()-1, v); |
|---|
| 259 | if (n > v.size()) |
|---|
| 260 | v2.set_subvector(v.size(), n-1, T(0)); |
|---|
| 261 | |
|---|
| 262 | return v2; |
|---|
| 263 | } |
|---|
| 264 | |
|---|
| 265 | //! Zero-pad a vector to the nearest greater power of two |
|---|
| 266 | template<class T> |
|---|
| 267 | Vec<T> zero_pad(const Vec<T> &v) |
|---|
| 268 | { |
|---|
| 269 | int n = pow2i(levels2bits(v.size())); |
|---|
| 270 | |
|---|
| 271 | return (n == v.size()) ? v : zero_pad(v, n); |
|---|
| 272 | } |
|---|
| 273 | |
|---|
| 274 | //! Zero-pad a matrix to size rows x cols |
|---|
| 275 | template<class T> |
|---|
| 276 | Mat<T> zero_pad(const Mat<T> &m, int rows, int cols) |
|---|
| 277 | { |
|---|
| 278 | it_assert((rows >= m.rows()) && (cols >= m.cols()), |
|---|
| 279 | "zero_pad() cannot shrink the matrix!"); |
|---|
| 280 | Mat<T> m2(rows, cols); |
|---|
| 281 | m2.set_submatrix(0,m.rows()-1,0,m.cols()-1, m); |
|---|
| 282 | if (cols > m.cols()) // Zero |
|---|
| 283 | m2.set_submatrix(0,m.rows()-1, m.cols(),cols-1, T(0)); |
|---|
| 284 | if (rows > m.rows()) // Zero |
|---|
| 285 | m2.set_submatrix(m.rows(), rows-1, 0, cols-1, T(0)); |
|---|
| 286 | |
|---|
| 287 | return m2; |
|---|
| 288 | } |
|---|
| 289 | |
|---|
| 290 | |
|---|
| 291 | //! Return zero if indexing outside the vector \c v otherwise return the |
|---|
| 292 | //! element \c index |
|---|
| 293 | template<class T> |
|---|
| 294 | T index_zero_pad(const Vec<T> &v, const int index) |
|---|
| 295 | { |
|---|
| 296 | if (index >= 0 && index < v.size()) |
|---|
| 297 | return v(index); |
|---|
| 298 | else |
|---|
| 299 | return T(0); |
|---|
| 300 | } |
|---|
| 301 | |
|---|
| 302 | |
|---|
| 303 | //! Transposition of the matrix \c m returning the transposed matrix in \c out |
|---|
| 304 | template<class T> |
|---|
| 305 | void transpose(const Mat<T> &m, Mat<T> &out) { out = m.T(); } |
|---|
| 306 | |
|---|
| 307 | //! Transposition of the matrix \c m |
|---|
| 308 | template<class T> |
|---|
| 309 | Mat<T> transpose(const Mat<T> &m) { return m.T(); } |
|---|
| 310 | |
|---|
| 311 | |
|---|
| 312 | //! Hermitian transpose (complex conjugate transpose) of the matrix \c m |
|---|
| 313 | //! returning the transposed matrix in \c out |
|---|
| 314 | template<class T> |
|---|
| 315 | void hermitian_transpose(const Mat<T> &m, Mat<T> &out) { out = m.H(); } |
|---|
| 316 | |
|---|
| 317 | //! Hermitian transpose (complex conjugate transpose) of the matrix \c m |
|---|
| 318 | template<class T> |
|---|
| 319 | Mat<T> hermitian_transpose(const Mat<T> &m) { return m.H(); } |
|---|
| 320 | |
|---|
| 321 | |
|---|
| 322 | |
|---|
| 323 | /*! |
|---|
| 324 | * \brief Returns true if matrix \c X is hermitian, false otherwise |
|---|
| 325 | * \author M. Szalay |
|---|
| 326 | * |
|---|
| 327 | * A square matrix \f$\mathbf{X}\f$ is hermitian if |
|---|
| 328 | * \f[ |
|---|
| 329 | * \mathbf{X} = \mathbf{X}^H |
|---|
| 330 | * \f] |
|---|
| 331 | */ |
|---|
| 332 | template<class Num_T> |
|---|
| 333 | bool is_hermitian(const Mat<Num_T>& X) { |
|---|
| 334 | |
|---|
| 335 | if (X == X.H() ) |
|---|
| 336 | return true; |
|---|
| 337 | else |
|---|
| 338 | return false; |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | /*! |
|---|
| 342 | * \brief Returns true if matrix \c X is unitary, false otherwise |
|---|
| 343 | * \author M. Szalay |
|---|
| 344 | * |
|---|
| 345 | * A square matrix \f$\mathbf{X}\f$ is unitary if |
|---|
| 346 | * \f[ |
|---|
| 347 | * \mathbf{X}^H = \mathbf{X}^{-1} |
|---|
| 348 | * \f] |
|---|
| 349 | */ |
|---|
| 350 | template<class Num_T> |
|---|
| 351 | bool is_unitary(const Mat<Num_T>& X) { |
|---|
| 352 | |
|---|
| 353 | if ( inv(X) == X.H() ) |
|---|
| 354 | return true; |
|---|
| 355 | else |
|---|
| 356 | return false; |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | |
|---|
| 360 | /*! |
|---|
| 361 | * \relates Vec |
|---|
| 362 | * \brief Creates a vector with \c n copies of the vector \c v |
|---|
| 363 | * \author Martin Senst |
|---|
| 364 | * |
|---|
| 365 | * \param v Vector to be repeated |
|---|
| 366 | * \param n Number of times to repeat \c v |
|---|
| 367 | */ |
|---|
| 368 | template<class T> |
|---|
| 369 | Vec<T> repmat(const Vec<T> &v, int n) |
|---|
| 370 | { |
|---|
| 371 | it_assert(n > 0, "repmat(): Wrong repetition parameter"); |
|---|
| 372 | int data_length = v.length(); |
|---|
| 373 | it_assert(data_length > 0, "repmat(): Input vector can not be empty"); |
|---|
| 374 | Vec<T> assembly(data_length * n); |
|---|
| 375 | for (int j = 0; j < n; ++j) { |
|---|
| 376 | assembly.set_subvector(j * data_length, v); |
|---|
| 377 | } |
|---|
| 378 | return assembly; |
|---|
| 379 | } |
|---|
| 380 | |
|---|
| 381 | |
|---|
| 382 | /*! |
|---|
| 383 | * \relates Mat |
|---|
| 384 | * \brief Creates a matrix with \c m by \c n copies of the matrix \c data |
|---|
| 385 | * \author Mark Dobossy |
|---|
| 386 | * |
|---|
| 387 | * \param data Matrix to be repeated |
|---|
| 388 | * \param m Number of times to repeat data vertically |
|---|
| 389 | * \param n Number of times to repeat data horizontally |
|---|
| 390 | */ |
|---|
| 391 | template<class T> |
|---|
| 392 | Mat<T> repmat(const Mat<T> &data, int m, int n) |
|---|
| 393 | { |
|---|
| 394 | it_assert((m > 0) && (n > 0), "repmat(): Wrong repetition parameters"); |
|---|
| 395 | int data_rows = data.rows(); |
|---|
| 396 | int data_cols = data.cols(); |
|---|
| 397 | it_assert((data_rows > 0) && (data_cols > 0), "repmat(): Input matrix can " |
|---|
| 398 | "not be empty"); |
|---|
| 399 | Mat<T> assembly(data_rows*m, data_cols*n); |
|---|
| 400 | for (int i = 0; i < m; ++i) { |
|---|
| 401 | for (int j = 0; j < n; ++j) { |
|---|
| 402 | assembly.set_submatrix(i*data_rows, j*data_cols, data); |
|---|
| 403 | } |
|---|
| 404 | } |
|---|
| 405 | return assembly; |
|---|
| 406 | } |
|---|
| 407 | |
|---|
| 408 | /*! |
|---|
| 409 | * \relates Mat |
|---|
| 410 | * \brief Returns a matrix with \c m by \c n copies of the vector \c data |
|---|
| 411 | * \author Adam Piatyszek |
|---|
| 412 | * |
|---|
| 413 | * \param v Vector to be repeated |
|---|
| 414 | * \param m Number of times to repeat data vertically |
|---|
| 415 | * \param n Number of times to repeat data horizontally |
|---|
| 416 | * \param transpose Specifies the input vector orientation (column vector |
|---|
| 417 | * by default) |
|---|
| 418 | */ |
|---|
| 419 | template<class T> inline |
|---|
| 420 | Mat<T> repmat(const Vec<T> &v, int m, int n, bool transpose = false) |
|---|
| 421 | { |
|---|
| 422 | return repmat((transpose ? v.T() : Mat<T>(v)), m, n); |
|---|
| 423 | } |
|---|
| 424 | |
|---|
| 425 | |
|---|
| 426 | /*! |
|---|
| 427 | * \brief Computes the Kronecker product of two matrices |
|---|
| 428 | * |
|---|
| 429 | * <tt>K = kron(X, Y)</tt> returns the Kronecker tensor product of \c X |
|---|
| 430 | * and \c Y. The result is a large array formed by taking all possible |
|---|
| 431 | * products between the elements of \c X and those of \c Y. If \c X is |
|---|
| 432 | * <tt>(m x n)</tt> and \c Y is <tt>(p x q)</tt>, then <tt>kron(X, Y)</tt> |
|---|
| 433 | * is <tt>(m*p x n*q)</tt>. |
|---|
| 434 | * |
|---|
| 435 | * \author Adam Piatyszek |
|---|
| 436 | */ |
|---|
| 437 | template<class Num_T> |
|---|
| 438 | Mat<Num_T> kron(const Mat<Num_T>& X, const Mat<Num_T>& Y) |
|---|
| 439 | { |
|---|
| 440 | Mat<Num_T> result(X.rows() * Y.rows(), X.cols() * Y.cols()); |
|---|
| 441 | |
|---|
| 442 | for (int i = 0; i < X.rows(); i++) |
|---|
| 443 | for (int j = 0; j < X.cols(); j++) |
|---|
| 444 | result.set_submatrix(i * Y.rows(), j * Y.cols(), X(i, j) * Y); |
|---|
| 445 | |
|---|
| 446 | return result; |
|---|
| 447 | } |
|---|
| 448 | |
|---|
| 449 | |
|---|
| 450 | /*! |
|---|
| 451 | * \brief Square root of the complex square matrix \c A |
|---|
| 452 | * |
|---|
| 453 | * This function computes the matrix square root of the complex square |
|---|
| 454 | * matrix \c A. The implementation is based on the Matlab/Octave \c |
|---|
| 455 | * sqrtm() function. |
|---|
| 456 | * |
|---|
| 457 | * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester |
|---|
| 458 | * Centre for Computational Mathematics, Manchester, England, January 1999 |
|---|
| 459 | * |
|---|
| 460 | * \author Adam Piatyszek |
|---|
| 461 | */ |
|---|
| 462 | cmat sqrtm(const cmat& A); |
|---|
| 463 | |
|---|
| 464 | /*! |
|---|
| 465 | * \brief Square root of the real square matrix \c A |
|---|
| 466 | * |
|---|
| 467 | * This function computes the matrix square root of the real square matrix |
|---|
| 468 | * \c A. Please note that the returned matrix is complex. The |
|---|
| 469 | * implementation is based on the Matlab/Octave \c sqrtm() function. |
|---|
| 470 | * |
|---|
| 471 | * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester |
|---|
| 472 | * Centre for Computational Mathematics, Manchester, England, January 1999 |
|---|
| 473 | * |
|---|
| 474 | * \author Adam Piatyszek |
|---|
| 475 | */ |
|---|
| 476 | cmat sqrtm(const mat& A); |
|---|
| 477 | |
|---|
| 478 | //!@} |
|---|
| 479 | |
|---|
| 480 | |
|---|
| 481 | |
|---|
| 482 | // -------------------- Diagonal matrix functions ------------------------- |
|---|
| 483 | |
|---|
| 484 | //! \addtogroup diag |
|---|
| 485 | //!@{ |
|---|
| 486 | |
|---|
| 487 | /*! |
|---|
| 488 | * \brief Create a diagonal matrix using vector \c v as its diagonal |
|---|
| 489 | * |
|---|
| 490 | * All other matrix elements except the ones on its diagonal are set to |
|---|
| 491 | * zero. An optional parameter \c K can be used to shift the diagonal in |
|---|
| 492 | * the resulting matrix. By default \c K is equal to zero. |
|---|
| 493 | * |
|---|
| 494 | * The size of the diagonal matrix will be \f$n+|K| \times n+|K|\f$, where |
|---|
| 495 | * \f$n\f$ is the length of the input vector \c v. |
|---|
| 496 | */ |
|---|
| 497 | template<class T> |
|---|
| 498 | Mat<T> diag(const Vec<T> &v, const int K = 0) |
|---|
| 499 | { |
|---|
| 500 | Mat<T> m(v.size() + std::abs(K), v.size() + std::abs(K)); |
|---|
| 501 | m = T(0); |
|---|
| 502 | if (K>0) |
|---|
| 503 | for (int i=v.size()-1; i>=0; i--) |
|---|
| 504 | m(i,i+K) = v(i); |
|---|
| 505 | else |
|---|
| 506 | for (int i=v.size()-1; i>=0; i--) |
|---|
| 507 | m(i-K,i) = v(i); |
|---|
| 508 | |
|---|
| 509 | return m; |
|---|
| 510 | } |
|---|
| 511 | |
|---|
| 512 | /*! |
|---|
| 513 | * \brief Create a diagonal matrix using vector \c v as its diagonal |
|---|
| 514 | * |
|---|
| 515 | * All other matrix elements except the ones on its diagonal are set to |
|---|
| 516 | * zero. |
|---|
| 517 | * |
|---|
| 518 | * The size of the diagonal matrix will be \f$n \times n\f$, where \f$n\f$ |
|---|
| 519 | * is the length of the input vector \c v. |
|---|
| 520 | */ |
|---|
| 521 | template<class T> |
|---|
| 522 | void diag(const Vec<T> &v, Mat<T> &m) |
|---|
| 523 | { |
|---|
| 524 | m.set_size(v.size(), v.size(), false); |
|---|
| 525 | m = T(0); |
|---|
| 526 | for (int i=v.size()-1; i>=0; i--) |
|---|
| 527 | m(i,i) = v(i); |
|---|
| 528 | } |
|---|
| 529 | |
|---|
| 530 | /*! |
|---|
| 531 | * \brief Get the diagonal elements of the input matrix \c m |
|---|
| 532 | * |
|---|
| 533 | * The size of the output vector with diagonal elements will be |
|---|
| 534 | * \f$n = min(r, c)\f$, where \f$r \times c\f$ are the dimensions of |
|---|
| 535 | * matrix \c m. |
|---|
| 536 | */ |
|---|
| 537 | template<class T> |
|---|
| 538 | Vec<T> diag(const Mat<T> &m) |
|---|
| 539 | { |
|---|
| 540 | Vec<T> t(std::min(m.rows(), m.cols())); |
|---|
| 541 | |
|---|
| 542 | for (int i=0; i<t.size(); i++) |
|---|
| 543 | t(i) = m(i,i); |
|---|
| 544 | |
|---|
| 545 | return t; |
|---|
| 546 | } |
|---|
| 547 | |
|---|
| 548 | /*! |
|---|
| 549 | \brief Returns a matrix with the elements of the input vector \c main on |
|---|
| 550 | the diagonal and the elements of the input vector \c sup on the diagonal |
|---|
| 551 | row above. |
|---|
| 552 | |
|---|
| 553 | If the number of elements in the vector \c main is \f$n\f$, then the |
|---|
| 554 | number of elements in the input vector \c sup must be \f$n-1\f$. The |
|---|
| 555 | size of the return matrix will be \f$n \times n\f$. |
|---|
| 556 | */ |
|---|
| 557 | template<class T> |
|---|
| 558 | Mat<T> bidiag(const Vec<T> &main, const Vec<T> &sup) |
|---|
| 559 | { |
|---|
| 560 | it_assert(main.size() == sup.size()+1, "bidiag()"); |
|---|
| 561 | |
|---|
| 562 | int n=main.size(); |
|---|
| 563 | Mat<T> m(n, n); |
|---|
| 564 | m = T(0); |
|---|
| 565 | for (int i=0; i<n-1; i++) { |
|---|
| 566 | m(i,i) = main(i); |
|---|
| 567 | m(i,i+1) = sup(i); |
|---|
| 568 | } |
|---|
| 569 | m(n-1,n-1) = main(n-1); |
|---|
| 570 | |
|---|
| 571 | return m; |
|---|
| 572 | } |
|---|
| 573 | |
|---|
| 574 | /*! |
|---|
| 575 | \brief Returns in the output variable \c m a matrix with the elements of |
|---|
| 576 | the input vector \c main on the diagonal and the elements of the input |
|---|
| 577 | vector \c sup on the diagonal row above. |
|---|
| 578 | |
|---|
| 579 | If the number of elements in the vector \c main is \f$n\f$, then the |
|---|
| 580 | number of elements in the input vector \c sup must be \f$n-1\f$. The |
|---|
| 581 | size of the output matrix \c m will be \f$n \times n\f$. |
|---|
| 582 | */ |
|---|
| 583 | template<class T> |
|---|
| 584 | void bidiag(const Vec<T> &main, const Vec<T> &sup, Mat<T> &m) |
|---|
| 585 | { |
|---|
| 586 | it_assert(main.size() == sup.size()+1, "bidiag()"); |
|---|
| 587 | |
|---|
| 588 | int n=main.size(); |
|---|
| 589 | m.set_size(n, n); |
|---|
| 590 | m = T(0); |
|---|
| 591 | for (int i=0; i<n-1; i++) { |
|---|
| 592 | m(i,i) = main(i); |
|---|
| 593 | m(i,i+1) = sup(i); |
|---|
| 594 | } |
|---|
| 595 | m(n-1,n-1) = main(n-1); |
|---|
| 596 | } |
|---|
| 597 | |
|---|
| 598 | /*! |
|---|
| 599 | \brief Returns the main diagonal and the diagonal row above in the two |
|---|
| 600 | output vectors \c main and \c sup. |
|---|
| 601 | |
|---|
| 602 | The input matrix \c in must be a square \f$n \times n\f$ matrix. The |
|---|
| 603 | length of the output vector \c main will be \f$n\f$ and the length of |
|---|
| 604 | the output vector \c sup will be \f$n-1\f$. |
|---|
| 605 | */ |
|---|
| 606 | template<class T> |
|---|
| 607 | void bidiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup) |
|---|
| 608 | { |
|---|
| 609 | it_assert(m.rows() == m.cols(), "bidiag(): Matrix must be square!"); |
|---|
| 610 | |
|---|
| 611 | int n=m.cols(); |
|---|
| 612 | main.set_size(n); |
|---|
| 613 | sup.set_size(n-1); |
|---|
| 614 | for (int i=0; i<n-1; i++) { |
|---|
| 615 | main(i) = m(i,i); |
|---|
| 616 | sup(i) = m(i,i+1); |
|---|
| 617 | } |
|---|
| 618 | main(n-1) = m(n-1,n-1); |
|---|
| 619 | } |
|---|
| 620 | |
|---|
| 621 | /*! |
|---|
| 622 | \brief Returns a matrix with the elements of \c main on the diagonal, |
|---|
| 623 | the elements of \c sup on the diagonal row above, and the elements of \c |
|---|
| 624 | sub on the diagonal row below. |
|---|
| 625 | |
|---|
| 626 | If the length of the input vector \c main is \f$n\f$ then the lengths of |
|---|
| 627 | the vectors \c sup and \c sub must equal \f$n-1\f$. The size of the |
|---|
| 628 | return matrix will be \f$n \times n\f$. |
|---|
| 629 | */ |
|---|
| 630 | template<class T> |
|---|
| 631 | Mat<T> tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub) |
|---|
| 632 | { |
|---|
| 633 | it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()"); |
|---|
| 634 | |
|---|
| 635 | int n=main.size(); |
|---|
| 636 | Mat<T> m(n, n); |
|---|
| 637 | m = T(0); |
|---|
| 638 | for (int i=0; i<n-1; i++) { |
|---|
| 639 | m(i,i) = main(i); |
|---|
| 640 | m(i,i+1) = sup(i); |
|---|
| 641 | m(i+1,i) = sub(i); |
|---|
| 642 | } |
|---|
| 643 | m(n-1,n-1) = main(n-1); |
|---|
| 644 | |
|---|
| 645 | return m; |
|---|
| 646 | } |
|---|
| 647 | |
|---|
| 648 | /*! |
|---|
| 649 | \brief Returns in the output matrix \c m a matrix with the elements of |
|---|
| 650 | \c main on the diagonal, the elements of \c sup on the diagonal row |
|---|
| 651 | above, and the elements of \c sub on the diagonal row below. |
|---|
| 652 | |
|---|
| 653 | If the length of the input vector \c main is \f$n\f$ then the lengths of |
|---|
| 654 | the vectors \c sup and \c sub must equal \f$n-1\f$. The size of the |
|---|
| 655 | output matrix \c m will be \f$n \times n\f$. |
|---|
| 656 | */ |
|---|
| 657 | template<class T> |
|---|
| 658 | void tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub, Mat<T> &m) |
|---|
| 659 | { |
|---|
| 660 | it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()"); |
|---|
| 661 | |
|---|
| 662 | int n=main.size(); |
|---|
| 663 | m.set_size(n, n); |
|---|
| 664 | m = T(0); |
|---|
| 665 | for (int i=0; i<n-1; i++) { |
|---|
| 666 | m(i,i) = main(i); |
|---|
| 667 | m(i,i+1) = sup(i); |
|---|
| 668 | m(i+1,i) = sub(i); |
|---|
| 669 | } |
|---|
| 670 | m(n-1,n-1) = main(n-1); |
|---|
| 671 | } |
|---|
| 672 | |
|---|
| 673 | /*! |
|---|
| 674 | \brief Returns the main diagonal, the diagonal row above, and the |
|---|
| 675 | diagonal row below int the output vectors \c main, \c sup, and \c sub. |
|---|
| 676 | |
|---|
| 677 | The input matrix \c m must be a square \f$n \times n\f$ matrix. The |
|---|
| 678 | length of the output vector \c main will be \f$n\f$ and the length of |
|---|
| 679 | the output vectors \c sup and \c sup will be \f$n-1\f$. |
|---|
| 680 | */ |
|---|
| 681 | template<class T> |
|---|
| 682 | void tridiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup, Vec<T> &sub) |
|---|
| 683 | { |
|---|
| 684 | it_assert(m.rows() == m.cols(), "tridiag(): Matrix must be square!"); |
|---|
| 685 | |
|---|
| 686 | int n=m.cols(); |
|---|
| 687 | main.set_size(n); |
|---|
| 688 | sup.set_size(n-1); |
|---|
| 689 | sub.set_size(n-1); |
|---|
| 690 | for (int i=0; i<n-1; i++) { |
|---|
| 691 | main(i) = m(i,i); |
|---|
| 692 | sup(i) = m(i,i+1); |
|---|
| 693 | sub(i) = m(i+1,i); |
|---|
| 694 | } |
|---|
| 695 | main(n-1) = m(n-1,n-1); |
|---|
| 696 | } |
|---|
| 697 | |
|---|
| 698 | |
|---|
| 699 | /*! |
|---|
| 700 | \brief The trace of the matrix \c m, i.e. the sum of the diagonal elements. |
|---|
| 701 | */ |
|---|
| 702 | template<class T> |
|---|
| 703 | T trace(const Mat<T> &m) |
|---|
| 704 | { |
|---|
| 705 | return sum(diag(m)); |
|---|
| 706 | } |
|---|
| 707 | |
|---|
| 708 | //!@} |
|---|
| 709 | |
|---|
| 710 | |
|---|
| 711 | // ----------------- reshaping vectors and matrices ------------------------ |
|---|
| 712 | |
|---|
| 713 | //! \addtogroup reshaping |
|---|
| 714 | //!@{ |
|---|
| 715 | |
|---|
| 716 | //! Reverse the input vector |
|---|
| 717 | template<class T> |
|---|
| 718 | Vec<T> reverse(const Vec<T> &in) |
|---|
| 719 | { |
|---|
| 720 | int i, s=in.length(); |
|---|
| 721 | |
|---|
| 722 | Vec<T> out(s); |
|---|
| 723 | for (i=0;i<s;i++) |
|---|
| 724 | out[i]=in[s-1-i]; |
|---|
| 725 | return out; |
|---|
| 726 | } |
|---|
| 727 | |
|---|
| 728 | //! Row vectorize the matrix [(0,0) (0,1) ... (N-1,N-2) (N-1,N-1)] |
|---|
| 729 | template<class T> |
|---|
| 730 | Vec<T> rvectorize(const Mat<T> &m) |
|---|
| 731 | { |
|---|
| 732 | int i, j, n=0, r=m.rows(), c=m.cols(); |
|---|
| 733 | Vec<T> v(r * c); |
|---|
| 734 | |
|---|
| 735 | for (i=0; i<r; i++) |
|---|
| 736 | for (j=0; j<c; j++) |
|---|
| 737 | v(n++) = m(i,j); |
|---|
| 738 | |
|---|
| 739 | return v; |
|---|
| 740 | } |
|---|
| 741 | |
|---|
| 742 | //! Column vectorize the matrix [(0,0) (1,0) ... (N-2,N-1) (N-1,N-1)] |
|---|
| 743 | template<class T> |
|---|
| 744 | Vec<T> cvectorize(const Mat<T> &m) |
|---|
| 745 | { |
|---|
| 746 | int i, j, n=0, r=m.rows(), c=m.cols(); |
|---|
| 747 | Vec<T> v(r * c); |
|---|
| 748 | |
|---|
| 749 | for (j=0; j<c; j++) |
|---|
| 750 | for (i=0; i<r; i++) |
|---|
| 751 | v(n++) = m(i,j); |
|---|
| 752 | |
|---|
| 753 | return v; |
|---|
| 754 | } |
|---|
| 755 | |
|---|
| 756 | /*! |
|---|
| 757 | \brief Reshape the matrix into an rows*cols matrix |
|---|
| 758 | |
|---|
| 759 | The data is taken columnwise from the original matrix and written |
|---|
| 760 | columnwise into the new matrix. |
|---|
| 761 | */ |
|---|
| 762 | template<class T> |
|---|
| 763 | Mat<T> reshape(const Mat<T> &m, int rows, int cols) |
|---|
| 764 | { |
|---|
| 765 | it_assert_debug(m.rows()*m.cols() == rows*cols, "Mat<T>::reshape: Sizes must match"); |
|---|
| 766 | Mat<T> temp(rows, cols); |
|---|
| 767 | int i, j, ii=0, jj=0; |
|---|
| 768 | for (j=0; j<m.cols(); j++) { |
|---|
| 769 | for (i=0; i<m.rows(); i++) { |
|---|
| 770 | temp(ii++,jj) = m(i,j); |
|---|
| 771 | if (ii == rows) { |
|---|
| 772 | jj++; ii=0; |
|---|
| 773 | } |
|---|
| 774 | } |
|---|
| 775 | } |
|---|
| 776 | return temp; |
|---|
| 777 | } |
|---|
| 778 | |
|---|
| 779 | /*! |
|---|
| 780 | \brief Reshape the vector into an rows*cols matrix |
|---|
| 781 | |
|---|
| 782 | The data is element by element from the vector and written columnwise |
|---|
| 783 | into the new matrix. |
|---|
| 784 | */ |
|---|
| 785 | template<class T> |
|---|
| 786 | Mat<T> reshape(const Vec<T> &v, int rows, int cols) |
|---|
| 787 | { |
|---|
| 788 | it_assert_debug(v.size() == rows*cols, "Mat<T>::reshape: Sizes must match"); |
|---|
| 789 | Mat<T> temp(rows, cols); |
|---|
| 790 | int i, j, ii=0; |
|---|
| 791 | for (j=0; j<cols; j++) { |
|---|
| 792 | for (i=0; i<rows; i++) { |
|---|
| 793 | temp(i,j) = v(ii++); |
|---|
| 794 | } |
|---|
| 795 | } |
|---|
| 796 | return temp; |
|---|
| 797 | } |
|---|
| 798 | |
|---|
| 799 | //!@} |
|---|
| 800 | |
|---|
| 801 | |
|---|
| 802 | //! Returns \a true if all elements are ones and \a false otherwise |
|---|
| 803 | bool all(const bvec &testvec); |
|---|
| 804 | //! Returns \a true if any element is one and \a false otherwise |
|---|
| 805 | bool any(const bvec &testvec); |
|---|
| 806 | |
|---|
| 807 | //! \cond |
|---|
| 808 | |
|---|
| 809 | // ---------------------------------------------------------------------- |
|---|
| 810 | // Instantiations |
|---|
| 811 | // ---------------------------------------------------------------------- |
|---|
| 812 | |
|---|
| 813 | #ifdef HAVE_EXTERN_TEMPLATE |
|---|
| 814 | |
|---|
| 815 | extern template int length(const vec &v); |
|---|
| 816 | extern template int length(const cvec &v); |
|---|
| 817 | extern template int length(const svec &v); |
|---|
| 818 | extern template int length(const ivec &v); |
|---|
| 819 | extern template int length(const bvec &v); |
|---|
| 820 | |
|---|
| 821 | extern template double sum(const vec &v); |
|---|
| 822 | extern template std::complex<double> sum(const cvec &v); |
|---|
| 823 | extern template short sum(const svec &v); |
|---|
| 824 | extern template int sum(const ivec &v); |
|---|
| 825 | extern template bin sum(const bvec &v); |
|---|
| 826 | |
|---|
| 827 | extern template double sum_sqr(const vec &v); |
|---|
| 828 | extern template std::complex<double> sum_sqr(const cvec &v); |
|---|
| 829 | extern template short sum_sqr(const svec &v); |
|---|
| 830 | extern template int sum_sqr(const ivec &v); |
|---|
| 831 | extern template bin sum_sqr(const bvec &v); |
|---|
| 832 | |
|---|
| 833 | extern template vec cumsum(const vec &v); |
|---|
| 834 | extern template cvec cumsum(const cvec &v); |
|---|
| 835 | extern template svec cumsum(const svec &v); |
|---|
| 836 | extern template ivec cumsum(const ivec &v); |
|---|
| 837 | extern template bvec cumsum(const bvec &v); |
|---|
| 838 | |
|---|
| 839 | extern template double prod(const vec &v); |
|---|
| 840 | extern template std::complex<double> prod(const cvec &v); |
|---|
| 841 | extern template short prod(const svec &v); |
|---|
| 842 | extern template int prod(const ivec &v); |
|---|
| 843 | extern template bin prod(const bvec &v); |
|---|
| 844 | |
|---|
| 845 | extern template vec cross(const vec &v1, const vec &v2); |
|---|
| 846 | extern template cvec cross(const cvec &v1, const cvec &v2); |
|---|
| 847 | extern template ivec cross(const ivec &v1, const ivec &v2); |
|---|
| 848 | extern template svec cross(const svec &v1, const svec &v2); |
|---|
| 849 | extern template bvec cross(const bvec &v1, const bvec &v2); |
|---|
| 850 | |
|---|
| 851 | extern template vec reverse(const vec &in); |
|---|
| 852 | extern template cvec reverse(const cvec &in); |
|---|
| 853 | extern template svec reverse(const svec &in); |
|---|
| 854 | extern template ivec reverse(const ivec &in); |
|---|
| 855 | extern template bvec reverse(const bvec &in); |
|---|
| 856 | |
|---|
| 857 | extern template vec zero_pad(const vec &v, int n); |
|---|
| 858 | extern template cvec zero_pad(const cvec &v, int n); |
|---|
| 859 | extern template ivec zero_pad(const ivec &v, int n); |
|---|
| 860 | extern template svec zero_pad(const svec &v, int n); |
|---|
| 861 | extern template bvec zero_pad(const bvec &v, int n); |
|---|
| 862 | |
|---|
| 863 | extern template vec zero_pad(const vec &v); |
|---|
| 864 | extern template cvec zero_pad(const cvec &v); |
|---|
| 865 | extern template ivec zero_pad(const ivec &v); |
|---|
| 866 | extern template svec zero_pad(const svec &v); |
|---|
| 867 | extern template bvec zero_pad(const bvec &v); |
|---|
| 868 | |
|---|
| 869 | extern template mat zero_pad(const mat &, int, int); |
|---|
| 870 | extern template cmat zero_pad(const cmat &, int, int); |
|---|
| 871 | extern template imat zero_pad(const imat &, int, int); |
|---|
| 872 | extern template smat zero_pad(const smat &, int, int); |
|---|
| 873 | extern template bmat zero_pad(const bmat &, int, int); |
|---|
| 874 | |
|---|
| 875 | extern template vec sum(const mat &m, int dim); |
|---|
| 876 | extern template cvec sum(const cmat &m, int dim); |
|---|
| 877 | extern template svec sum(const smat &m, int dim); |
|---|
| 878 | extern template ivec sum(const imat &m, int dim); |
|---|
| 879 | extern template bvec sum(const bmat &m, int dim); |
|---|
| 880 | |
|---|
| 881 | extern template double sumsum(const mat &X); |
|---|
| 882 | extern template std::complex<double> sumsum(const cmat &X); |
|---|
| 883 | extern template short sumsum(const smat &X); |
|---|
| 884 | extern template int sumsum(const imat &X); |
|---|
| 885 | extern template bin sumsum(const bmat &X); |
|---|
| 886 | |
|---|
| 887 | extern template vec sum_sqr(const mat & m, int dim); |
|---|
| 888 | extern template cvec sum_sqr(const cmat &m, int dim); |
|---|
| 889 | extern template svec sum_sqr(const smat &m, int dim); |
|---|
| 890 | extern template ivec sum_sqr(const imat &m, int dim); |
|---|
| 891 | extern template bvec sum_sqr(const bmat &m, int dim); |
|---|
| 892 | |
|---|
| 893 | extern template mat cumsum(const mat &m, int dim); |
|---|
| 894 | extern template cmat cumsum(const cmat &m, int dim); |
|---|
| 895 | extern template smat cumsum(const smat &m, int dim); |
|---|
| 896 | extern template imat cumsum(const imat &m, int dim); |
|---|
| 897 | extern template bmat cumsum(const bmat &m, int dim); |
|---|
| 898 | |
|---|
| 899 | extern template vec prod(const mat &m, int dim); |
|---|
| 900 | extern template cvec prod(const cmat &v, int dim); |
|---|
| 901 | extern template svec prod(const smat &m, int dim); |
|---|
| 902 | extern template ivec prod(const imat &m, int dim); |
|---|
| 903 | extern template bvec prod(const bmat &m, int dim); |
|---|
| 904 | |
|---|
| 905 | extern template vec diag(const mat &in); |
|---|
| 906 | extern template cvec diag(const cmat &in); |
|---|
| 907 | extern template void diag(const vec &in, mat &m); |
|---|
| 908 | extern template void diag(const cvec &in, cmat &m); |
|---|
| 909 | extern template mat diag(const vec &v, const int K); |
|---|
| 910 | extern template cmat diag(const cvec &v, const int K); |
|---|
| 911 | |
|---|
| 912 | extern template mat bidiag(const vec &, const vec &); |
|---|
| 913 | extern template cmat bidiag(const cvec &, const cvec &); |
|---|
| 914 | extern template void bidiag(const vec &, const vec &, mat &); |
|---|
| 915 | extern template void bidiag(const cvec &, const cvec &, cmat &); |
|---|
| 916 | extern template void bidiag(const mat &, vec &, vec &); |
|---|
| 917 | extern template void bidiag(const cmat &, cvec &, cvec &); |
|---|
| 918 | |
|---|
| 919 | extern template mat tridiag(const vec &main, const vec &, const vec &); |
|---|
| 920 | extern template cmat tridiag(const cvec &main, const cvec &, const cvec &); |
|---|
| 921 | extern template void tridiag(const vec &main, const vec &, const vec &, mat &); |
|---|
| 922 | extern template void tridiag(const cvec &main, const cvec &, const cvec &, cmat &); |
|---|
| 923 | extern template void tridiag(const mat &m, vec &, vec &, vec &); |
|---|
| 924 | extern template void tridiag(const cmat &m, cvec &, cvec &, cvec &); |
|---|
| 925 | |
|---|
| 926 | extern template double trace(const mat &in); |
|---|
| 927 | extern template std::complex<double> trace(const cmat &in); |
|---|
| 928 | extern template short trace(const smat &in); |
|---|
| 929 | extern template int trace(const imat &in); |
|---|
| 930 | extern template bin trace(const bmat &in); |
|---|
| 931 | |
|---|
| 932 | extern template void transpose(const mat &m, mat &out); |
|---|
| 933 | extern template void transpose(const cmat &m, cmat &out); |
|---|
| 934 | extern template void transpose(const smat &m, smat &out); |
|---|
| 935 | extern template void transpose(const imat &m, imat &out); |
|---|
| 936 | extern template void transpose(const bmat &m, bmat &out); |
|---|
| 937 | |
|---|
| 938 | extern template mat transpose(const mat &m); |
|---|
| 939 | extern template cmat transpose(const cmat &m); |
|---|
| 940 | extern template smat transpose(const smat &m); |
|---|
| 941 | extern template imat transpose(const imat &m); |
|---|
| 942 | extern template bmat transpose(const bmat &m); |
|---|
| 943 | |
|---|
| 944 | extern template void hermitian_transpose(const mat &m, mat &out); |
|---|
| 945 | extern template void hermitian_transpose(const cmat &m, cmat &out); |
|---|
| 946 | extern template void hermitian_transpose(const smat &m, smat &out); |
|---|
| 947 | extern template void hermitian_transpose(const imat &m, imat &out); |
|---|
| 948 | extern template void hermitian_transpose(const bmat &m, bmat &out); |
|---|
| 949 | |
|---|
| 950 | extern template mat hermitian_transpose(const mat &m); |
|---|
| 951 | extern template cmat hermitian_transpose(const cmat &m); |
|---|
| 952 | extern template smat hermitian_transpose(const smat &m); |
|---|
| 953 | extern template imat hermitian_transpose(const imat &m); |
|---|
| 954 | extern template bmat hermitian_transpose(const bmat &m); |
|---|
| 955 | |
|---|
| 956 | extern template bool is_hermitian(const mat &X); |
|---|
| 957 | extern template bool is_hermitian(const cmat &X); |
|---|
| 958 | |
|---|
| 959 | extern template bool is_unitary(const mat &X); |
|---|
| 960 | extern template bool is_unitary(const cmat &X); |
|---|
| 961 | |
|---|
| 962 | extern template vec rvectorize(const mat &m); |
|---|
| 963 | extern template cvec rvectorize(const cmat &m); |
|---|
| 964 | extern template ivec rvectorize(const imat &m); |
|---|
| 965 | extern template svec rvectorize(const smat &m); |
|---|
| 966 | extern template bvec rvectorize(const bmat &m); |
|---|
| 967 | |
|---|
| 968 | extern template vec cvectorize(const mat &m); |
|---|
| 969 | extern template cvec cvectorize(const cmat &m); |
|---|
| 970 | extern template ivec cvectorize(const imat &m); |
|---|
| 971 | extern template svec cvectorize(const smat &m); |
|---|
| 972 | extern template bvec cvectorize(const bmat &m); |
|---|
| 973 | |
|---|
| 974 | extern template mat reshape(const mat &m, int rows, int cols); |
|---|
| 975 | extern template cmat reshape(const cmat &m, int rows, int cols); |
|---|
| 976 | extern template imat reshape(const imat &m, int rows, int cols); |
|---|
| 977 | extern template smat reshape(const smat &m, int rows, int cols); |
|---|
| 978 | extern template bmat reshape(const bmat &m, int rows, int cols); |
|---|
| 979 | |
|---|
| 980 | extern template mat reshape(const vec &m, int rows, int cols); |
|---|
| 981 | extern template cmat reshape(const cvec &m, int rows, int cols); |
|---|
| 982 | extern template imat reshape(const ivec &m, int rows, int cols); |
|---|
| 983 | extern template smat reshape(const svec &m, int rows, int cols); |
|---|
| 984 | extern template bmat reshape(const bvec &m, int rows, int cols); |
|---|
| 985 | |
|---|
| 986 | extern template mat kron(const mat &X, const mat &Y); |
|---|
| 987 | extern template cmat kron(const cmat &X, const cmat &Y); |
|---|
| 988 | extern template imat kron(const imat &X, const imat &Y); |
|---|
| 989 | extern template smat kron(const smat &X, const smat &Y); |
|---|
| 990 | extern template bmat kron(const bmat &X, const bmat &Y); |
|---|
| 991 | |
|---|
| 992 | extern template vec repmat(const vec &v, int n); |
|---|
| 993 | extern template cvec repmat(const cvec &v, int n); |
|---|
| 994 | extern template ivec repmat(const ivec &v, int n); |
|---|
| 995 | extern template svec repmat(const svec &v, int n); |
|---|
| 996 | extern template bvec repmat(const bvec &v, int n); |
|---|
| 997 | |
|---|
| 998 | extern template mat repmat(const vec &v, int m, int n, bool transpose); |
|---|
| 999 | extern template cmat repmat(const cvec &v, int m, int n, bool transpose); |
|---|
| 1000 | extern template imat repmat(const ivec &v, int m, int n, bool transpose); |
|---|
| 1001 | extern template smat repmat(const svec &v, int m, int n, bool transpose); |
|---|
| 1002 | extern template bmat repmat(const bvec &v, int m, int n, bool transpose); |
|---|
| 1003 | |
|---|
| 1004 | extern template mat repmat(const mat &data, int m, int n); |
|---|
| 1005 | extern template cmat repmat(const cmat &data, int m, int n); |
|---|
| 1006 | extern template imat repmat(const imat &data, int m, int n); |
|---|
| 1007 | extern template smat repmat(const smat &data, int m, int n); |
|---|
| 1008 | extern template bmat repmat(const bmat &data, int m, int n); |
|---|
| 1009 | |
|---|
| 1010 | #endif // HAVE_EXTERN_TEMPLATE |
|---|
| 1011 | |
|---|
| 1012 | //! \endcond |
|---|
| 1013 | |
|---|
| 1014 | } // namespace itpp |
|---|
| 1015 | |
|---|
| 1016 | #endif // #ifndef MATFUNC_H |
|---|