XMM - Probabilistic Models for Motion Recognition and Mapping

xmmMatrix.hpp
Go to the documentation of this file.
1 /*
2  * xmmMatrix.hpp
3  *
4  * Matrix Utilities
5  *
6  * Contact:
7  * - Jules Francoise <jules.francoise@ircam.fr>
8  *
9  * This code has been initially authored by Jules Francoise
10  * <http://julesfrancoise.com> during his PhD thesis, supervised by Frederic
11  * Bevilacqua <href="http://frederic-bevilacqua.net>, in the Sound Music
12  * Movement Interaction team <http://ismm.ircam.fr> of the
13  * STMS Lab - IRCAM, CNRS, UPMC (2011-2015).
14  *
15  * Copyright (C) 2015 UPMC, Ircam-Centre Pompidou.
16  *
17  * This File is part of XMM.
18  *
19  * XMM is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * XMM is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with XMM. If not, see <http://www.gnu.org/licenses/>.
31  */
32 
33 #ifndef xmmMatrix_h
34 #define xmmMatrix_h
35 
36 #include <cmath>
37 #include <exception>
38 #include <iostream>
39 #include <stdexcept>
40 #include <vector>
41 
42 namespace xmm {
54 template <typename T>
55 class Matrix {
56  public:
61  static const double kEpsilonPseudoInverse() { return 1.0e-9; }
62 
66  unsigned int nrows;
67 
71  unsigned int ncols;
72 
76  std::vector<T> _data;
77 
83  typename std::vector<T>::iterator data;
84 
88  bool ownData;
89 
95  Matrix(bool ownData_ = true) : nrows(0), ncols(0), ownData(ownData_) {}
96 
103  Matrix(unsigned int nrows_, bool ownData_ = true) {
104  nrows = nrows_;
105  ncols = nrows_;
106  ownData = ownData_;
107  if (ownData) {
108  _data.assign(nrows * ncols, T(0.0));
109  data = _data.begin();
110  }
111  }
112 
120  Matrix(unsigned int nrows_, unsigned int ncols_, bool ownData_ = true) {
121  nrows = nrows_;
122  ncols = ncols_;
123  ownData = ownData_;
124  if (ownData) {
125  _data.assign(nrows * ncols, T(0.0));
126  data = _data.begin();
127  }
128  }
129 
136  Matrix(unsigned int nrows_, unsigned int ncols_,
137  typename std::vector<T>::iterator data_it) {
138  nrows = nrows_;
139  ncols = ncols_;
140  ownData = false;
141  data = data_it;
142  }
143 
150  void resize(unsigned int nrows_, unsigned int ncols_) {
151  nrows = nrows_;
152  ncols = ncols_;
153  _data.resize(nrows * ncols);
154  }
155 
160  void resize(unsigned int nrows_) {
161  if (nrows != ncols) throw std::runtime_error("Matrix is not square");
162 
163  nrows = nrows_;
164  ncols = nrows;
165  _data.resize(nrows * ncols);
166  }
167 
172  float sum() const {
173  float sum_(0.);
174  for (unsigned int i = 0; i < nrows * ncols; i++) sum_ += data[i];
175  return sum_;
176  }
177 
181  void print() const {
182  for (unsigned int i = 0; i < nrows; i++) {
183  for (unsigned int j = 0; j < ncols; j++) {
184  std::cout << data[i * ncols + j] << " ";
185  }
186  std::cout << std::endl;
187  }
188  }
189 
195  Matrix<T> *transpose() const {
196  Matrix<T> *out = new Matrix<T>(ncols, nrows);
197  for (unsigned int i = 0; i < ncols; i++) {
198  for (unsigned int j = 0; j < nrows; j++) {
199  out->data[i * nrows + j] = data[j * ncols + i];
200  }
201  }
202  return out;
203  }
204 
211  Matrix<T> *product(Matrix const *mat) const {
212  if (ncols != mat->nrows)
213  throw std::runtime_error("Wrong dimensions for matrix product");
214 
215  Matrix<T> *out = new Matrix<T>(nrows, mat->ncols);
216  for (unsigned int i = 0; i < nrows; i++) {
217  for (unsigned int j = 0; j < mat->ncols; j++) {
218  out->data[i * mat->ncols + j] = 0.;
219  for (unsigned int k = 0; k < ncols; k++) {
220  out->data[i * mat->ncols + j] +=
221  data[i * ncols + k] * mat->data[k * mat->ncols + j];
222  }
223  }
224  }
225  return out;
226  }
227 
234  Matrix<T> *pinv(double *det) const {
235  Matrix<T> *inverse = NULL;
236  if (nrows == ncols) {
237  inverse = gauss_jordan_inverse(det);
238  if (inverse) {
239  return inverse;
240  }
241  }
242 
243  inverse = new Matrix<T>(ncols, nrows);
244  Matrix<T> *transp, *prod, *dst;
245  transp = this->transpose();
246  if (nrows >= ncols) {
247  prod = transp->product(this);
248  dst = prod->gauss_jordan_inverse(det);
249  inverse = dst->product(transp);
250  } else {
251  prod = this->product(transp);
252  dst = prod->gauss_jordan_inverse(det);
253  inverse = transp->product(dst);
254  }
255  *det = 0;
256  delete transp;
257  delete prod;
258  delete dst;
259  return inverse;
260  }
261 
270  Matrix<T> *gauss_jordan_inverse(double *det) const {
271  if (nrows != ncols) {
272  throw std::runtime_error(
273  "Gauss-Jordan inversion: Can't invert Non-square matrix");
274  }
275  *det = 1.0f;
276  Matrix<T> mat(nrows, ncols * 2);
277  Matrix<T> new_mat(nrows, ncols * 2);
278 
279  unsigned int n = nrows;
280 
281  // Create matrix
282  for (unsigned int i = 0; i < n; i++) {
283  for (unsigned int j = 0; j < n; j++) {
284  mat._data[i * 2 * n + j] = data[i * n + j];
285  }
286  mat._data[i * 2 * n + n + i] = 1;
287  }
288 
289  for (unsigned int k = 0; k < n; k++) {
290  unsigned int i(k);
291  while (std::fabs(mat._data[i * 2 * n + k]) <
293  i++;
294  if (i == n) {
295  throw std::runtime_error("Non-invertible matrix");
296  }
297  }
298  *det *= mat._data[i * 2 * n + k];
299 
300  // if found > Exchange lines
301  if (i != k) {
302  mat.swap_lines(i, k);
303  }
304 
305  new_mat._data = mat._data;
306 
307  for (unsigned int j = 0; j < 2 * n; j++) {
308  new_mat._data[k * 2 * n + j] /= mat._data[k * 2 * n + k];
309  }
310  for (i = 0; i < n; i++) {
311  if (i != k) {
312  for (unsigned int j = 0; j < 2 * n; j++) {
313  new_mat._data[i * 2 * n + j] -=
314  mat._data[i * 2 * n + k] *
315  new_mat._data[k * 2 * n + j];
316  }
317  }
318  }
319  mat._data = new_mat._data;
320  }
321 
322  Matrix<T> *dst = new Matrix<T>(nrows, ncols);
323  for (unsigned int i = 0; i < n; i++)
324  for (unsigned int j = 0; j < n; j++)
325  dst->_data[i * n + j] = mat._data[i * 2 * n + n + j];
326  return dst;
327  }
328 
334  void swap_lines(unsigned int i, unsigned int j) {
335  T tmp;
336  for (unsigned int k = 0; k < ncols; k++) {
337  tmp = data[i * ncols + k];
338  data[i * ncols + k] = data[j * ncols + k];
339  data[j * ncols + k] = tmp;
340  }
341  }
342 
348  void swap_columns(unsigned int i, unsigned int j) {
349  T tmp;
350  for (unsigned int k = 0; k < nrows; k++) {
351  tmp = data[k * ncols + i];
352  data[k * ncols + i] = data[k * ncols + j];
353  data[k * ncols + j] = tmp;
354  }
355  }
356 };
357 }
358 
359 #endif
Dirty and very incomplete Matrix Class.
Definition: xmmMatrix.hpp:55
void swap_columns(unsigned int i, unsigned int j)
Swap 2 columns of the matrix.
Definition: xmmMatrix.hpp:348
std::vector< T >::iterator data
Data iterator.
Definition: xmmMatrix.hpp:83
Matrix(unsigned int nrows_, unsigned int ncols_, bool ownData_=true)
Constructor.
Definition: xmmMatrix.hpp:120
void resize(unsigned int nrows_, unsigned int ncols_)
Resize the matrix.
Definition: xmmMatrix.hpp:150
float sum() const
Compute the Sum of the matrix.
Definition: xmmMatrix.hpp:172
Matrix< T > * product(Matrix const *mat) const
Compute the product of matrices.
Definition: xmmMatrix.hpp:211
Matrix(bool ownData_=true)
Default Constructor.
Definition: xmmMatrix.hpp:95
Matrix< T > * transpose() const
Compute the transpose matrix.
Definition: xmmMatrix.hpp:195
unsigned int ncols
number of columns of the matrix
Definition: xmmMatrix.hpp:71
Matrix< T > * pinv(double *det) const
Compute the Pseudo-Inverse of a Matrix.
Definition: xmmMatrix.hpp:234
Matrix(unsigned int nrows_, bool ownData_=true)
Square Matrix Constructor.
Definition: xmmMatrix.hpp:103
static const double kEpsilonPseudoInverse()
Epsilon value for Matrix inversion.
Definition: xmmMatrix.hpp:61
Matrix< T > * gauss_jordan_inverse(double *det) const
Compute the Gauss-Jordan Inverse of a Square Matrix.
Definition: xmmMatrix.hpp:270
unsigned int nrows
number of rows of the matrix
Definition: xmmMatrix.hpp:66
Definition: xmmAttribute.hpp:42
Matrix(unsigned int nrows_, unsigned int ncols_, typename std::vector< T >::iterator data_it)
Constructor from vector (shared data)
Definition: xmmMatrix.hpp:136
bool ownData
Defines if the matrix has its own data.
Definition: xmmMatrix.hpp:88
void print() const
Print the matrix.
Definition: xmmMatrix.hpp:181
std::vector< T > _data
Matrix Data if not shared.
Definition: xmmMatrix.hpp:76
void resize(unsigned int nrows_)
Resize a Square Matrix.
Definition: xmmMatrix.hpp:160
void swap_lines(unsigned int i, unsigned int j)
Swap 2 lines of the matrix.
Definition: xmmMatrix.hpp:334