37#include <visp3/core/vpConfig.h>
39#include <visp3/core/vpColVector.h>
40#include <visp3/core/vpMath.h>
41#include <visp3/core/vpMatrix.h>
44#include <visp3/core/vpException.h>
45#include <visp3/core/vpMatrixException.h>
48#ifdef VISP_HAVE_LAPACK
50#if !(GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2)
52#include <gsl/gsl_blas.h>
53#include <gsl/gsl_math.h>
54#include <gsl/gsl_matrix.h>
55#include <gsl/gsl_vector.h>
57#include <gsl/gsl_linalg.h>
58#include <gsl/gsl_permutation.h>
62typedef MKL_INT integer;
64integer allocate_work(
double **work)
66 integer dimWork = (integer)((*work)[0]);
68 *work =
new double[dimWork];
69 return (integer)dimWork;
71#elif !defined(VISP_HAVE_GSL)
72#ifdef VISP_HAVE_LAPACK_BUILT_IN
73typedef long int integer;
77extern "C" int dgeqrf_(integer *m, integer *n,
double *a, integer *lda,
double *tau,
double *work, integer *lwork,
79extern "C" int dormqr_(
char *side,
char *trans, integer *m, integer *n, integer *k,
double *a, integer *lda,
80 double *tau,
double *c__, integer *ldc,
double *work, integer *lwork, integer *info);
81extern "C" int dorgqr_(integer *, integer *, integer *,
double *, integer *,
double *,
double *, integer *, integer *);
82extern "C" int dtrtri_(
char *uplo,
char *diag, integer *n,
double *a, integer *lda, integer *info);
83extern "C" int dgeqp3_(integer *m, integer *n,
double *a, integer *lda, integer *p,
double *tau,
double *work,
84 integer *lwork, integer *info);
86int allocate_work(
double **work);
88int allocate_work(
double **work)
90 unsigned int dimWork =
static_cast<unsigned int>((*work)[0]);
92 *work =
new double[dimWork];
93 return static_cast<int>(dimWork);
98#if defined(VISP_HAVE_GSL)
99#ifndef DOXYGEN_SHOULD_SKIP_THIS
100void display_gsl(gsl_matrix *M)
103 for (
unsigned int i = 0;
i < M->size1; ++
i) {
104 unsigned int k =
i * M->tda;
105 for (
unsigned int j = 0;
j < M->size2; ++
j) {
106 std::cout << M->data[k +
j] <<
" ";
108 std::cout << std::endl;
114#if defined(VISP_HAVE_LAPACK)
150#if defined(VISP_HAVE_GSL)
154 gsl_matrix *gsl_A, *gsl_Q, *gsl_R, gsl_inv;
160 gsl_tau = gsl_vector_alloc(std::min<unsigned int>(
rowNum,
colNum));
162 gsl_inv.size1 = inv.
rowNum;
163 gsl_inv.size2 = inv.
colNum;
164 gsl_inv.tda = gsl_inv.size2;
165 gsl_inv.data = inv.
data;
170 unsigned int Atda =
static_cast<unsigned int>(gsl_A->tda);
171 size_t len =
sizeof(double) *
colNum;
172 for (
unsigned int i = 0; i <
rowNum; ++i) {
173 unsigned int k = i * Atda;
174 memcpy(&gsl_A->data[k], (*
this)[i], len);
176 gsl_linalg_QR_decomp(gsl_A, gsl_tau);
177 gsl_linalg_QR_unpack(gsl_A, gsl_tau, gsl_Q, gsl_R);
178#if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2)
179 gsl_linalg_tri_upper_invert(gsl_R);
184 for (
unsigned int i = 0; i <
rowNum; ++i) {
185 double *Tii = gsl_matrix_ptr(gsl_R, i, i);
187 double aii = -(*Tii);
189 m = gsl_matrix_submatrix(gsl_R, 0, 0, i, i);
190 v = gsl_matrix_subcolumn(gsl_R, i, 0, i);
191 gsl_blas_dtrmv(CblasUpper, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
192 gsl_blas_dscal(aii, &v.vector);
197 gsl_matrix_transpose(gsl_Q);
199 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, gsl_R, gsl_Q, 0, &gsl_inv);
200 unsigned int gsl_inv_tda =
static_cast<unsigned int>(gsl_inv.tda);
201 size_t inv_len =
sizeof(double) * inv.
colNum;
202 for (
unsigned int i = 0; i < inv.
rowNum; ++i) {
203 unsigned int k = i * gsl_inv_tda;
204 memcpy(inv[i], &gsl_inv.
data[k], inv_len);
207 gsl_matrix_free(gsl_A);
208 gsl_matrix_free(gsl_Q);
209 gsl_matrix_free(gsl_R);
210 gsl_vector_free(gsl_tau);
221 integer rowNum_ = (integer)this->
getRows();
222 integer colNum_ = (integer)this->
getCols();
223 integer lda = (integer)rowNum_;
224 integer dimTau = std::min<integer>(rowNum_, colNum_);
225 integer dimWork = -1;
226 double *tau =
new double[dimTau];
227 double *work =
new double[1];
254 std::cout <<
"dgeqrf_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
257 dimWork = allocate_work(&work);
279 std::cout <<
"dgeqrf_:" << -info <<
"th element had an illegal value" << std::endl;
288 dtrtri_((
char *)
"U", (
char *)
"N", &dimTau, C.
data, &lda, &info);
291 std::cout <<
"dtrtri_:" << -info <<
"th element had an illegal value" << std::endl;
293 std::cout <<
"dtrtri_:R(" << info <<
"," << info <<
")"
294 <<
" is exactly zero. The triangular matrix is singular "
295 "and its inverse can not be computed."
297 std::cout <<
"R=" << std::endl << C << std::endl;
306 for (
unsigned int i = 0; i < C.
getRows(); ++i)
307 for (
unsigned int j = 0; j < C.
getRows(); ++j)
318 dormqr_((
char *)
"R", (
char *)
"T", &rowNum_, &colNum_, &dimTau, A.
data, &lda, tau, C.
data, &ldc, work, &dimWork,
321 std::cout <<
"dormqr_:Preparation" << -info <<
"th element had an illegal value" << std::endl;
324 dimWork = allocate_work(&work);
326 dormqr_((
char *)
"R", (
char *)
"T", &rowNum_, &colNum_, &dimTau, A.
data, &lda, tau, C.
data, &ldc, work, &dimWork,
330 std::cout <<
"dormqr_:" << -info <<
"th element had an illegal value" << std::endl;
384#if defined(VISP_HAVE_LAPACK)
451#if defined(VISP_HAVE_LAPACK)
452#if defined(VISP_HAVE_GSL)
455 unsigned int r = std::min<unsigned int>(n, m);
466 Q.resize(m, q,
false);
468 R.resize(r, r,
false);
470 R.resize(r, n,
false);
474 gsl_matrix *gsl_A, *gsl_Q, *gsl_R, gsl_Qfull;
479 gsl_tau = gsl_vector_alloc(std::min<unsigned int>(
rowNum,
colNum));
482 unsigned int Atda =
static_cast<unsigned int>(gsl_A->tda);
483 size_t len =
sizeof(double) *
colNum;
484 for (
unsigned int i = 0; i <
rowNum; ++i) {
485 unsigned int k = i * Atda;
486 memcpy(&gsl_A->data[k], (*
this)[i], len);
491 gsl_linalg_QR_decomp(gsl_A, gsl_tau);
496 gsl_Qfull.size1 = Q.rowNum;
497 gsl_Qfull.size2 = Q.colNum;
498 gsl_Qfull.tda = gsl_Qfull.size2;
499 gsl_Qfull.data = Q.data;
503 gsl_linalg_QR_unpack(gsl_A, gsl_tau, &gsl_Qfull, gsl_R);
510 gsl_linalg_QR_unpack(gsl_A, gsl_tau, gsl_Q, gsl_R);
514 unsigned int Qtda =
static_cast<unsigned int>(gsl_Q->tda);
515 size_t len =
sizeof(double) * Q.colNum;
516 for (
unsigned int i = 0; i < Q.rowNum; ++i) {
517 unsigned int k = i * Qtda;
518 memcpy(Q[i], &gsl_Q->data[k], len);
523 gsl_matrix_free(gsl_Q);
527 na = std::min<unsigned int>(m, n);
528 unsigned int Rtda =
static_cast<unsigned int>(gsl_R->tda);
529 size_t Rlen =
sizeof(double) * R.colNum;
530 for (
unsigned int i = 0; i < na; ++i) {
531 unsigned int k = i * Rtda;
532 memcpy(R[i], &gsl_R->data[k], Rlen);
535 if (std::abs(gsl_R->data[k + i]) < tol)
539 gsl_matrix_free(gsl_A);
540 gsl_matrix_free(gsl_R);
541 gsl_vector_free(gsl_tau);
545 integer m = (integer)
rowNum;
546 integer n = (integer)
colNum;
547 integer r = std::min<integer>(n, m);
558 Q.resize(
static_cast<unsigned int>(m),
static_cast<unsigned int>(q));
560 R.resize(
static_cast<unsigned int>(r),
static_cast<unsigned int>(r));
562 R.resize(
static_cast<unsigned int>(r),
static_cast<unsigned int>(n));
566 integer dimWork = -1;
567 double *qrdata =
new double[m * na];
568 double *tau =
new double[std::min<integer>(m, q)];
569 double *work =
new double[1];
573 for (integer i = 0; i < m; ++i) {
574 for (integer j = 0; j < n; ++j)
575 qrdata[i + m * j] =
data[j + n * i];
576 for (integer j = n; j < na; ++j)
577 qrdata[i + m * j] = 0;
591 std::cout <<
"dgeqrf_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
597 dimWork = allocate_work(&work);
610 std::cout <<
"dgeqrf_:" << -info <<
"th element had an illegal value" << std::endl;
620 na = std::min<integer>(m, n);
622 for (
int i = 0; i < na; ++i) {
623 for (
int j = i; j < na; ++j)
624 R[i][j] = qrdata[i + m * j];
625 if (std::abs(qrdata[i + m * i]) < tol)
630 for (
int i = 0; i < na; ++i) {
631 for (
int j = i; j < n; ++j)
632 R[i][j] = qrdata[i + m * j];
633 if (std::abs(qrdata[i + m * i]) < tol)
650 for (
int i = 0; i < m; ++i)
651 for (
int j = 0; j < q; ++j)
652 Q[i][j] = qrdata[i + m * j];
657 return static_cast<unsigned int>(r);
669#if defined(VISP_HAVE_LAPACK)
670#if !defined(VISP_HAVE_GSL)
736unsigned int vpMatrix::qrPivotLapack(
vpMatrix &Q,
vpMatrix &R,
vpMatrix &P,
bool full,
bool squareR,
double tol)
const
738 integer m =
static_cast<integer
>(
rowNum);
739 integer n =
static_cast<integer
>(
colNum);
740 integer r = std::min<integer>(n, m);
752 Q.resize(
static_cast<unsigned int>(m),
static_cast<unsigned int>(q));
756 P.
resize(0,
static_cast<unsigned int>(n));
759 R.resize(
static_cast<unsigned int>(r),
static_cast<unsigned int>(n));
760 P.
resize(
static_cast<unsigned int>(n),
static_cast<unsigned int>(n));
765 integer dimWork = -1;
766 integer min_q_m = std::min<integer>(q, m);
767 double *qrdata =
new double[m * na];
768 double *tau =
new double[min_q_m];
769 double *work =
new double[1];
770 integer *
p =
new integer[na];
771 for (
int i = 0;
i < na; ++
i) {
778 for (integer i = 0;
i < m; ++
i) {
779 for (integer j = 0;
j < n; ++
j) {
780 qrdata[
i + m *
j] =
data[
j + n *
i];
782 for (integer j = n;
j < na; ++
j) {
783 qrdata[
i + m *
j] = 0;
796 dgeqp3_(&m, &na, qrdata, &m, p, tau, work, &dimWork, &info);
799 std::cout <<
"dgeqp3_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
807 dimWork = allocate_work(&work);
817 dgeqp3_(&m, &na, qrdata, &m, p, tau, work, &dimWork, &info);
820 std::cout <<
"dgeqp3_:" << -info <<
" th element had an illegal value" << std::endl;
830 na = std::min<integer>(n, m);
831 for (
int i = 0;
i < na; ++
i) {
832 if (std::abs(qrdata[i + m * i]) < tol) {
840 R.resize(
static_cast<unsigned int>(r),
static_cast<unsigned int>(r));
841 for (
int i = 0;
i <
r; ++
i) {
842 for (
int j = i;
j <
r; ++
j) {
843 R[
i][
j] = qrdata[
i + m *
j];
848 P.
resize(
static_cast<unsigned int>(r),
static_cast<unsigned int>(n));
849 for (
int i = 0;
i <
r; ++
i) {
855 R.resize(
static_cast<unsigned int>(na),
static_cast<unsigned int>(n));
856 for (
int i = 0;
i < na; ++
i) {
857 for (
int j = i;
j < n; ++
j) {
858 R[
i][
j] = qrdata[
i + m *
j];
862 P.
resize(
static_cast<unsigned int>(n),
static_cast<unsigned int>(n));
863 for (
int i = 0;
i < n; ++
i) {
875 dorgqr_(&m, &q, &q, qrdata, &m, tau, work, &dimWork, &info);
878 for (
int i = 0;
i < m; ++
i) {
879 for (
int j = 0;
j < q; ++
j) {
880 Q[
i][
j] = qrdata[
i + m *
j];
888 return static_cast<unsigned int>(
r);
958unsigned int vpMatrix::qrPivotLapackGSL(
vpMatrix &Q,
vpMatrix &R,
vpMatrix &P,
bool full,
bool squareR,
double tol)
const
962 unsigned int r = std::min<unsigned int>(n, m);
973 Q.resize(m, q,
false);
976 R.resize(0, 0,
false);
980 R.resize(r, n,
false);
986 gsl_matrix gsl_A, *gsl_Q, *gsl_R, gsl_Qfull;
988 gsl_permutation *gsl_p;
989 gsl_vector *gsl_norm;
994 gsl_A.tda = gsl_A.size2;
995 gsl_A.data = this->
data;
1000 gsl_tau = gsl_vector_alloc(std::min<unsigned int>(
rowNum,
colNum));
1001 gsl_norm = gsl_vector_alloc(
colNum);
1002 gsl_p = gsl_permutation_alloc(n);
1007 gsl_Qfull.size1 =
Q.rowNum;
1008 gsl_Qfull.size2 =
Q.colNum;
1009 gsl_Qfull.tda = gsl_Qfull.size2;
1010 gsl_Qfull.data =
Q.data;
1011 gsl_Qfull.owner = 0;
1012 gsl_Qfull.block = 0;
1014 gsl_linalg_QRPT_decomp2(&gsl_A, &gsl_Qfull, gsl_R, gsl_tau, gsl_p, &gsl_signum, gsl_norm);
1021 gsl_linalg_QRPT_decomp2(&gsl_A, gsl_Q, gsl_R, gsl_tau, gsl_p, &gsl_signum, gsl_norm);
1025 unsigned int Qtda =
static_cast<unsigned int>(gsl_Q->tda);
1026 size_t len =
sizeof(double) *
Q.colNum;
1027 for (
unsigned int i = 0;
i <
Q.rowNum; ++
i) {
1028 unsigned int k =
i * Qtda;
1029 memcpy(Q[i], &gsl_Q->data[k], len);
1034 gsl_matrix_free(gsl_Q);
1038 na = std::min<unsigned int>(m, n);
1039 unsigned int Rtda =
static_cast<unsigned int>(gsl_R->tda);
1040 for (
unsigned int i = 0;
i < na; ++
i) {
1041 unsigned int k =
i * Rtda;
1042 if (std::abs(gsl_R->data[k + i]) < tol)
1047 R.resize(r, r,
false);
1049 for (
unsigned int i = 0;
i <
r; ++
i)
1050 P[i][gsl_p->data[i]] = 1;
1053 R.resize(na, n,
false);
1055 for (
unsigned int i = 0;
i < n; ++
i)
1056 P[i][gsl_p->data[i]] = 1;
1060 size_t Rlen =
sizeof(double) *
R.colNum;
1061 for (
unsigned int i = 0;
i < na; ++
i) {
1062 unsigned int k =
i * Rtda;
1063 memcpy(R[i], &gsl_R->data[k], Rlen);
1066 gsl_matrix_free(gsl_R);
1067 gsl_vector_free(gsl_tau);
1068 gsl_vector_free(gsl_norm);
1069 gsl_permutation_free(gsl_p);
1144#if defined(VISP_HAVE_LAPACK)
1145#if defined(VISP_HAVE_GSL)
1146 return qrPivotLapackGSL(Q, R, P, full, squareR, tol);
1148 return qrPivotLapack(Q, R, P, full, squareR, tol);
1178#if defined(VISP_HAVE_LAPACK)
1179#if defined(VISP_HAVE_GSL)
1184 gsl_inv.size1 = inv.
rowNum;
1185 gsl_inv.size2 = inv.
colNum;
1186 gsl_inv.tda = gsl_inv.size2;
1187 gsl_inv.data = inv.
data;
1191 unsigned int tda =
static_cast<unsigned int>(gsl_inv.tda);
1192 size_t len =
sizeof(double) * inv.
colNum;
1193 for (
unsigned int i = 0; i <
rowNum; ++i) {
1194 unsigned int k = i * tda;
1195 memcpy(&gsl_inv.data[k], (*
this)[i], len);
1199#if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2)
1200 gsl_linalg_tri_upper_invert(&gsl_inv);
1205 for (
unsigned int i = 0; i <
rowNum; ++i) {
1206 double *Tii = gsl_matrix_ptr(&gsl_inv, i, i);
1208 double aii = -(*Tii);
1210 m = gsl_matrix_submatrix(&gsl_inv, 0, 0, i, i);
1211 v = gsl_matrix_subcolumn(&gsl_inv, i, 0, i);
1212 gsl_blas_dtrmv(CblasUpper, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
1213 gsl_blas_dscal(aii, &v.vector);
1220#if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2)
1221 gsl_linalg_tri_lower_invert(&gsl_inv);
1226 for (
unsigned int i = 0; i <
rowNum; ++i) {
1227 size_t j =
rowNum - i - 1;
1228 double *Tjj = gsl_matrix_ptr(&gsl_inv, j, j);
1229 *Tjj = 1.0 / (*Tjj);
1230 double ajj = -(*Tjj);
1232 m = gsl_matrix_submatrix(&gsl_inv, j + 1, j + 1,
rowNum - j - 1,
rowNum - j - 1);
1233 v = gsl_matrix_subcolumn(&gsl_inv, j, j + 1,
rowNum - j - 1);
1234 gsl_blas_dtrmv(CblasLower, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
1235 gsl_blas_dscal(ajj, &v.vector);
1244 integer n = (integer)
rowNum;
1251 dtrtri_((
char *)
"L", (
char *)
"N", &n, R.data, &n, &info);
1253 dtrtri_((
char *)
"U", (
char *)
"N", &n, R.data, &n, &info);
1257 std::cout <<
"dtrtri_:" << -info <<
"th element had an illegal value" << std::endl;
1258 else if (info > 0) {
1259 std::cout <<
"dtrtri_:R(" << info <<
"," << info <<
")"
1260 <<
" is exactly zero. The triangular matrix is singular "
1261 "and its inverse can not be computed."
1325 unsigned int r =
t().
qrPivot(Q, R, P,
false,
true);
1326 x = Q.extract(0, 0,
colNum, r) * R.inverseTriangular().t() * P * b;
unsigned int getCols() const
Type * data
Address of the first element of the data array.
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int getRows() const
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ dimensionError
Bad dimension.
error that can be emitted by the vpMatrix class and its derivatives
@ rankDeficient
Rank deficient.
@ matrixError
Matrix operation error.
Implementation of a matrix and operations on matrices.
unsigned int qr(vpMatrix &Q, vpMatrix &R, bool full=false, bool squareR=false, double tol=1e-6) const
vpMatrix inverseTriangular(bool upper=true) const
unsigned int qrPivot(vpMatrix &Q, vpMatrix &R, vpMatrix &P, bool full=false, bool squareR=false, double tol=1e-6) const
vpMatrix inverseByQRLapack() const
void solveByQR(const vpColVector &b, vpColVector &x) const
vpMatrix inverseByQR() const