38 #include <visp3/core/vpConfig.h>
40 #ifndef DOXYGEN_SHOULD_SKIP_THIS
42 #include <visp3/core/vpMatrix.h>
43 #include <visp3/core/vpMath.h>
44 #include <visp3/core/vpColVector.h>
45 #include <visp3/core/vpException.h>
46 #include <visp3/core/vpMatrixException.h>
47 #include <visp3/core/vpDebug.h>
61 static double pythag(
double a,
double b)
66 if (absa > absb)
return absa*sqrt(1.0+
vpMath::sqr(absb/absa));
68 else return (std::fabs(absb) <= std::numeric_limits<double>::epsilon() ? 0.0 : absb*sqrt(1.0+
vpMath::sqr(absa/absb)));
74 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
96 #define MAX_ITER_SVD 50
102 double epsilon = 10*std::numeric_limits<double>::epsilon();
104 unsigned int flag,i,its,j,jj,k,l=0,nm=0;
105 double c,f,h,s,x,y,z;
106 double anorm=0.0,g=0.0,scale=0.0;
110 double **a =
new double*[m+1];
111 double **v =
new double*[n+1];
115 double *w =
new double[n+1];
116 for (i=0;i<n;i++) w[i+1] = 0.0;
130 vpERROR_TRACE(
"\n\t\tSVDcmp: You must augment A with extra zero rows") ;
132 "\n\t\tSVDcmp: You must augment A with "
133 "extra zero rows")) ;
135 double* rv1=
new double[n+1];
142 for (k=i;k<=m;k++) scale += fabs(a[k][i]);
144 if ((std::fabs(scale) > epsilon)) {
147 s += a[k][i]*a[k][i];
150 g = -SIGN(sqrt(s),f);
155 for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
157 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
160 for (k=i;k<=m;k++) a[k][i] *= scale;
165 if (i <= m && i != n) {
166 for (k=l;k<=n;k++) scale += fabs(a[i][k]);
168 if ((std::fabs(scale) > epsilon) ) {
171 s += a[i][k]*a[i][k];
174 g = -SIGN(sqrt(s),f);
177 for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
180 for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
181 for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
184 for (k=l;k<=n;k++) a[i][k] *= scale;
192 if ((std::fabs(g) > epsilon) ) {
194 v[j][i]=(a[i][j]/a[i][l])/g;
196 for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
197 for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
200 for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
210 for (j=l;j<=n;j++) a[i][j]=0.0;
212 if ((std::fabs(g) > epsilon) ) {
216 for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
218 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
221 for (j=i;j<=m;j++) a[j][i] *= g;
223 for (j=i;j<=m;j++) a[j][i]=0.0;
228 for (its=1;its<=MAX_ITER_SVD;its++) {
233 if ((std::fabs(rv1[l]) <= epsilon) ) {
238 if ((std::fabs(w[nm]) <= epsilon) )
break;
246 if ((std::fabs(f) > epsilon) ) {
266 for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
270 if (its == MAX_ITER_SVD)
272 for (i=0;i<n;i++) W[i] = w[i+1];
275 std::cout << *
this <<std::endl ;
284 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
286 f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
288 for (j=l;j<=nm;j++) {
296 if ((std::fabs(z) > epsilon) ) {
304 for (jj=1;jj<=n;jj++) {
313 if ((std::fabs(z) > epsilon) ) {
320 for (jj=1;jj<=m;jj++) {
332 for (i=0;i<n;i++) W[i] = w[i+1];
366 unsigned int m = this->
rowNum;
367 unsigned int n = this->
colNum;
377 if (std::fabs(w[j]) > std::numeric_limits<double>::epsilon())
379 for (i=0;i<m;i++) s += u[i][j]*b[i];
386 for (jj=0;jj<n;jj++) s += v[j][jj]*tmp[jj];
413 #define TOLERANCE 1.0e-7
416 void svd_internal_use(
double *U,
double *S,
double *V,
417 unsigned int nRow,
unsigned int nCol)
419 unsigned int i, j, k, EstColRank, RotCount, SweepCount, slimit;
420 double eps, e2, tol, vt, p, x0, y0, q, r, c0, s0, d1, d2;
427 e2 = 10.0 * nRow * eps * eps;
431 for (i = 0; i < nCol; i++)
432 for (j = 0; j < nCol; j++) {
433 V[nCol * i + j] = 0.0;
434 V[nCol * i + i] = 1.0;
436 RotCount = EstColRank * (EstColRank - 1) / 2;
437 while (RotCount != 0 && SweepCount <= slimit) {
438 RotCount = EstColRank * (EstColRank - 1) / 2;
440 for (j = 0; j < EstColRank - 1; j++) {
441 for (k = j + 1; k < EstColRank; k++) {
443 for (i = 0; i < nRow; i++) {
444 x0 = U[nCol * i + j];
445 y0 = U[nCol * i + k];
453 if (q <= e2 * S[0] || fabs(p) <= tol * q)
458 vt = sqrt(4 * p * p + r * r);
459 c0 = sqrt(fabs(.5 * (1 + r / vt)));
461 for (i = 0; i < nRow; i++) {
462 d1 = U[nCol * i + j];
463 d2 = U[nCol * i + k];
464 U[nCol * i + j] = d1 * c0 + d2 * s0;
465 U[nCol * i + k] = -d1 * s0 + d2 * c0;
468 for (i = 0; i < nCol; i++) {
469 d1 = V[nCol * i + j];
470 d2 = V[nCol * i + k];
471 V[nCol * i + j] = d1 * c0 + d2 * s0;
472 V[nCol * i + k] = -d1 * s0 + d2 * c0;
479 vt = sqrt(4 * p * p + q * q);
480 s0 = sqrt(fabs(.5 * (1 - q / vt)));
484 for (i = 0; i < nRow; i++) {
485 d1 = U[nCol * i + j];
486 d2 = U[nCol * i + k];
487 U[nCol * i + j] = d1 * c0 + d2 * s0;
488 U[nCol * i + k] = -d1 * s0 + d2 * c0;
491 for (i = 0; i < nCol; i++) {
492 d1 = V[nCol * i + j];
493 d2 = V[nCol * i + k];
494 V[nCol * i + j] = d1 * c0 + d2 * s0;
495 V[nCol * i + k] = -d1 * s0 + d2 * c0;
500 while (EstColRank >= 3 && S[(EstColRank - 1)] <= S[0] * tol + tol * tol)
503 for(i = 0; i < nCol; i++)
505 for(i = 0; i < nCol; i++)
506 for(j = 0; j < nRow; j++)
507 U[nCol * j + i] = U[nCol * j + i] / S[i];
543 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
544 # include <opencv2/core/core.hpp>
546 int rows = (int)this->
getRows();
547 int cols = (int)this->
getCols();
548 cv::Mat m(rows, cols, CV_64F, this->
data);
549 cv::SVD opencvSVD(m);
550 cv::Mat opencvV = opencvSVD.vt;
551 cv::Mat opencvW = opencvSVD.w;
552 v.
resize((
unsigned int)opencvV.rows, (
unsigned int)opencvV.cols);
553 w.
resize((
unsigned int)(opencvW.rows*opencvW.cols));
555 memcpy(v.
data, opencvV.data, (
size_t)(8*opencvV.rows*opencvV.cols));
557 memcpy(w.
data, opencvW.data, (
size_t)(8*opencvW.rows*opencvW.cols));
558 this->
resize((
unsigned int)opencvSVD.u.rows, (
unsigned int)opencvSVD.u.cols);
559 memcpy(this->
data,opencvSVD.u.data, (
size_t)(8*opencvSVD.u.rows*opencvSVD.u.cols));
564 #ifdef VISP_HAVE_LAPACK_C
565 extern "C" int dgesdd_(
char *jobz,
int *m,
int *n,
double *a,
int *lda,
double *s,
double *u,
int *ldu,
double *vt,
int *ldvt,
double *work,
int *lwork,
int *iwork,
int *info);
570 int m =
static_cast<int>(this->
getCols()), n = static_cast<int>(this->
getRows()), lda = m, ldu = m, ldvt = std::min(m,n);
576 int* iwork =
new int[8*
static_cast<unsigned int>(std::min(n,m))];
579 double* a =
new double[
static_cast<unsigned int>(lda*n)];
582 double* vt = this->
data;
587 dgesdd_( (
char*)
"S", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &wkopt, &lwork, iwork, &info );
589 work =
new double[
static_cast<unsigned int>(lwork)];
591 dgesdd_( (
char*)
"S", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info );
594 vpTRACE(
"The algorithm computing SVD failed to converge.");
596 "The algorithm computing SVD failed to converge.")) ;
608 #include <gsl/gsl_linalg.h>
620 gsl_matrix *A = gsl_matrix_alloc(nr, nc) ;
623 for (i=0 ; i < nr ; i++)
626 for (j=0 ; j < nc ; j++)
627 A->data[k+j] = (*
this)[i][j] ;
631 gsl_matrix *V = gsl_matrix_alloc(nc, nc) ;
632 gsl_vector *S = gsl_vector_alloc(nc) ;
633 gsl_vector *work = gsl_vector_alloc(nc) ;
635 gsl_linalg_SV_decomp(A,V,S, work) ;
643 for (i=0 ; i < nr ; i++)
644 for (j=0 ; j < nc ; j++)
645 (*
this)[i][j] = gsl_matrix_get(A,i,j) ;
648 for (i=0 ; i < nc ; i++)
651 for (j=0 ; j < nc ; j++)
652 v[i][j] = V->
data[k+j] ;
655 for (j=0 ; j < nc ; j++)
656 w[j] = gsl_vector_get(S,j) ;
662 gsl_vector_free(work) ;
664 #else //optimisation Anthony 20/03/2008
668 gsl_vector *work = gsl_vector_alloc(nc) ;
699 gsl_linalg_SV_decomp(&A,&V,&S, work) ;
701 gsl_vector_free(work) ;
713 #endif // doxygen should skip this
Implementation of a matrix and operations on matrices.
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true)
double * data
Address of the first element of the data array.
unsigned int getCols() const
Return the number of columns of the 2D array.
static Type maximum(const Type &a, const Type &b)
unsigned int rowNum
Number of rows in the array.
static double sqr(double x)
vpMatrix transpose() const
unsigned int getRows() const
Return the number of rows of the 2D array.
unsigned int colNum
Number of columns in the array.
Implementation of column vector and the associated operations.
error that can be emited by the vpMatrix class and its derivates
double ** rowPtrs
Address of the first element of each rows.
void resize(const unsigned int i, const bool flagNullify=true)