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
00036
00037
00038 #if ! defined USING_QSC
00039
00040 #include "svdcmp.h"
00041
00042 template<typename T>int _SVDecompose(Array2D<T> &A, Array1D<T> &W, Array2D<T> &V, int maxiter)
00043 {
00044
00045 int m=A.dim1(),n=A.dim2();
00046
00047
00048 if(V.dim1()!=n || V.dim2()!=n) return(-2);
00049
00050 T anorm, c, f, g, h, s, scale, x, y, z;
00051 T tmp[n];
00052 g = scale = anorm = 0.0;
00053
00054
00055 for(int i=0; i<n; i++)
00056 {
00057 int l=i+1;
00058 tmp[i]=scale*g;
00059 g=0.0;
00060 scale=0.0;
00061 if(i<m)
00062 {
00063 for(int k=i; k<m; k++)
00064 scale+=fabs(A(k,i));
00065 if(scale)
00066 {
00067 T sum=0.0;
00068 for(int k=i; k<m; k++)
00069 {
00070 A(k,i)/=scale;
00071 sum += A(k,i) * A(k,i);
00072 }
00073 f=A(i,i);
00074 g=SignOfNeg((double)sqrt(sum),(double)f);
00075 h=f*g-sum;
00076 A(i,i)=f-g;
00077 for(int j=l; j<n; j++)
00078 {
00079 T sum=0.0;
00080 for(int k=i; k<m; k++)
00081 sum += A(k,i) * A(k,j);
00082 f=sum/h;
00083 for(int k=i; k<m; k++)
00084 A(k,j) += f * A(k,i);
00085 }
00086 for(int k=i; k<m; k++)
00087 A(k,i) *= scale;
00088 }
00089 }
00090 W[i]=scale*g;
00091 g=0.0;
00092 scale=0.0;
00093 if(i<m && i!=n)
00094 {
00095 for(int k=l; k<n; k++)
00096 scale += fabs(A(i,k));
00097 if(scale)
00098 {
00099 T sum=0.0;
00100 for(int k=l; k<n; k++)
00101 {
00102 A(i,k) /= scale;
00103 sum += A(i,k) * A(i,k);
00104 }
00105 f=A(i,l);
00106 g=SignOfNeg((double)sqrt(sum), (double)f);
00107 h=f*g-sum;
00108 A(i,l)=f-g;
00109 for(int k=l; k<n; k++)
00110 tmp[k] = A(i,k) / h;
00111 for(int j=l; j<m; j++)
00112 {
00113 T sum=0.0;
00114 for(int k=l; k<n; k++)
00115 sum += A(j,k) * A(i,k);
00116 for(int k=l; k<n; k++)
00117 A(j,k) += sum * tmp[k];
00118 }
00119 for(int k=l; k<n; k++)
00120 A(i,k) *= scale;
00121 }
00122 }
00123 anorm=max( (double)(anorm), (double) fabs(W[i])+fabs(tmp[i]) );
00124 }
00125
00126
00127
00128 for(int i=n-1,l=n; i>=0; i--)
00129 {
00130 if(i<n-1)
00131 {
00132 if(g)
00133 {
00134 for(int j=l; j<n; j++)
00135 V(j,i) = (A(i,j) / A(i,l)) / g;
00136 for(int j=l; j<n; j++)
00137 {
00138 T sum=0.0;
00139 for(int k=l; k<n; k++)
00140 sum += A(i,k) * V(k,j);
00141 for(int k=l; k<n; k++)
00142 V(k,j) += sum * V(k,i);
00143 }
00144 }
00145 for(int j=l; j<n; j++)
00146 V(i,j) = V(j,i) = 0.0;
00147 }
00148 V(i,i)=1.0;
00149 g=tmp[i];
00150 l=i;
00151 }
00152
00153 for(int i=min(m,n)-1; i>=0; i--)
00154 {
00155 int l=i+1;
00156 g=W[i];
00157 for(int j=l; j<n; j++)
00158 A(i,j) = 0.0;
00159 if(g)
00160 {
00161 g=1.0/g;
00162 for(int j=l; j<n; j++)
00163 {
00164 T sum=0.0;
00165 for(int k=l; k<m; k++)
00166 sum += A(k,i) * A(k,j);
00167 f=sum/A(i,i)*g;
00168 for(int k=i; k<m; k++)
00169 A(k,j)+=f*A(k,i);
00170 }
00171 for(int j=i; j<m; j++)
00172 A(j,i) *= g;
00173 }
00174 else for(int j=i; j<m; j++)
00175 A(j,i)=0.0;
00176 ++A(i,i);
00177 }
00178
00179 for(int k=n-1; k>=0; k--)
00180 {
00181 for(int its=1,l; its<=maxiter; its++)
00182 {
00183 int nm = -1;
00184 for(l=k; l>=0; l--)
00185 {
00186 nm=l-1;
00187
00188 if( fabs(tmp[l]) + anorm == anorm ) goto skipit;
00189 if( fabs(W[nm]) + anorm == anorm ) break;
00190 }
00191 c=0.0;
00192 s=1.0;
00193 for(int i=l; i<=k; i++)
00194 {
00195 f=s*tmp[i];
00196 tmp[i]=c*tmp[i];
00197 if( fabs (f) + anorm == anorm) break;
00198 g=W[i];
00199 h=HYPOT(f,g);
00200 W[i]=h;
00201 h=1.0/h;
00202 c=g*h;
00203 s=-f*h;
00204 for(int j=0; j<m; j++)
00205 {
00206 y=A(j,nm);
00207 z=A(j,i);
00208 A(j,nm) = y*c + z*s;
00209 A(j,i) = z*c - y*s;
00210 }
00211 }
00212 skipit:;
00213 z=W[k];
00214 if(l==k)
00215 {
00216 if(z<0.0)
00217 {
00218
00219 W[k]=-z;
00220 for(int j=0; j<n; j++)
00221 V(j,k)=-V(j,k);
00222 }
00223 break;
00224 }
00225 if(its==maxiter)
00226 return(1);
00227 x=W[l];
00228
00229 nm=k-1;
00230 y=W[nm];
00231 g=tmp[nm];
00232 h=tmp[k];
00233 f=((y-z)*(y+z) + (g-h)*(g+h)) / (2.0*h*y);
00234 g=HYPOT(f,(__typeof__(f))1.0);
00235 f=((x-z)*(x+z) + h*((y / (f - SignOfNeg(g,f))) - h)) / x;
00236 c=s=1.0;
00237
00238
00239 for(int j=l; j<=nm; j++)
00240 {
00241 int i=j+1;
00242 g=tmp[i];
00243 y=W[i];
00244 h=s*g;
00245 g=c*g;
00246 z=HYPOT(f,h);
00247 tmp[j]=z;
00248 c=f/z;
00249 s=h/z;
00250 f=x*c + g*s;
00251 g=g*c - x*s;
00252 h=y*s;
00253 y*=c;
00254 for(int ii=0; ii<n; ii++)
00255 {
00256 x=V(ii,j);
00257 z=V(ii,i);
00258 V(ii,j)=x*c + z*s;
00259 V(ii,i)=z*c - x*s;
00260 }
00261 z=HYPOT(f,h);
00262 W[j]=z;
00263 if(z)
00264 {
00265 z=1.0/z;
00266 c=f*z;
00267 s=h*z;
00268 }
00269 f=c*g + s*y;
00270 x=c*y - s*g;
00271 for(int ii=0; ii<m; ii++)
00272 {
00273 y=A(ii,j);
00274 z=A(ii,i);
00275 A(ii,j)=y*c + z*s;
00276 A(ii,i)=z*c - y*s;
00277 }
00278 }
00279 tmp[l]=0.0;
00280 tmp[k]=f;
00281 W[k]=x;
00282 }
00283 }
00284
00285 return(0);
00286
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296 template<typename T>int _SVDFwBackSubst(const Array2D<T> &U, const Array1D<T> &W,
00297 const Array2D<T> &V, Array2D<T> & inv)
00298 {
00299
00300 int n=U.dim1();
00301
00302
00303 if(V.dim1()!=n || V.dim2()!=n) return(-2);
00304
00305
00306 Array2D<T> tmp = Array2D<T>(n,n);
00307 for(int col=0; col<n; col++){
00308 for(int i=0; i<n; i++)
00309 {
00310 double h=0.0;
00311 if(W.get(i) != 0.0)
00312 {
00313
00314
00315 h = U.get(col,i);
00316 h/= W.get(i);
00317 }
00318 tmp(i,col)=h;
00319
00320
00321 }
00322 }
00323
00324
00325 V.gemm(tmp,inv,false);
00326
00327
00328 return(0);
00329 }
00330
00331 int SVDecompose(Array2D<double> &a,Array1D<double> &w,Array2D<double> &v,int maxiter)
00332 { return(_SVDecompose(a,w,v,maxiter)); }
00333
00334 int SVDecompose(Array2D<float> &a,Array1D<float> &w,Array2D<float> &v,int maxiter)
00335 { return(_SVDecompose(a,w,v,maxiter)); }
00336
00337 int SVDFwBackSubst(const Array2D<double> &u, const Array1D<double> &w,
00338 const Array2D<double> &v, Array2D<double> &inv)
00339 { return(_SVDFwBackSubst(u,w,v,inv)); }
00340
00341 int SVDFwBackSubst(const Array2D<float> &u, const Array1D<float> &w,
00342 const Array2D<float> &v, Array2D<float> &inv)
00343 { return(_SVDFwBackSubst(u,w,v,inv)); }
00344
00345 #endif