Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMatrix_lu.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Matrix LU decomposition.
32 */
33
34#include <visp3/core/vpConfig.h>
35
36#include <visp3/core/vpColVector.h>
37#include <visp3/core/vpMath.h>
38#include <visp3/core/vpMatrix.h>
39
40#ifdef VISP_HAVE_EIGEN3
41#include <Eigen/LU>
42#endif
43
44#ifdef VISP_HAVE_LAPACK
45#ifdef VISP_HAVE_GSL
46#include <gsl/gsl_linalg.h>
47#include <gsl/gsl_permutation.h>
48#endif
49#ifdef VISP_HAVE_MKL
50#include <mkl.h>
51typedef MKL_INT integer;
52#else
53#ifdef VISP_HAVE_LAPACK_BUILT_IN
54typedef long int integer;
55#else
56typedef int integer;
57#endif
58extern "C" int dgetrf_(integer *m, integer *n, double *a, integer *lda, integer *ipiv, integer *info);
59extern "C" void dgetri_(integer *n, double *a, integer *lda, integer *ipiv, double *work, integer *lwork,
60 integer *info);
61#endif
62#endif
63
64#if defined(VISP_HAVE_OPENCV) // Require opencv >= 2.1.1
65#include <opencv2/core/core.hpp>
66#endif
67
68// Exception
69#include <visp3/core/vpException.h>
70#include <visp3/core/vpMatrixException.h>
71
72#include <cmath> // std::fabs
73#include <limits> // numeric_limits
74
76/*--------------------------------------------------------------------
77 LU Decomposition related functions
78-------------------------------------------------------------------- */
79
131{
132 const unsigned int val_2 = 2;
133 const unsigned int val_3 = 3;
134 if ((colNum == 1) && (rowNum == 1)) {
135 vpMatrix inv;
136 inv.resize(1, 1, false);
137 double d = det();
138 if (std::fabs(d) < std::numeric_limits<double>::epsilon()) {
139 throw(vpException(vpException::fatalError, "Cannot inverse matrix %d by %d by LU. Matrix determinant is 0.",
140 rowNum, colNum));
141 }
142 inv[0][0] = 1. / d;
143 return inv;
144 }
145 else if ((colNum == val_2) && (rowNum == val_2)) {
146 vpMatrix inv;
147 inv.resize(val_2, val_2, false);
148 double d = det();
149 if (std::fabs(d) < std::numeric_limits<double>::epsilon()) {
150 throw(vpException(vpException::fatalError, "Cannot inverse matrix %d by %d by LU. Matrix determinant is 0.",
151 rowNum, colNum));
152 }
153 d = 1. / d;
154 inv[1][1] = (*this)[0][0] * d;
155 inv[0][0] = (*this)[1][1] * d;
156 inv[0][1] = -(*this)[0][1] * d;
157 inv[1][0] = -(*this)[1][0] * d;
158 return inv;
159 }
160 else if ((colNum == val_3) && (rowNum == val_3)) {
161 vpMatrix inv;
162 inv.resize(val_3, val_3, false);
163 double d = det();
164 if (std::fabs(d) < std::numeric_limits<double>::epsilon()) {
165 throw(vpException(vpException::fatalError, "Cannot inverse matrix %d by %d by LU. Matrix determinant is 0.",
166 rowNum, colNum));
167 }
168 d = 1. / d;
169 const unsigned int index_0 = 0;
170 const unsigned int index_1 = 1;
171 const unsigned int index_2 = 2;
172 inv[index_0][index_0] = (((*this)[index_1][index_1] * (*this)[index_2][index_2]) - ((*this)[index_1][index_2] * (*this)[index_2][index_1])) * d;
173 inv[index_0][index_1] = (((*this)[index_0][index_2] * (*this)[index_2][index_1]) - ((*this)[index_0][index_1] * (*this)[index_2][index_2])) * d;
174 inv[index_0][index_2] = (((*this)[index_0][index_1] * (*this)[index_1][index_2]) - ((*this)[index_0][index_2] * (*this)[index_1][index_1])) * d;
175
176 inv[index_1][index_0] = (((*this)[index_1][index_2] * (*this)[index_2][index_0]) - ((*this)[index_1][index_0] * (*this)[index_2][index_2])) * d;
177 inv[index_1][index_1] = (((*this)[index_0][index_0] * (*this)[index_2][index_2]) - ((*this)[index_0][index_2] * (*this)[index_2][index_0])) * d;
178 inv[index_1][index_2] = (((*this)[index_0][index_2] * (*this)[index_1][index_0]) - ((*this)[index_0][index_0] * (*this)[index_1][index_2])) * d;
179
180 inv[index_2][index_0] = (((*this)[index_1][index_0] * (*this)[index_2][index_1]) - ((*this)[index_1][index_1] * (*this)[index_2][index_0])) * d;
181 inv[index_2][index_1] = (((*this)[index_0][index_1] * (*this)[index_2][index_0]) - ((*this)[index_0][index_0] * (*this)[index_2][index_1])) * d;
182 inv[index_2][index_2] = (((*this)[index_0][index_0] * (*this)[index_1][index_1]) - ((*this)[index_0][index_1] * (*this)[index_1][index_0])) * d;
183 return inv;
184 }
185 else {
186#if defined(VISP_HAVE_LAPACK)
187 return inverseByLULapack();
188#elif defined(VISP_HAVE_EIGEN3)
189 return inverseByLUEigen3();
190#elif defined(VISP_HAVE_OPENCV)
191 return inverseByLUOpenCV();
192#else
193 throw(vpException(vpException::fatalError, "Cannot inverse by LU. "
194 "Install Lapack, Eigen3 or OpenCV 3rd party"));
195#endif
196 }
197}
198
236double vpMatrix::detByLU() const
237{
238 const unsigned int val_2 = 2;
239 const unsigned int val_3 = 3;
240 if ((rowNum == 1) && (colNum == 1)) {
241 return (*this)[0][0];
242 }
243 else if ((rowNum == val_2) && (colNum == val_2)) {
244 return (((*this)[0][0] * (*this)[1][1]) - ((*this)[0][1] * (*this)[1][0]));
245 }
246 else if ((rowNum == val_3) && (colNum == val_3)) {
247 const unsigned int index_0 = 0;
248 const unsigned int index_1 = 1;
249 const unsigned int index_2 = 2;
250 return ((((*this)[index_0][index_0] * (((*this)[index_1][index_1] * (*this)[index_2][index_2]) - ((*this)[index_1][index_2] * (*this)[index_2][index_1]))) -
251 ((*this)[index_0][index_1] * (((*this)[index_1][index_0] * (*this)[index_2][index_2]) - ((*this)[index_1][index_2] * (*this)[index_2][index_0])))) +
252 ((*this)[index_0][index_2] * (((*this)[index_1][index_0] * (*this)[index_2][index_1]) - ((*this)[index_1][index_1] * (*this)[index_2][index_0]))));
253 }
254 else {
255#if defined(VISP_HAVE_LAPACK)
256 return detByLULapack();
257#elif defined(VISP_HAVE_EIGEN3)
258 return detByLUEigen3();
259#elif defined(VISP_HAVE_OPENCV)
260 return detByLUOpenCV();
261#else
262 throw(vpException(vpException::fatalError, "Cannot compute matrix determinant. "
263 "Install Lapack, Eigen3 or OpenCV 3rd party"));
264#endif
265 }
266}
267
268#if defined(VISP_HAVE_LAPACK)
304{
305#if defined(VISP_HAVE_GSL)
306 {
307 if (rowNum != colNum) {
308 throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
309 }
310
311 gsl_matrix *A = gsl_matrix_alloc(rowNum, colNum);
312
313 // copy the input matrix to ensure the function doesn't modify its content
314 unsigned int tda = static_cast<unsigned int>(A->tda);
315 for (unsigned int i = 0; i < rowNum; ++i) {
316 unsigned int k = i * tda;
317 for (unsigned int j = 0; j < colNum; ++j)
318 A->data[k + j] = (*this)[i][j];
319 }
320
321 vpMatrix Ainv(rowNum, colNum);
322
323 gsl_matrix inverse;
324 inverse.size1 = rowNum;
325 inverse.size2 = colNum;
326 inverse.tda = inverse.size2;
327 inverse.data = Ainv.data;
328 inverse.owner = 0;
329 inverse.block = 0;
330
331 gsl_permutation *p = gsl_permutation_alloc(rowNum);
332 int s;
333
334 // Do the LU decomposition on A and use it to solve the system
335 gsl_linalg_LU_decomp(A, p, &s);
336 gsl_linalg_LU_invert(A, p, &inverse);
337
338 gsl_permutation_free(p);
339 gsl_matrix_free(A);
340
341 return Ainv;
342 }
343#else
344 {
345 if (rowNum != colNum) {
346 throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
347 }
348
349 integer dim = (integer)rowNum;
350 integer lda = dim;
351 integer info;
352 integer lwork = dim * dim;
353 integer *ipiv = new integer[dim + 1];
354 double *work = new double[lwork];
355
356 vpMatrix A = *this;
357
358 dgetrf_(&dim, &dim, A.data, &lda, &ipiv[1], &info);
359 if (info) {
360 delete[] ipiv;
361 delete[] work;
362 throw(vpException(vpException::fatalError, "Lapack LU decomposition failed; info=%d", info));
363 }
364
365 dgetri_(&dim, A.data, &dim, &ipiv[1], work, &lwork, &info);
366
367 delete[] ipiv;
368 delete[] work;
369
370 return A;
371 }
372#endif
373}
374
405{
406#if defined(VISP_HAVE_GSL)
407 {
408 double det = 0.;
409
410 if (rowNum != colNum) {
411 throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
412 rowNum, colNum));
413 }
414
415 gsl_matrix *A = gsl_matrix_alloc(rowNum, colNum);
416
417 // copy the input matrix to ensure the function doesn't modify its content
418 unsigned int tda = static_cast<unsigned int>(A->tda);
419 for (unsigned int i = 0; i < rowNum; i++) {
420 unsigned int k = i * tda;
421 for (unsigned int j = 0; j < colNum; j++)
422 A->data[k + j] = (*this)[i][j];
423 }
424
425 gsl_permutation *p = gsl_permutation_alloc(rowNum);
426 int s;
427
428 // Do the LU decomposition on A and use it to solve the system
429 gsl_linalg_LU_decomp(A, p, &s);
430 det = gsl_linalg_LU_det(A, s);
431
432 gsl_permutation_free(p);
433 gsl_matrix_free(A);
434
435 return det;
436 }
437#else
438 {
439 if (rowNum != colNum) {
440 throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
441 rowNum, colNum));
442 }
443
444 integer dim = (integer)rowNum;
445 integer lda = dim;
446 integer info;
447 integer *ipiv = new integer[dim + 1];
448
449 vpMatrix A = *this;
450
451 dgetrf_(&dim, &dim, A.data, &lda, &ipiv[1], &info);
452 if (info < 0) {
453 delete[] ipiv;
454 throw(vpException(vpException::fatalError, "Lapack LU decomposition failed; info=%d", -info));
455 }
456
457 double det = A[0][0];
458 for (unsigned int i = 1; i < rowNum; ++i) {
459 det *= A[i][i];
460 }
461
462 double sign = 1.;
463 for (int i = 1; i <= dim; ++i) {
464 if (ipiv[i] != i)
465 sign = -sign;
466 }
467
468 det *= sign;
469
470 delete[] ipiv;
471
472 return det;
473 }
474#endif
475}
476#endif
477
478#if defined(VISP_HAVE_OPENCV)
514{
515 if (rowNum != colNum) {
516 throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
517 }
518
519 cv::Mat M(rowNum, colNum, CV_64F, this->data);
520
521 cv::Mat Minv = M.inv(cv::DECOMP_LU);
522
524 memcpy(A.data, Minv.data, static_cast<size_t>(8 * Minv.rows * Minv.cols));
525
526 return A;
527}
528
559{
560 double det = 0.;
561
562 if (rowNum != colNum) {
563 throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
564 rowNum, colNum));
565 }
566
567 cv::Mat M(rowNum, colNum, CV_64F, this->data);
568 det = cv::determinant(M);
569
570 return (det);
571}
572#endif
573
574#if defined(VISP_HAVE_EIGEN3)
575
611{
612 if (rowNum != colNum) {
613 throw(vpException(vpException::fatalError, "Cannot inverse a non square matrix (%ux%u) by LU", rowNum, colNum));
614 }
615 vpMatrix A(this->getRows(), this->getCols());
616
617 Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > M(this->data, this->getRows(),
618 this->getCols());
619 Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > A_(A.data, this->getRows(),
620 this->getCols());
621
622 A_ = M.inverse();
623
624 return A;
625}
626
657{
658 if (rowNum != colNum) {
659 throw(vpException(vpException::fatalError, "Cannot compute matrix determinant of a non square matrix (%ux%u)",
660 rowNum, colNum));
661 }
662
663 Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > M(this->data, this->getRows(),
664 this->getCols());
665
666 return M.determinant();
667}
668#endif
669END_VISP_NAMESPACE
unsigned int getCols() const
Definition vpArray2D.h:423
Type * data
Address of the first element of the data array.
Definition vpArray2D.h:149
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
unsigned int rowNum
Definition vpArray2D.h:1201
unsigned int getRows() const
Definition vpArray2D.h:433
unsigned int colNum
Definition vpArray2D.h:1203
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ fatalError
Fatal error.
Definition vpException.h:72
vpMatrix inverseByLU() const
vpMatrix inverseByLUEigen3() const
vpMatrix inverseByLUOpenCV() const
double detByLUEigen3() const
double detByLUOpenCV() const
vpMatrix inverseByLULapack() const
double detByLU() const
double det(vpDetMethod method=LU_DECOMPOSITION) const
double detByLULapack() const