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 |
---|