00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <base/SVD>
00036
00037 #include <base/Math>
00038
00039 using base::SVD;
00040
00041 using base::Math;
00042 using base::Matrix;
00043 using base::Vector;
00044
00045
00046
00047 const Real SVD::maxCondition = 1e100;
00048 const Real SVD::minSingValue = 1e-6;
00049
00050 inline float FMIN(float a, float b) { return a<b?a:b; }
00051 inline float FMAX(float a, float b) { return a>b?a:b; }
00052 inline int IMIN(int a, int b) { return a<b?a:b; }
00053 inline int IMAX(int a, int b) { return a>b?a:b; }
00054
00055 inline float SQR(float a) { return (a==0.0)?0.0:a*a; }
00056
00057
00058 inline void nrerror(char error_text[])
00059 { throw std::runtime_error(Exception(String(error_text))); }
00060
00061
00062 extern "C" {
00063
00064 #include <stdio.h>
00065 #include <stdlib.h>
00066 #include <math.h>
00067
00068
00069 #define NR_END 1
00070 #define FREE_ARG char*
00071
00072
00073 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
00074
00075
00076
00077 float *vector(long nl, long nh)
00078
00079 {
00080 float *v;
00081
00082 v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
00083 if (!v) nrerror("allocation failure in vector()");
00084 return v-nl+NR_END;
00085 }
00086
00087 void free_matrix(float **m, long nrl, long nrh, long ncl, long nch)
00088
00089 {
00090 free((FREE_ARG) (m[nrl]+ncl-NR_END));
00091 free((FREE_ARG) (m+nrl-NR_END));
00092 }
00093
00094
00095
00096 void free_vector(float *v, long nl, long nh)
00097
00098 {
00099 free((FREE_ARG) (v+nl-NR_END));
00100 }
00101
00102
00103
00104 float **matrix(long nrl, long nrh, long ncl, long nch)
00105
00106 {
00107 long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
00108 float **m;
00109
00110
00111 m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
00112 if (!m) nrerror("allocation failure 1 in matrix()");
00113 m += NR_END;
00114 m -= nrl;
00115
00116
00117 m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float)));
00118 if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
00119 m[nrl] += NR_END;
00120 m[nrl] -= ncl;
00121
00122 for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
00123
00124
00125 return m;
00126 }
00127
00128
00129 float pythag(float a, float b)
00130 {
00131 float absa, absb;
00132 absa=fabs(a);
00133 absb=fabs(b);
00134 if(absa>absb)
00135 return(absa*sqrt(1.0+SQR(absb/absa)));
00136 else
00137 return(absb==0.0 ? 0.0 : absb*sqrt(1.0+SQR(absa/absb)));
00138 }
00139
00140
00141
00142
00143
00144 void svdcmp(float **a, int m, int n, float w[], float **v)
00145 {
00146 float pythag(float a, float b);
00147 int flag,i,its,j,jj,k,l,nm, front, back;
00148 float anorm,c,f,g,h,s,scale,x,y,z,*rv1, *rv2, tol;
00149 float **ut, **vt;
00150
00151 vt=matrix(1,n,1,n);
00152 ut=matrix(1,m,1,n);
00153
00154 tol=(float)(1e-6);
00155
00156 rv1=vector(1,n);
00157 rv2=vector(1,n);
00158 g=scale=anorm=0.0;
00159 for (i=1;i<=n;i++) {
00160 l=i+1;
00161 rv1[i]=scale*g;
00162 g=s=scale=0.0;
00163 if (i <= m) {
00164 for (k=i;k<=m;k++)
00165 scale += fabs(a[k][i]);
00166 if (scale) {
00167 for (k=i;k<=m;k++) {
00168 a[k][i] /= scale;
00169 s += a[k][i]*a[k][i];
00170 }
00171 f=a[i][i];
00172 g = -SIGN(sqrt(s),f);
00173 h=f*g-s;
00174 a[i][i]=f-g;
00175 for (j=l;j<=n;j++) {
00176 for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
00177 f=s/h;
00178 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
00179 }
00180 for (k=i;k<=m;k++) a[k][i] *= scale;
00181 }
00182 }
00183 w[i]=scale *g;
00184 g=s=scale=0.0;
00185 if (i <= m && i != n) {
00186 for (k=l;k<=n;k++) scale += fabs(a[i][k]);
00187 if (scale) {
00188 for (k=l;k<=n;k++) {
00189 a[i][k] /= scale;
00190 s += a[i][k]*a[i][k];
00191 }
00192 f=a[i][l];
00193 g = -SIGN(sqrt(s),f);
00194 h=f*g-s;
00195 a[i][l]=f-g;
00196 for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
00197 for (j=l;j<=m;j++) {
00198 for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
00199 for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
00200 }
00201 for (k=l;k<=n;k++) a[i][k] *= scale;
00202 }
00203 }
00204 anorm=FMAX(anorm,(fabs(w[i])+fabs(rv1[i])));
00205 }
00206 for (i=n;i>=1;i--) {
00207 if (i < n) {
00208 if (g) {
00209 for (j=l;j<=n;j++)
00210 v[j][i]=(a[i][j]/a[i][l])/g;
00211 for (j=l;j<=n;j++) {
00212 for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
00213 for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
00214 }
00215 }
00216 for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
00217 }
00218 v[i][i]=1.0;
00219 g=rv1[i];
00220 l=i;
00221 }
00222 for (i=IMIN(m,n);i>=1;i--) {
00223 l=i+1;
00224 g=w[i];
00225 for (j=l;j<=n;j++) a[i][j]=0.0;
00226 if (g) {
00227 g=1.0/g;
00228 for (j=l;j<=n;j++) {
00229 for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
00230 f=(s/a[i][i])*g;
00231 for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
00232 }
00233 for (j=i;j<=m;j++) a[j][i] *= g;
00234 } else for (j=i;j<=m;j++) a[j][i]=0.0;
00235 ++a[i][i];
00236 }
00237 for (k=n;k>=1;k--) {
00238 for (its=1;its<=30;its++) {
00239 flag=1;
00240 for (l=k;l>=1;l--) {
00241 nm=l-1;
00242 if ((float)(fabs(rv1[l])+anorm) == anorm) {
00243 flag=0;
00244 break;
00245 }
00246 if ((float)(fabs(w[nm])+anorm) == anorm) break;
00247 }
00248 if (flag) {
00249 c=0.0;
00250 s=1.0;
00251 for (i=l;i<=k;i++) {
00252 f=s*rv1[i];
00253 rv1[i]=c*rv1[i];
00254 if ((float)(fabs(f)+anorm) == anorm) break;
00255 g=w[i];
00256 h=pythag(f,g);
00257 w[i]=h;
00258 h=1.0/h;
00259 c=g*h;
00260 s = -f*h;
00261 for (j=1;j<=m;j++) {
00262 y=a[j][nm];
00263 z=a[j][i];
00264 a[j][nm]=y*c+z*s;
00265 a[j][i]=z*c-y*s;
00266 }
00267 }
00268 }
00269 z=w[k];
00270 if (l == k) {
00271 if (z < 0.0) {
00272 w[k] = -z;
00273 for (j=1;j<=n;j++) v[j][k] = -v[j][k];
00274 }
00275 break;
00276 }
00277 if (its == 30) nrerror("no convergence in 30 svdcmp iterations");
00278 x=w[l];
00279 nm=k-1;
00280 y=w[nm];
00281 g=rv1[nm];
00282 h=rv1[k];
00283 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
00284 g=pythag(f,1.0);
00285 f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
00286 c=s=1.0;
00287 for (j=l;j<=nm;j++) {
00288 i=j+1;
00289 g=rv1[i];
00290 y=w[i];
00291 h=s*g;
00292 g=c*g;
00293 z=pythag(f,h);
00294 rv1[j]=z;
00295 c=f/z;
00296 s=h/z;
00297 f=x*c+g*s;
00298 g = g*c-x*s;
00299 h=y*s;
00300 y *= c;
00301 for (jj=1;jj<=n;jj++) {
00302 x=v[jj][j];
00303 z=v[jj][i];
00304 v[jj][j]=x*c+z*s;
00305 v[jj][i]=z*c-x*s;
00306 }
00307 z=pythag(f,h);
00308 w[j]=z;
00309 if (z) {
00310 z=1.0/z;
00311 c=f*z;
00312 s=h*z;
00313 }
00314 f=c*g+s*y;
00315 x=c*y-s*g;
00316 for (jj=1;jj<=m;jj++) {
00317 y=a[jj][j];
00318 z=a[jj][i];
00319 a[jj][j]=y*c+z*s;
00320 a[jj][i]=z*c-y*s;
00321 }
00322 }
00323 rv1[l]=0.0;
00324 rv1[k]=f;
00325 w[k]=x;
00326 }
00327 }
00328
00329
00330
00331 front=1;
00332 back=n;
00333 for(i=1;i<=n;i++)
00334 {
00335 if(w[i]<tol)
00336 {
00337 rv1[back]=i;
00338 back--;
00339 }
00340 else
00341 {
00342 rv1[front]=i;
00343 front++;
00344 }
00345 }
00346
00347 for(i=1;i<=n;i++)
00348 {
00349 rv2[i]=w[(int)(rv1[i])];
00350 for(j=1;j<=n;j++)
00351 vt[j][i]=v[j][(int)(rv1[i])];
00352 for(j=1;j<=m;j++)
00353 ut[j][i]=a[j][(int)(rv1[i])];
00354 }
00355
00356 for(i=1;i<=n;i++)
00357 {
00358 w[i]=rv2[i];
00359 for(j=1;j<=n;j++)
00360 v[j][i]=vt[j][i];
00361 for(j=1;j<=m;j++)
00362 a[j][i]=ut[j][i];
00363 }
00364
00365 free_vector(rv1,1,n);
00366 free_vector(rv2,1,n);
00367 free_matrix(vt,1,n,1,m);
00368 free_matrix(ut,1,m,1,n);
00369
00370 }
00371
00372
00373
00374
00375 }
00376
00377
00378
00379 SVD::SVD(const Matrix &A)
00380 : M(A.rows()), N(A.cols())
00381 {
00382 float **v, *w, **u;
00383
00384
00385 v=::matrix(1,N,1,N);
00386 u=::matrix(1,M,1,N);
00387 w=::vector(1,N);
00388
00389 for(Int r=0; r<M; r++)
00390 for(Int c=0; c<N; c++)
00391 u[r+1][c+1] = float( A(r,c) );
00392
00393
00394 svdcmp(u, int(M), int(N), w, v);
00395
00396
00397 UMat = zeroMatrix(M,M);
00398 for(Int r=0; r<M; r++)
00399 for(Int c=0; c< Math::minimum(N,M); c++)
00400 UMat(r,c) = Real( u[r+1][c+1] );
00401
00402 VMat.resize(N,N);
00403 for(Int r=0; r<N; r++)
00404 for(Int c=0; c<N; c++)
00405 VMat(r,c) = Real( v[r+1][c+1] );
00406
00407 s.resize(N);
00408 for(Int i=0; i<N; i++)
00409 s[i] = Real( w[i+1] );
00410 }
00411
00412
00413
00414 const Matrix& SVD::U() const
00415 {
00416 return UMat;
00417 }
00418
00419 const Matrix& SVD::V() const
00420 {
00421 return VMat;
00422 }
00423
00424 const Vector SVD::diag() const
00425 {
00426 Vector d( Math::minimum(M,N) );
00427 d = vectorRange(s, Range(0, d.size()));
00428 return d;
00429 }
00430
00431
00432 Matrix SVD::S() const
00433 {
00434 Matrix S( zeroMatrix(M,N) );
00435 for(Int i=0; i< Math::minimum(N,M); i++)
00436 S(i,i) = s[i];
00437 return S;
00438 }
00439
00440
00441 Real SVD::condition(Real maxCond) const
00442 {
00443 Vector d(diag());
00444 Int minInd = min_index(d);
00445 Int maxInd = max_index(d);
00446
00447 Real min = d[minInd];
00448 Real max = d[maxInd];
00449
00450 if(min / max < 1.0/maxCond)
00451 return maxCond;
00452 else
00453 return max / min;
00454
00455 }
00456
00457
00458 Matrix SVD::inv(Real minSingVal) const
00459 {
00460
00461 const Int M = UMat.size1();
00462 const Int N = VMat.size1();
00463 Matrix tmpMat( zeroMatrix(N, M) );
00464 matrixRange(tmpMat, Range(0,N), Range(0,N) ) = VMat;
00465
00466
00467 for(Int i=0; i<s.size(); i++)
00468 {
00469 Real tmp = s[i];
00470 if(fabs(tmp) < minSingVal)
00471 tmp = 0.0;
00472 else
00473 tmp = 1.0 / tmp;
00474
00475 matrixColumn(tmpMat,i) *= tmp;
00476 }
00477
00478
00479 Matrix invA(N, M);
00480 invA = tmpMat * transpose(UMat);
00481
00482 return invA;
00483 }
00484
00485