Visual Servoing Platform
version 3.7.0
Toggle main menu visibility
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>
51
typedef
MKL_INT integer;
52
#else
53
#ifdef VISP_HAVE_LAPACK_BUILT_IN
54
typedef
long
int
integer;
55
#else
56
typedef
int
integer;
57
#endif
58
extern
"C"
int
dgetrf_(integer *m, integer *n,
double
*a, integer *lda, integer *ipiv, integer *info);
59
extern
"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
75
BEGIN_VISP_NAMESPACE
76
/*--------------------------------------------------------------------
77
LU Decomposition related functions
78
-------------------------------------------------------------------- */
79
130
vpMatrix
vpMatrix::inverseByLU
()
const
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
236
double
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)
303
vpMatrix
vpMatrix::inverseByLULapack
()
const
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
404
double
vpMatrix::detByLULapack
()
const
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)
513
vpMatrix
vpMatrix::inverseByLUOpenCV
()
const
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
523
vpMatrix
A(
rowNum
,
colNum
);
524
memcpy(A.
data
, Minv.data,
static_cast<
size_t
>
(8 * Minv.rows * Minv.cols));
525
526
return
A;
527
}
528
558
double
vpMatrix::detByLUOpenCV
()
const
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
610
vpMatrix
vpMatrix::inverseByLUEigen3
()
const
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
656
double
vpMatrix::detByLUEigen3
()
const
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
669
END_VISP_NAMESPACE
vpArray2D< double >::getCols
unsigned int getCols() const
Definition
vpArray2D.h:423
vpArray2D::data
Type * data
Address of the first element of the data array.
Definition
vpArray2D.h:149
vpArray2D::resize
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition
vpArray2D.h:448
vpArray2D< double >::rowNum
unsigned int rowNum
Definition
vpArray2D.h:1201
vpArray2D< double >::getRows
unsigned int getRows() const
Definition
vpArray2D.h:433
vpArray2D< double >::colNum
unsigned int colNum
Definition
vpArray2D.h:1203
vpException
error that can be emitted by ViSP classes.
Definition
vpException.h:60
vpException::fatalError
@ fatalError
Fatal error.
Definition
vpException.h:72
vpMatrix::inverseByLU
vpMatrix inverseByLU() const
Definition
vpMatrix_lu.cpp:130
vpMatrix::inverseByLUEigen3
vpMatrix inverseByLUEigen3() const
Definition
vpMatrix_lu.cpp:610
vpMatrix::inverseByLUOpenCV
vpMatrix inverseByLUOpenCV() const
Definition
vpMatrix_lu.cpp:513
vpMatrix::vpMatrix
vpMatrix()
Definition
vpMatrix.h:191
vpMatrix::detByLUEigen3
double detByLUEigen3() const
Definition
vpMatrix_lu.cpp:656
vpMatrix::detByLUOpenCV
double detByLUOpenCV() const
Definition
vpMatrix_lu.cpp:558
vpMatrix::inverseByLULapack
vpMatrix inverseByLULapack() const
Definition
vpMatrix_lu.cpp:303
vpMatrix::detByLU
double detByLU() const
Definition
vpMatrix_lu.cpp:236
vpMatrix::det
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition
vpMatrix.cpp:1649
vpMatrix::detByLULapack
double detByLULapack() const
Definition
vpMatrix_lu.cpp:404
BEGIN_VISP_NAMESPACE
Definition
vpMbtDistanceCircle.cpp:55
modules
core
src
math
matrix
vpMatrix_lu.cpp
Generated by
1.17.0