43 #include <visp3/core/vpConfig.h> 45 #include <visp3/core/vpColVector.h> 46 #include <visp3/core/vpMath.h> 47 #include <visp3/core/vpMatrix.h> 50 #include <visp3/core/vpException.h> 51 #include <visp3/core/vpMatrixException.h> 54 #include <visp3/core/vpDebug.h> 56 #ifdef VISP_HAVE_LAPACK 58 # if !(GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2) 60 # include <gsl/gsl_math.h> 61 # include <gsl/gsl_vector.h> 62 # include <gsl/gsl_matrix.h> 63 # include <gsl/gsl_blas.h> 65 # include <gsl/gsl_linalg.h> 66 # include <gsl/gsl_permutation.h> 70 typedef MKL_INT integer;
72 integer allocate_work(
double **work)
74 integer dimWork = (integer)((*work)[0]);
76 *work =
new double[dimWork];
77 return (integer)dimWork;
79 # elif !defined(VISP_HAVE_GSL) 80 # ifdef VISP_HAVE_LAPACK_BUILT_IN 81 typedef long int integer;
85 extern "C" int dgeqrf_(integer *m, integer *n,
double *a, integer *lda,
double *tau,
double *work, integer *lwork,
87 extern "C" int dormqr_(
char *side,
char *trans, integer *m, integer *n, integer *k,
double *a, integer *lda,
88 double *tau,
double *c__, integer *ldc,
double *work, integer *lwork, integer *info);
89 extern "C" int dorgqr_(integer *, integer *, integer *,
double *, integer *,
double *,
double *, integer *, integer *);
90 extern "C" int dtrtri_(
char *uplo,
char *diag, integer *n,
double *a, integer *lda, integer *info);
91 extern "C" int dgeqp3_(integer *m, integer *n,
double*a, integer *lda, integer *p,
92 double *tau,
double *work, integer* lwork, integer *info);
94 int allocate_work(
double **work);
96 int allocate_work(
double **work)
98 unsigned int dimWork = (
unsigned int)((*work)[0]);
100 *work =
new double[dimWork];
106 #if defined(VISP_HAVE_GSL) 107 #ifndef DOXYGEN_SHOULD_SKIP_THIS 108 void display_gsl(gsl_matrix *M)
111 for (
unsigned int i = 0; i < M->size1; i++) {
112 unsigned int k = i * M->tda;
113 for (
unsigned int j = 0; j < M->size2; j++) {
114 std:: cout << M->data[k + j] <<
" ";
116 std::cout << std::endl;
122 #if defined(VISP_HAVE_LAPACK) 154 #if defined(VISP_HAVE_GSL) 158 gsl_matrix *gsl_A, *gsl_Q, *gsl_R, gsl_inv;
166 gsl_inv.size1 = inv.
rowNum;
167 gsl_inv.size2 = inv.
colNum;
168 gsl_inv.tda = gsl_inv.size2;
169 gsl_inv.data = inv.
data;
174 unsigned int Atda =
static_cast<unsigned int>(gsl_A->tda);
175 size_t len =
sizeof(double) *
colNum;
176 for (
unsigned int i = 0; i <
rowNum; i++) {
177 unsigned int k = i * Atda;
178 memcpy(&gsl_A->data[k], (*
this)[i], len);
180 gsl_linalg_QR_decomp(gsl_A, gsl_tau);
181 gsl_linalg_QR_unpack(gsl_A, gsl_tau, gsl_Q, gsl_R);
182 #if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2) 183 gsl_linalg_tri_upper_invert(gsl_R);
188 for (
unsigned int i = 0; i <
rowNum; i++) {
189 double *Tii = gsl_matrix_ptr(gsl_R, i, i);
191 double aii = -(*Tii);
193 m = gsl_matrix_submatrix(gsl_R, 0, 0, i, i);
194 v = gsl_matrix_subcolumn(gsl_R, i, 0, i);
195 gsl_blas_dtrmv(CblasUpper, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
196 gsl_blas_dscal(aii, &v.vector);
201 gsl_matrix_transpose(gsl_Q);
203 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, gsl_R, gsl_Q, 0, &gsl_inv);
204 unsigned int gsl_inv_tda =
static_cast<unsigned int>(gsl_inv.tda);
205 size_t inv_len =
sizeof(double) * inv.
colNum;
206 for(
unsigned int i = 0; i < inv.
rowNum; i++) {
207 unsigned int k = i * gsl_inv_tda;
208 memcpy(inv[i], &gsl_inv.
data[k], inv_len);
211 gsl_matrix_free(gsl_A);
212 gsl_matrix_free(gsl_Q);
213 gsl_matrix_free(gsl_R);
214 gsl_vector_free(gsl_tau);
225 integer rowNum_ = (integer)this->
getRows();
226 integer colNum_ = (integer)this->
getCols();
227 integer lda = (integer)rowNum_;
228 integer dimTau = (std::min)(rowNum_, colNum_);
229 integer dimWork = -1;
230 double *tau =
new double[dimTau];
231 double *work =
new double[1];
258 std::cout <<
"dgeqrf_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
261 dimWork = allocate_work(&work);
283 std::cout <<
"dgeqrf_:" << -info <<
"th element had an illegal value" << std::endl;
292 dtrtri_((
char *)
"U", (
char *)
"N", &dimTau, C.
data, &lda, &info);
295 std::cout <<
"dtrtri_:" << -info <<
"th element had an illegal value" << std::endl;
297 std::cout <<
"dtrtri_:R(" << info <<
"," << info <<
")" 298 <<
" is exactly zero. The triangular matrix is singular " 299 "and its inverse can not be computed." 301 std::cout <<
"R=" << std::endl << C << std::endl;
310 for (
unsigned int i = 0; i < C.
getRows(); i++)
311 for (
unsigned int j = 0; j < C.
getRows(); j++)
322 dormqr_((
char *)
"R", (
char *)
"T", &rowNum_, &colNum_, &dimTau, A.
data, &lda, tau, C.
data, &ldc, work, &dimWork,
325 std::cout <<
"dormqr_:Preparation" << -info <<
"th element had an illegal value" << std::endl;
328 dimWork = allocate_work(&work);
330 dormqr_((
char *)
"R", (
char *)
"T", &rowNum_, &colNum_, &dimTau, A.
data, &lda, tau, C.
data, &ldc, work, &dimWork,
334 std::cout <<
"dormqr_:" << -info <<
"th element had an illegal value" << std::endl;
383 #if defined(VISP_HAVE_LAPACK) 446 #if defined(VISP_HAVE_LAPACK) 447 #if defined(VISP_HAVE_GSL) 450 unsigned int r = std::min(n, m);
469 gsl_matrix *gsl_A, *gsl_Q, *gsl_R, gsl_Qfull;
477 unsigned int Atda =
static_cast<unsigned int>(gsl_A->tda);
478 size_t len =
sizeof(double) *
colNum;
479 for (
unsigned int i = 0; i <
rowNum; i++) {
480 unsigned int k = i * Atda;
481 memcpy(&gsl_A->data[k], (*
this)[i], len);
486 gsl_linalg_QR_decomp(gsl_A, gsl_tau);
491 gsl_Qfull.size1 = Q.
rowNum;
492 gsl_Qfull.size2 = Q.
colNum;
493 gsl_Qfull.tda = gsl_Qfull.size2;
494 gsl_Qfull.data = Q.
data;
498 gsl_linalg_QR_unpack(gsl_A, gsl_tau, &gsl_Qfull, gsl_R);
503 gsl_Q = gsl_matrix_alloc(rowNum, rowNum);
505 gsl_linalg_QR_unpack(gsl_A, gsl_tau, gsl_Q, gsl_R);
509 unsigned int Qtda =
static_cast<unsigned int>(gsl_Q->tda);
510 size_t len =
sizeof(double) * Q.
colNum;
511 for(
unsigned int i = 0; i < Q.
rowNum; i++) {
512 unsigned int k = i * Qtda;
513 memcpy(Q[i], &gsl_Q->
data[k], len);
518 gsl_matrix_free(gsl_Q);
523 unsigned int Rtda =
static_cast<unsigned int>(gsl_R->tda);
524 size_t Rlen =
sizeof(double) * R.
colNum;
525 for(
unsigned int i = 0; i < na; i++) {
526 unsigned int k = i * Rtda;
527 memcpy(R[i], &gsl_R->
data[k], Rlen);
530 if(std::abs(gsl_R->data[k + i]) < tol)
534 gsl_matrix_free(gsl_A);
535 gsl_matrix_free(gsl_R);
536 gsl_vector_free(gsl_tau);
540 integer m = (integer)rowNum;
541 integer n = (integer)
colNum;
542 integer r = std::min(n, m);
553 Q.
resize(static_cast<unsigned int>(m), static_cast<unsigned int>(q));
555 R.
resize(static_cast<unsigned int>(r), static_cast<unsigned int>(r));
557 R.
resize(static_cast<unsigned int>(r), static_cast<unsigned int>(n));
561 integer dimWork = -1;
562 double * qrdata =
new double[m*na];
563 double *tau =
new double[std::min(m,q)];
564 double *work =
new double[1];
568 for (integer i = 0; i < m; ++i)
570 for (integer j = 0; j < n; ++j)
571 qrdata[i + m * j] =
data[j + n * i];
572 for (integer j = n; j < na; ++j)
573 qrdata[i + m * j] = 0;
590 std::cout <<
"dgeqrf_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
596 dimWork = allocate_work(&work);
610 std::cout <<
"dgeqrf_:" << -info <<
"th element had an illegal value" << std::endl;
623 for(
int i=0;i<na;i++)
625 for(
int j=i;j<na;j++)
626 R[i][j] = qrdata[i+m*j];
627 if(std::abs(qrdata[i+m*i]) < tol)
633 for(
int i=0;i<na;i++)
636 R[i][j] = qrdata[i+m*j];
637 if(std::abs(qrdata[i+m*i]) < tol)
655 for(
int i = 0; i < m; ++i)
656 for(
int j = 0; j < q; ++j)
657 Q[i][j] = qrdata[i+m*j];
662 return (
unsigned int) r;
663 #endif // defined(VISP_HAVE_GSL) 739 #if defined(VISP_HAVE_LAPACK) 740 #if defined(VISP_HAVE_GSL) 743 unsigned int r = std::min(n, m);
767 gsl_matrix gsl_A, *gsl_Q, *gsl_R, gsl_Qfull;
769 gsl_permutation *gsl_p;
770 gsl_vector *gsl_norm;
775 gsl_A.tda = gsl_A.size2;
776 gsl_A.data = this->
data;
782 gsl_norm = gsl_vector_alloc(
colNum);
783 gsl_p = gsl_permutation_alloc(n);
788 gsl_Qfull.size1 = Q.
rowNum;
789 gsl_Qfull.size2 = Q.
colNum;
790 gsl_Qfull.tda = gsl_Qfull.size2;
791 gsl_Qfull.data = Q.
data;
795 gsl_linalg_QRPT_decomp2(&gsl_A, &gsl_Qfull, gsl_R, gsl_tau, gsl_p, &gsl_signum, gsl_norm);
802 gsl_linalg_QRPT_decomp2(&gsl_A, gsl_Q, gsl_R, gsl_tau, gsl_p, &gsl_signum, gsl_norm);
806 unsigned int Qtda =
static_cast<unsigned int>(gsl_Q->tda);
807 size_t len =
sizeof(double) * Q.
colNum;
808 for(
unsigned int i = 0; i < Q.
rowNum; i++) {
809 unsigned int k = i * Qtda;
810 memcpy(Q[i], &gsl_Q->
data[k], len);
815 gsl_matrix_free(gsl_Q);
820 unsigned int Rtda =
static_cast<unsigned int>(gsl_R->tda);
821 for(
unsigned int i = 0; i < na; i++) {
822 unsigned int k = i * Rtda;
823 if(std::abs(gsl_R->data[k + i]) < tol)
830 for(
unsigned int i = 0; i < r; ++i)
831 P[i][gsl_p->data[i]] = 1;
836 for(
unsigned int i = 0; i < n; ++i)
837 P[i][gsl_p->data[i]] = 1;
841 size_t Rlen =
sizeof(double) * R.
colNum;
842 for(
unsigned int i = 0; i < na; i++) {
843 unsigned int k = i * Rtda;
844 memcpy(R[i], &gsl_R->
data[k], Rlen);
847 gsl_matrix_free(gsl_R);
848 gsl_vector_free(gsl_tau);
849 gsl_vector_free(gsl_norm);
850 gsl_permutation_free(gsl_p);
854 integer m = (integer)
rowNum;
855 integer n = (integer)
colNum;
856 integer r = std::min(n, m);
868 Q.
resize(static_cast<unsigned int>(m), static_cast<unsigned int>(q));
872 P.
resize(0, static_cast<unsigned int>(n));
875 R.
resize(static_cast<unsigned int>(r), static_cast<unsigned int>(n));
876 P.
resize(static_cast<unsigned int>(n), static_cast<unsigned int>(n));
881 integer dimWork = -1;
882 double* qrdata =
new double[m*na];
883 double* tau =
new double[std::min(q,m)];
884 double* work =
new double[1];
885 integer* p =
new integer[na];
886 for(
int i = 0; i < na; ++i)
892 for(integer i = 0; i < m; ++i)
894 for(integer j = 0; j < n; ++j)
895 qrdata[i+m*j] =
data[j + n*i];
896 for(integer j = n; j < na; ++j)
915 std::cout <<
"dgeqp3_:Preparation:" << -info <<
"th element had an illegal value" << std::endl;
923 dimWork = allocate_work(&work);
939 std::cout <<
"dgeqp3_:" << -info <<
" th element had an illegal value" << std::endl;
950 for(
int i = 0; i < na; ++i)
951 if(std::abs(qrdata[i+m*i]) < tol)
957 R.
resize(static_cast<unsigned int>(r), static_cast<unsigned int>(r));
960 R[i][j] = qrdata[i+m*j];
963 P.
resize(static_cast<unsigned int>(r), static_cast<unsigned int>(n));
964 for(
int i = 0; i < r; ++i)
969 R.
resize(static_cast<unsigned int>(na), static_cast<unsigned int>(n));
970 for(
int i=0;i<na;i++)
972 R[i][j] = qrdata[i+m*j];
974 P.
resize(static_cast<unsigned int>(n), static_cast<unsigned int>(n));
975 for(
int i = 0; i < n; ++i)
992 for(
int i = 0; i < m; ++i)
993 for(
int j = 0; j < q; ++j)
994 Q[i][j] = qrdata[i+m*j];
1000 return (
unsigned int) r;
1028 "Cannot inverse a triangular matrix (%d, %d) that is not square",
rowNum,
colNum));
1030 #if defined(VISP_HAVE_LAPACK) 1031 #if defined(VISP_HAVE_GSL) 1036 gsl_inv.size1 = inv.
rowNum;
1037 gsl_inv.size2 = inv.
colNum;
1038 gsl_inv.tda = gsl_inv.size2;
1039 gsl_inv.data = inv.
data;
1043 unsigned int tda =
static_cast<unsigned int>(gsl_inv.tda);
1044 size_t len =
sizeof(double) * inv.
colNum;
1045 for (
unsigned int i = 0; i <
rowNum; i++) {
1046 unsigned int k = i * tda;
1047 memcpy(&gsl_inv.data[k], (*
this)[i], len);
1051 #if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2) 1052 gsl_linalg_tri_upper_invert(&gsl_inv);
1057 for (
unsigned int i = 0; i <
rowNum; i++) {
1058 double *Tii = gsl_matrix_ptr(&gsl_inv, i, i);
1060 double aii = -(*Tii);
1062 m = gsl_matrix_submatrix(&gsl_inv, 0, 0, i, i);
1063 v = gsl_matrix_subcolumn(&gsl_inv, i, 0, i);
1064 gsl_blas_dtrmv(CblasUpper, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
1065 gsl_blas_dscal(aii, &v.vector);
1072 #if (GSL_MAJOR_VERSION >= 2 && GSL_MINOR_VERSION >= 2) 1073 gsl_linalg_tri_lower_invert(&gsl_inv);
1078 for (
unsigned int i = 0; i <
rowNum; i++) {
1079 size_t j = rowNum - i - 1;
1080 double *Tjj = gsl_matrix_ptr(&gsl_inv, j, j);
1081 *Tjj = 1.0 / (*Tjj);
1082 double ajj = -(*Tjj);
1083 if (j < rowNum - 1) {
1084 m = gsl_matrix_submatrix(&gsl_inv, j + 1, j + 1, rowNum - j - 1, rowNum - j - 1);
1085 v = gsl_matrix_subcolumn(&gsl_inv, j, j + 1, rowNum - j - 1);
1086 gsl_blas_dtrmv(CblasLower, CblasNoTrans, CblasNonUnit, &m.matrix, &v.vector);
1087 gsl_blas_dscal(ajj, &v.vector);
1096 integer n = (integer) rowNum;
1102 if(rowNum > 1 && upper)
1103 dtrtri_((
char *)
"L", (
char *)
"N", &n, R.
data, &n, &info);
1105 dtrtri_((
char *)
"U", (
char *)
"N", &n, R.
data, &n, &info);
1109 std::cout <<
"dtrtri_:" << -info <<
"th element had an illegal value" << std::endl;
1110 else if (info > 0) {
1111 std::cout <<
"dtrtri_:R(" << info <<
"," << info <<
")" 1112 <<
" is exactly zero. The triangular matrix is singular " 1113 "and its inverse can not be computed." 1173 unsigned int r =
t().
qrPivot(Q, R, P,
false,
true);
Used to indicate that a value is not in the allowed range.
Implementation of a matrix and operations on matrices.
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
vpMatrix inverseTriangular(bool upper=true) const
error that can be emited by ViSP classes.
Type * data
Address of the first element of the data array.
unsigned int getCols() const
unsigned int qrPivot(vpMatrix &Q, vpMatrix &R, vpMatrix &P, bool full=false, bool squareR=false, double tol=1e-6) const
unsigned int qr(vpMatrix &Q, vpMatrix &R, bool full=false, bool squareR=false, double tol=1e-6) const
unsigned int rowNum
Number of rows in the array.
vpMatrix extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) const
unsigned int getRows() const
unsigned int colNum
Number of columns in the array.
void solveByQR(const vpColVector &b, vpColVector &x) const
vpMatrix inverseByQR() const
Implementation of column vector and the associated operations.
error that can be emited by the vpMatrix class and its derivates
vpMatrix inverseByQRLapack() const