Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
vpMatrix_lu.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Matrix LU decomposition.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpConfig.h>
40 
41 #include <visp3/core/vpColVector.h>
42 #include <visp3/core/vpMath.h>
43 #include <visp3/core/vpMatrix.h>
44 
45 #ifdef VISP_HAVE_EIGEN3
46 #include <Eigen/LU>
47 #endif
48 
49 #ifdef VISP_HAVE_GSL
50 #include <gsl/gsl_linalg.h>
51 #include <gsl/gsl_permutation.h>
52 #endif
53 
54 #ifdef VISP_HAVE_LAPACK
55 #ifdef VISP_HAVE_LAPACK_BUILT_IN
56 typedef long int integer;
57 #else
58 typedef int integer;
59 #endif
60 
61 extern "C" int dgetrf_(integer *m, integer *n, double *a, integer *lda, integer *ipiv, integer *info);
62 extern "C" void dgetri_(integer *n, double *a, integer *lda, integer *ipiv, double *work, integer *lwork,
63  integer *info);
64 #endif
65 
66 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
67 #include <opencv2/core/core.hpp>
68 #endif
69 
70 // Exception
71 #include <visp3/core/vpException.h>
72 #include <visp3/core/vpMatrixException.h>
73 
74 #include <cmath> // std::fabs
75 #include <limits> // numeric_limits
76 
77 /*--------------------------------------------------------------------
78  LU Decomposition related functions
79 -------------------------------------------------------------------- */
80 
131 {
132 #if defined(VISP_HAVE_LAPACK)
133  return inverseByLULapack();
134 #elif defined(VISP_HAVE_EIGEN3)
135  return inverseByLUEigen3();
136 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101)
137  return inverseByLUOpenCV();
138 #elif defined(VISP_HAVE_GSL)
139  return inverseByLUGsl();
140 #else
141  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant. Install Eigen3, "
142  "Lapack, OpenCV or GSL 3rd party"));
143 #endif
144 }
145 
180 double vpMatrix::detByLU() const
181 {
182  if (rowNum == 2 && colNum == 2) {
183  return ((*this)[0][0] * (*this)[1][1] - (*this)[0][1] * (*this)[1][0]);
184  } else if (rowNum == 3 && colNum == 3) {
185  return ((*this)[0][0] * ((*this)[1][1] * (*this)[2][2] - (*this)[1][2] * (*this)[2][1]) -
186  (*this)[0][1] * ((*this)[1][0] * (*this)[2][2] - (*this)[1][2] * (*this)[2][0]) +
187  (*this)[0][2] * ((*this)[1][0] * (*this)[2][1] - (*this)[1][1] * (*this)[2][0]));
188  } else {
189 #if defined(VISP_HAVE_LAPACK)
190  return detByLULapack();
191 #elif defined(VISP_HAVE_EIGEN3)
192  return detByLUEigen3();
193 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101)
194  return detByLUOpenCV();
195 #elif defined(VISP_HAVE_GSL)
196  return detByLUGsl();
197 #else
198  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant. Install Lapack, "
199  "Eigen3, OpenCV or GSL 3rd party"));
200 #endif
201  }
202 }
203 
204 
205 #if defined(VISP_HAVE_GSL)
206 
238 {
239  if (rowNum != colNum) {
240  throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
241  }
242 
243  gsl_matrix *A = gsl_matrix_alloc(rowNum, colNum);
244 
245  // copy the input matrix to ensure the function doesn't modify its content
246  unsigned int tda = (unsigned int)A->tda;
247  for (unsigned int i = 0; i < rowNum; i++) {
248  unsigned int k = i * tda;
249  for (unsigned int j = 0; j < colNum; j++)
250  A->data[k + j] = (*this)[i][j];
251  }
252 
253  vpMatrix Ainv(rowNum, colNum);
254 
255  gsl_matrix inverse;
256  inverse.size1 = rowNum;
257  inverse.size2 = colNum;
258  inverse.tda = inverse.size2;
259  inverse.data = Ainv.data;
260  inverse.owner = 0;
261  inverse.block = 0;
262 
263  gsl_permutation *p = gsl_permutation_alloc(rowNum);
264  int s;
265 
266  // Do the LU decomposition on A and use it to solve the system
267  gsl_linalg_LU_decomp(A, p, &s);
268  gsl_linalg_LU_invert(A, p, &inverse);
269 
270  gsl_permutation_free(p);
271  gsl_matrix_free(A);
272 
273  return Ainv;
274 }
275 
301 double vpMatrix::detByLUGsl() const
302 {
303  double det = 0.;
304 
305  if (rowNum != colNum) {
306  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
307  rowNum, colNum));
308  }
309 
310  gsl_matrix *A = gsl_matrix_alloc(rowNum, colNum);
311 
312  // copy the input matrix to ensure the function doesn't modify its content
313  unsigned int tda = (unsigned int)A->tda;
314  for (unsigned int i = 0; i < rowNum; i++) {
315  unsigned int k = i * tda;
316  for (unsigned int j = 0; j < colNum; j++)
317  A->data[k + j] = (*this)[i][j];
318  }
319 
320  gsl_permutation *p = gsl_permutation_alloc(rowNum);
321  int s;
322 
323  // Do the LU decomposition on A and use it to solve the system
324  gsl_linalg_LU_decomp(A, p, &s);
325  det = gsl_linalg_LU_det(A, s);
326 
327  gsl_permutation_free(p);
328  gsl_matrix_free(A);
329 
330  return det;
331 }
332 #endif
333 
334 #ifdef VISP_HAVE_LAPACK
335 
367 {
368  if (rowNum != colNum) {
369  throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
370  }
371 
372  integer dim = (integer)rowNum;
373  integer lda = dim;
374  integer info;
375  integer lwork = dim * dim;
376  integer *ipiv = new integer[dim + 1];
377  double *work = new double[lwork];
378 
379  vpMatrix A = *this;
380 
381  dgetrf_(&dim, &dim, A.data, &lda, &ipiv[1], &info);
382  if (info) {
383  delete[] ipiv;
384  delete[] work;
385  throw(vpException(vpException::fatalError, "Lapack LU decomposition failed; info=%d", info));
386  }
387 
388  dgetri_(&dim, A.data, &dim, &ipiv[1], work, &lwork, &info);
389 
390  delete[] ipiv;
391  delete[] work;
392 
393  return A;
394 }
395 
422 {
423  if (rowNum != colNum) {
424  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
425  rowNum, colNum));
426  }
427 
428  integer dim = (integer)rowNum;
429  integer lda = dim;
430  integer info;
431  integer *ipiv = new integer[dim + 1];
432 
433  vpMatrix A = *this;
434 
435  dgetrf_(&dim, &dim, A.data, &lda, &ipiv[1], &info);
436  if (info < 0) {
437  delete[] ipiv;
438  throw(vpException(vpException::fatalError, "Lapack LU decomposition failed; info=%d", -info));
439  }
440 
441  double det = A[0][0];
442  for (unsigned int i = 1; i < rowNum; i++) {
443  det *= A[i][i];
444  }
445 
446  double sign = 1.;
447  for (int i = 1; i <= dim; i++) {
448  if (ipiv[i] != i)
449  sign = -sign;
450  }
451 
452  det *= sign;
453 
454  delete[] ipiv;
455 
456  return det;
457 }
458 #endif
459 
460 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
461 
493 {
494  if (rowNum != colNum) {
495  throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
496  }
497 
498  cv::Mat M(rowNum, colNum, CV_64F, this->data);
499 
500  cv::Mat Minv = M.inv(cv::DECOMP_LU);
501 
502  vpMatrix A(rowNum, colNum);
503  memcpy(A.data, Minv.data, (size_t)(8 * Minv.rows * Minv.cols));
504 
505  return A;
506 }
507 
534 {
535  double det = 0.;
536 
537  if (rowNum != colNum) {
538  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
539  rowNum, colNum));
540  }
541 
542  cv::Mat M(rowNum, colNum, CV_64F, this->data);
543  det = cv::determinant(M);
544 
545  return (det);
546 }
547 #endif
548 
549 #if defined(VISP_HAVE_EIGEN3)
550 
583 {
584  if (rowNum != colNum) {
585  throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
586  }
587  vpMatrix A(this->getRows(), this->getCols());
588 
589  Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > M(this->data, this->getRows(),
590  this->getCols());
591  Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > A_(A.data, this->getRows(),
592  this->getCols());
593 
594  A_ = M.inverse();
595 
596  return A;
597 }
598 
625 {
626  if (rowNum != colNum) {
627  throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
628  rowNum, colNum));
629  }
630 
631  Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > M(this->data, this->getRows(),
632  this->getCols());
633 
634  return M.determinant();
635 }
636 #endif
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
vpMatrix inverseByLUGsl() const
double detByLULapack() const
error that can be emited by ViSP classes.
Definition: vpException.h:71
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
unsigned int getCols() const
Definition: vpArray2D.h:146
double detByLUOpenCV() const
double detByLUEigen3() const
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
vpMatrix inverseByLUOpenCV() const
double detByLU() const
unsigned int getRows() const
Definition: vpArray2D.h:156
vpMatrix inverseByLUEigen3() const
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:4906
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:76
vpMatrix inverseByLU() const
vpMatrix inverseByLULapack() const
double detByLUGsl() const