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>
62 typedef MKL_INT integer;
64 integer 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
73 typedef long int integer;
77 extern "C" int dgeqrf_(integer *m, integer *n,
double *a, integer *lda,
double *tau,
double *work, integer *lwork,
79 extern "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);
81 extern "C" int dorgqr_(integer *, integer *, integer *,
double *, integer *,
double *,
double *, integer *, integer *);
82 extern "C" int dtrtri_(
char *uplo,
char *diag, integer *n,
double *a, integer *lda, integer *info);
83 extern "C" int dgeqp3_(integer *m, integer *n,
double *a, integer *lda, integer *p,
double *tau,
double *work,
84 integer *lwork, integer *info);
86 int allocate_work(
double **work);
88 int allocate_work(
double **work)
90 unsigned int dimWork = (
unsigned int)((*work)[0]);
92 *work =
new double[dimWork];
98 #if defined(VISP_HAVE_GSL)
99 #ifndef DOXYGEN_SHOULD_SKIP_THIS
100 void 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);
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 (
unsigned int)r;
669 #if defined(VISP_HAVE_LAPACK)
670 #if !defined(VISP_HAVE_GSL)
736 unsigned 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);
958 unsigned 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);
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)
1049 for (
unsigned int i = 0; i < r; ++i)
1050 P[i][gsl_p->data[i]] = 1;
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);
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 rowNum
Number of rows in the array.
unsigned int getRows() const
unsigned int colNum
Number of columns in the array.
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
vpMatrix extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) const