SVD分解C实现
2010-05-24 10:56
387 查看
int svd(int m,int n,int withu,int withv,double eps,double tol, double *a, double *q, double *u, double *v, double *vt) { int i,j,k,l,l1,iter,retval; double c,f,g,h,s,x,y,z; double *e; e = (double *)calloc(n,sizeof(double)); retval = 0; /* Copy 'a' to 'u' */ for (i=0;i<m;i++) { for (j=0;j<n;j++) u[i*n + j] = a[i*n + j]; } /* Householder's reduction to bidiagonal form. */ g = x = 0.0; for (i=0;i<n;i++) { e[i] = g; s = 0.0; l = i+1; for (j=i;j<m;j++) s += (u[j*n+i]*u[j*n+i]); if (s < tol) g = 0.0; else { f = u[i*n+i]; g = (f < 0) ? sqrt(s) : -sqrt(s); h = f * g - s; u[i*n+i] = f - g; for (j=l;j<n;j++) { s = 0.0; for (k=i;k<m;k++) s += (u[k*n+i] * u[k*n+j]); f = s / h; for (k=i;k<m;k++) u[k*n+j] += (f * u[k*n+i]); } /* end j */ } /* end s */ q[i] = g; s = 0.0; for (j=l;j<n;j++) s += (u[i*n+j] * u[i*n+j]); if (s < tol) g = 0.0; else { f = u[i*n+i+1]; g = (f < 0) ? sqrt(s) : -sqrt(s); h = f * g - s; u[i*n+i+1] = f - g; for (j=l;j<n;j++) e[j] = u[i*n+j]/h; for (j=l;j<m;j++) { s = 0.0; for (k=l;k<n;k++) s += (u[j*n+k] * u[i*n+k]); for (k=l;k<n;k++) u[j*n+k] += (s * e[k]); } /* end j */ } /* end s */ y = fabs(q[i]) + fabs(e[i]); if (y > x) x = y; } /* end i */ /* accumulation of right-hand transformations */ if (withv) { for (i=n-1;i>=0;i--) { if (g != 0.0) { h = u[i*n+i+1] * g; for (j=l;j<n;j++) v[j*n+i] = u[i*n+j]/h; for (j=l;j<n;j++) { s = 0.0; for (k=l;k<n;k++) s += (u[i*n+k] * v[k*n+j]); for (k=l;k<n;k++) v[k*n+j] += (s * v[k*n+i]); } /* end j */ } /* end g */ for (j=l;j<n;j++) v[i*n+j] = v[j*n+i] = 0.0; v[i*n+i] = 1.0; g = e[i]; l = i; } /* end i */ } /* end withv, parens added for clarity */ /* accumulation of left-hand transformations */ if (withu) { for (i=n;i<m;i++) { for (j=n;j<m;j++) u[i*n+j] = 0.0; u[i*n+i] = 1.0; } } if (withu) { for (i=n-1;i>=0;i--) { l = i + 1; g = q[i]; for (j=l;j<m;j++) /* upper limit was 'n' */ u[i*n+j] = 0.0; if (g != 0.0) { h = u[i*n+i] * g; for (j=l;j<m;j++) { /* upper limit was 'n' */ s = 0.0; for (k=l;k<m;k++) s += (u[k*n+i] * u[k*n+j]); f = s / h; for (k=i;k<m;k++) u[k*n+j] += (f * u[k*n+i]); } /* end j */ for (j=i;j<m;j++) u[j*n+i] /= g; } /* end g */ else { for (j=i;j<m;j++) u[j*n+i] = 0.0; } u[i*n+i] += 1.0; } /* end i*/ } /* end withu, parens added for clarity */ /* diagonalization of the bidiagonal form */ eps *= x; for (k=n-1;k>=0;k--) { iter = 0; test_f_splitting: for (l=k;l>=0;l--) { if (fabs(e[l]) <= eps) goto test_f_convergence; if (fabs(q[l-1]) <= eps) goto cancellation; } /* end l */ /* cancellation of e[l] if l > 0 */ cancellation: c = 0.0; s = 1.0; l1 = l - 1; for (i=l;i<=k;i++) { f = s * e[i]; e[i] *= c; if (fabs(f) <= eps) goto test_f_convergence; g = q[i]; h = q[i] = sqrt(f*f + g*g); c = g / h; s = -f / h; if (withu) { for (j=0;j<m;j++) { y = u[j*n+l1]; z = u[j*n+i]; u[j*n+l1] = y * c + z * s; u[j*n+i] = -y * s + z * c; } /* end j */ } /* end withu, parens added for clarity */ } /* end i */ test_f_convergence: z = q[k]; if (l == k) goto convergence; /* shift from bottom 2x2 minor */ iter++; if (iter > 30) { retval = k; break; } x = q[l]; y = q[k-1]; g = e[k-1]; h = e[k]; f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y); g = sqrt(f*f + 1.0); f = ((x-z)*(x+z) + h*(y/((f<0)?(f-g):(f+g))-h))/x; /* next QR transformation */ c = s = 1.0; for (i=l+1;i<=k;i++) { g = e[i]; y = q[i]; h = s * g; g *= c; e[i-1] = z = sqrt(f*f+h*h); c = f / z; s = h / z; f = x * c + g * s; g = -x * s + g * c; h = y * s; y *= c; if (withv) { for (j=0;j<n;j++) { x = v[j*n+i-1]; z = v[j*n+i]; v[j*n+i-1] = x * c + z * s; v[j*n+i] = -x * s + z * c; } /* end j */ } /* end withv, parens added for clarity */ q[i-1] = z = sqrt(f*f + h*h); c = f/z; s = h/z; f = c * g + s * y; x = -s * g + c * y; if (withu) { for (j=0;j<m;j++) { y = u[j*n+i-1]; z = u[j*n+i]; u[j*n+i-1] = y * c + z * s; u[j*n+i] = -y * s + z * c; } /* end j */ } /* end withu, parens added for clarity */ } /* end i */ e[l] = 0.0; e[k] = f; q[k] = x; goto test_f_splitting; convergence: if (z < 0.0) { /* q[k] is made non-negative */ q[k] = - z; if (withv) { for (j=0;j<n;j++) v[j*n+k] = -v[j*n+k]; } /* end withv, parens added for clarity */ } /* end z */ } /* end k */ free(e); matrix_transpose(m, n, v, vt); return retval; }
相关文章推荐
- SVD分解的并行实现
- 机器学习笔记(二)矩阵和线性代数 例:用Python实现SVD分解进行图片压缩
- 使用矩阵分解(SVD)实现推荐系统
- 机器学习Python实现 SVD 分解
- 机器学习Python实现 SVD 分解
- SVD分解的并行实现
- 特征值分解、奇异值分解(SVD)原理与在降维中的应用
- 从几何解释SVD分解
- 推荐系统之矩阵分解及C++实现
- 机器学习中的数学 -强大的矩阵奇异值分解(SVD)及其应用
- 使用ByteArray实现数据的传输,以及协议的分解.
- 机器学习中的数学:强大的矩阵奇异值分解(SVD)及其应用
- MATLAB与VC++混合编程实现一维小波多尺度分解
- javascript-简单的计算器实现步骤分解(附图)
- 存一下。MATLAB矩阵分解:LU,QR,SVD详解
- spark中 进行高维矩阵的SVD分解(2)
- Tiger Concurrent Practice --日志分析并行分解设计与实现收藏
- VC++实现AVI文件的合成和分解
- 自适应滤波:奇异值分解SVD
- SVD分解的理解