42 #include <visp/vpConfig.h>
44 #ifndef DOXYGEN_SHOULD_SKIP_THIS
46 #include <visp/vpMatrix.h>
47 #include <visp/vpMath.h>
48 #include <visp/vpColVector.h>
49 #include <visp/vpException.h>
50 #include <visp/vpMatrixException.h>
51 #include <visp/vpDebug.h>
65 static double pythag(
double a,
double b)
70 if (absa > absb)
return absa*sqrt(1.0+
vpMath::sqr(absb/absa));
72 else return (std::fabs(absb) <= std::numeric_limits<double>::epsilon() ? 0.0 : absb*sqrt(1.0+
vpMath::sqr(absa/absb)));
78 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
100 #define MAX_ITER_SVD 50
106 double epsilon = 10*std::numeric_limits<double>::epsilon();
108 unsigned int flag,i,its,j,jj,k,l=0,nm=0;
109 double c,f,h,s,x,y,z;
110 double anorm=0.0,g=0.0,scale=0.0;
114 double **a =
new double*[m+1];
115 double **v =
new double*[n+1];
119 double *w =
new double[n+1];
120 for (i=0;i<n;i++) w[i+1] = 0.0;
134 vpERROR_TRACE(
"\n\t\tSVDcmp: You must augment A with extra zero rows") ;
136 "\n\t\tSVDcmp: You must augment A with "
137 "extra zero rows")) ;
139 double* rv1=
new double[n+1];
146 for (k=i;k<=m;k++) scale += fabs(a[k][i]);
148 if ((std::fabs(scale) > epsilon)) {
151 s += a[k][i]*a[k][i];
154 g = -SIGN(sqrt(s),f);
159 for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
161 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
164 for (k=i;k<=m;k++) a[k][i] *= scale;
169 if (i <= m && i != n) {
170 for (k=l;k<=n;k++) scale += fabs(a[i][k]);
172 if ((std::fabs(scale) > epsilon) ) {
175 s += a[i][k]*a[i][k];
178 g = -SIGN(sqrt(s),f);
181 for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
184 for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
185 for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
188 for (k=l;k<=n;k++) a[i][k] *= scale;
196 if ((std::fabs(g) > epsilon) ) {
198 v[j][i]=(a[i][j]/a[i][l])/g;
200 for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
201 for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
204 for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
214 for (j=l;j<=n;j++) a[i][j]=0.0;
216 if ((std::fabs(g) > epsilon) ) {
220 for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
222 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
225 for (j=i;j<=m;j++) a[j][i] *= g;
227 for (j=i;j<=m;j++) a[j][i]=0.0;
232 for (its=1;its<=MAX_ITER_SVD;its++) {
237 if ((std::fabs(rv1[l]) <= epsilon) ) {
242 if ((std::fabs(w[nm]) <= epsilon) )
break;
250 if ((std::fabs(f) > epsilon) ) {
270 for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
274 if (its == MAX_ITER_SVD)
276 for (i=0;i<n;i++) W[i] = w[i+1];
279 std::cout << *
this <<std::endl ;
288 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
290 f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
292 for (j=l;j<=nm;j++) {
300 if ((std::fabs(z) > epsilon) ) {
308 for (jj=1;jj<=n;jj++) {
317 if ((std::fabs(z) > epsilon) ) {
324 for (jj=1;jj<=m;jj++) {
336 for (i=0;i<n;i++) W[i] = w[i+1];
370 unsigned int m = this->
rowNum;
371 unsigned int n = this->
colNum;
381 if (std::fabs(w[j]) > std::numeric_limits<double>::epsilon())
383 for (i=0;i<m;i++) s += u[i][j]*b[i];
390 for (jj=0;jj<n;jj++) s += v[j][jj]*tmp[jj];
417 #define TOLERANCE 1.0e-7
420 void svd_internal_use(
double *U,
double *S,
double *V,
421 unsigned int nRow,
unsigned int nCol)
423 unsigned int i, j, k, EstColRank, RotCount, SweepCount, slimit;
424 double eps, e2, tol, vt, p, x0, y0, q, r, c0, s0, d1, d2;
431 e2 = 10.0 * nRow * eps * eps;
435 for (i = 0; i < nCol; i++)
436 for (j = 0; j < nCol; j++) {
437 V[nCol * i + j] = 0.0;
438 V[nCol * i + i] = 1.0;
440 RotCount = EstColRank * (EstColRank - 1) / 2;
441 while (RotCount != 0 && SweepCount <= slimit) {
442 RotCount = EstColRank * (EstColRank - 1) / 2;
444 for (j = 0; j < EstColRank - 1; j++) {
445 for (k = j + 1; k < EstColRank; k++) {
447 for (i = 0; i < nRow; i++) {
448 x0 = U[nCol * i + j];
449 y0 = U[nCol * i + k];
457 if (q <= e2 * S[0] || fabs(p) <= tol * q)
462 vt = sqrt(4 * p * p + r * r);
463 c0 = sqrt(fabs(.5 * (1 + r / vt)));
465 for (i = 0; i < nRow; i++) {
466 d1 = U[nCol * i + j];
467 d2 = U[nCol * i + k];
468 U[nCol * i + j] = d1 * c0 + d2 * s0;
469 U[nCol * i + k] = -d1 * s0 + d2 * c0;
472 for (i = 0; i < nCol; i++) {
473 d1 = V[nCol * i + j];
474 d2 = V[nCol * i + k];
475 V[nCol * i + j] = d1 * c0 + d2 * s0;
476 V[nCol * i + k] = -d1 * s0 + d2 * c0;
483 vt = sqrt(4 * p * p + q * q);
484 s0 = sqrt(fabs(.5 * (1 - q / vt)));
488 for (i = 0; i < nRow; i++) {
489 d1 = U[nCol * i + j];
490 d2 = U[nCol * i + k];
491 U[nCol * i + j] = d1 * c0 + d2 * s0;
492 U[nCol * i + k] = -d1 * s0 + d2 * c0;
495 for (i = 0; i < nCol; i++) {
496 d1 = V[nCol * i + j];
497 d2 = V[nCol * i + k];
498 V[nCol * i + j] = d1 * c0 + d2 * s0;
499 V[nCol * i + k] = -d1 * s0 + d2 * c0;
504 while (EstColRank >= 3 && S[(EstColRank - 1)] <= S[0] * tol + tol * tol)
507 for(i = 0; i < nCol; i++)
509 for(i = 0; i < nCol; i++)
510 for(j = 0; j < nRow; j++)
511 U[nCol * j + i] = U[nCol * j + i] / S[i];
547 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
548 # include <opencv2/core/core.hpp>
550 int rows = (int)this->
getRows();
551 int cols = (int)this->
getCols();
552 cv::Mat m(rows, cols, CV_64F, this->
data);
553 cv::SVD opencvSVD(m);
554 cv::Mat opencvV = opencvSVD.vt;
555 cv::Mat opencvW = opencvSVD.w;
556 v.
resize((
unsigned int)opencvV.rows, (
unsigned int)opencvV.cols);
557 w.
resize((
unsigned int)(opencvW.rows*opencvW.cols));
559 memcpy(v.
data, opencvV.data, (
size_t)(8*opencvV.rows*opencvV.cols));
561 memcpy(w.
data, opencvW.data, (
size_t)(8*opencvW.rows*opencvW.cols));
562 this->
resize((
unsigned int)opencvSVD.u.rows, (
unsigned int)opencvSVD.u.cols);
563 memcpy(this->
data,opencvSVD.u.data, (
size_t)(8*opencvSVD.u.rows*opencvSVD.u.cols));
568 #ifdef VISP_HAVE_LAPACK
569 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);
574 int m =
static_cast<int>(this->
getCols()), n = static_cast<int>(this->
getRows()), lda = m, ldu = m, ldvt = std::min(m,n);
580 int* iwork =
new int[8*
static_cast<unsigned int>(std::min(n,m))];
583 double* a =
new double[
static_cast<unsigned int>(lda*n)];
586 double* vt = this->
data;
591 dgesdd_( (
char*)
"S", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &wkopt, &lwork, iwork, &info );
593 work =
new double[
static_cast<unsigned int>(lwork)];
595 dgesdd_( (
char*)
"S", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info );
598 vpTRACE(
"The algorithm computing SVD failed to converge.");
609 #include <gsl/gsl_linalg.h>
621 gsl_matrix *A = gsl_matrix_alloc(nr, nc) ;
624 for (i=0 ; i < nr ; i++)
627 for (j=0 ; j < nc ; j++)
628 A->data[k+j] = (*
this)[i][j] ;
632 gsl_matrix *V = gsl_matrix_alloc(nc, nc) ;
633 gsl_vector *S = gsl_vector_alloc(nc) ;
634 gsl_vector *work = gsl_vector_alloc(nc) ;
636 gsl_linalg_SV_decomp(A,V,S, work) ;
644 for (i=0 ; i < nr ; i++)
645 for (j=0 ; j < nc ; j++)
646 (*
this)[i][j] = gsl_matrix_get(A,i,j) ;
649 for (i=0 ; i < nc ; i++)
652 for (j=0 ; j < nc ; j++)
653 v[i][j] = V->
data[k+j] ;
656 for (j=0 ; j < nc ; j++)
657 w[j] = gsl_vector_get(S,j) ;
663 gsl_vector_free(work) ;
665 #else //optimisation Anthony 20/03/2008
669 gsl_vector *work = gsl_vector_alloc(nc) ;
700 gsl_linalg_SV_decomp(&A,&V,&S, work) ;
702 gsl_vector_free(work) ;
714 #endif // doxygen should skip this
Definition of the vpMatrix class.
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
static Type maximum(const Type &a, const Type &b)
double * data
address of the first element of the data array
double ** rowPtrs
address of the first element of each rows
static double sqr(double x)
vpMatrix transpose() const
unsigned int rowNum
number of rows
Class that provides a data structure for the column vectors as well as a set of operations on these v...
unsigned int getCols() const
Return the number of columns of the matrix.
error that can be emited by the vpMatrix class and its derivates
unsigned int colNum
number of columns
unsigned int getRows() const
Return the number of rows of the matrix.
void resize(const unsigned int i, const bool flagNullify=true)