⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svd.c

📁 su 的源代码库
💻 C
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved.                       *//***************************************************************************SVD - Singular Value Decomposition related routines****************************************************************************compute_svd - perform singular value decomposition svd_backsubstitute - back substitute results of compute_svdsvd_sort - sort singular values in descending order****************************************************************************Credits: Ian Kay, Canadian Geological Survey, Ottawa, Ontario 1999.This is a translation in C from an code written in Fortran that appearedin NETLIB, EISPACK, and SLATEC collections that was itself a translationfrom an original Algol code that appeared in:Golub, G. and C. Reinsch (1971) Handbook for automatic computation II, linear algebra, p 134-151. SpringerVerlag, New York.See also discussions of a similar code in Numerical Recipes in C.svd_sort: Nils Maercklin, GeoForschungsZentrum (GFZ) Potsdam, Germany, 2001.***************************************************************************/#include <cwp.h>#define SVD_SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))#define SVD_MAX_ITERATION 40/* Function prototype of routine used internally */float pythag(float a, float b);float pythag(float a, float b)/* pythagorean theorem */{    float absa,absb;    absa=fabs(a);    absb=fabs(b);    if (absa > absb)     	return absa*sqrt(1.0+(absb/absa)*(absb/absa));    else return     	(absb == 0.0 ? 0.0 : absb*sqrt(1.0+(absa/absb)*(absa/absb)));}void svd_backsubstitute(float **u, float w[], float **v, int m, int n, float b[], float x[])/**************************************************************************svd_backsubstitute - back substitute results of compute_svd***************************************************************************Credits: similar to code in Netlib's EISPACK and CLAPACKsee also discussions in NR in C**************************************************************************/{	int jj,j,i;	float s,*tmp;	tmp=alloc1float(n);	for (j=0;j<n;j++) {		s=0.0;		if (w[j]) {			for (i=0;i<m;i++) 				s += u[i][j]*b[i];			s /= w[j];		}		tmp[j]=s;	}	for (j=0;j<n;j++) {		s=0.0;		for (jj=0;jj<n;jj++) 			s += v[j][jj]*tmp[jj];		x[j]=s;	}	free1float (tmp);}void compute_svd(float **a, int m, int n, float w[], float **v)/*************************************************************************compute_svd - perform singular value decomposition **************************************************************************Credits: similar to code in Netlib's EISPACK and CLAPACK see also discussions in NR in C*************************************************************************/{	float pythag(float a, float b);	int flag,i,its,j,jj,k,l=0,nm=0;	float anorm,c,f,g,h,s,scale,x,y,z,*rv1;	int maxiter=SVD_MAX_ITERATION;	rv1=alloc1float(n);	g=scale=anorm=0.0;	for (i=0;i<n;i++) {		l=i+1;		rv1[i]=scale*g;		g=s=scale=0.0;		if (i < m) {			for (k=i;k<m;k++) 				scale += fabs(a[k][i]);			if (scale) {				for (k=i;k<m;k++) {					a[k][i] /= scale;					s += a[k][i]*a[k][i];				}				f=a[i][i];				g = -SVD_SIGN(sqrt(s),f);				h=f*g-s;				a[i][i]=f-g;				for (j=l;j<n;j++) {					for (s=0.0,k=i;k<m;k++) 						s += a[k][i]*a[k][j];					f=s/h;					for (k=i;k<m;k++) 						a[k][j] += f*a[k][i];				}				for (k=i;k<m;k++) 					a[k][i] *= scale;			}		}		w[i]=scale *g;		g=s=scale=0.0;		if (i < m && i != n-1) {			for (k=l;k<n;k++) 				scale += fabs(a[i][k]);			if (scale) {				for (k=l;k<n;k++) {					a[i][k] /= scale;					s += a[i][k]*a[i][k];				}				f=a[i][l];				g = -SVD_SIGN(sqrt(s),f);				h=f*g-s;				a[i][l]=f-g;				for (k=l;k<n;k++) 					rv1[k]=a[i][k]/h;				for (j=l;j<m;j++) {					for (s=0.0,k=l;k<n;k++) 						s += a[j][k]*a[i][k];					for (k=l;k<n;k++) 						a[j][k] += s*rv1[k];				}				for (k=l;k<n;k++) 					a[i][k] *= scale;			}		}		anorm=(anorm>(fabs(w[i])+fabs(rv1[i])) ? anorm : (fabs(w[i])+fabs(rv1[i])));	}	for (i=n-1;i>=0;i--) {		if (i < n-1) {			if (g) {				for (j=l;j<n;j++)					v[j][i]=(a[i][j]/a[i][l])/g;				for (j=l;j<n;j++) {					for (s=0.0,k=l;k<n;k++) 						s += a[i][k]*v[k][j];					for (k=l;k<n;k++) 						v[k][j] += s*v[k][i];				}			}			for (j=l;j<n;j++) 				v[i][j]=v[j][i]=0.0;		}		v[i][i]=1.0;		g=rv1[i];		l=i;	}	for (i=(m<n?m:n)-1;i>=0;i--) {		l=i+1;		g=w[i];		for (j=l;j<n;j++) 			a[i][j]=0.0;		if (g) {			g=1.0/g;			for (j=l;j<n;j++) {				for (s=0.0,k=l;k<m;k++) 					s += a[k][i]*a[k][j];				f=(s/a[i][i])*g;				for (k=i;k<m;k++) 					a[k][j] += f*a[k][i];			}			for (j=i;j<m;j++) 				a[j][i] *= g;		} else 			for (j=i;j<m;j++) 				a[j][i]=0.0;		++a[i][i];	}	for (k=n-1;k>=0;k--) {		for (its=1;its<=maxiter;its++) {			flag=1;			for (l=k;l>=0;l--) {				nm=l-1;				if ((float)(fabs(rv1[l])+anorm) == anorm) {					flag=0;					break;				}				if ((float)(fabs(w[nm])+anorm) == anorm) break;			}			if (flag) {				c=0.0;				s=1.0;				for (i=l;i<=k;i++) {					f=s*rv1[i];					rv1[i]=c*rv1[i];					if ((float)(fabs(f)+anorm) == anorm) break;					g=w[i];					h=pythag(f,g);					w[i]=h;					h=1.0/h;					c=g*h;					s = -f*h;					for (j=0;j<m;j++) {						y=a[j][nm];						z=a[j][i];						a[j][nm]=y*c+z*s;						a[j][i]=z*c-y*s;					}				}			}			z=w[k];			if (l == k) {				if (z < 0.0) {					w[k] = -z;					for (j=0;j<n;j++) v[j][k] = -v[j][k];				}				break;			}			if (its == 30) { fprintf(stderr,"no convergence in 30 compute_svd iterations\n");exit (-2);}			x=w[l];			nm=k-1;			y=w[nm];			g=rv1[nm];			h=rv1[k];			f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);			g=pythag(f,1.0);			f=((x-z)*(x+z)+h*((y/(f+SVD_SIGN(g,f)))-h))/x;			c=s=1.0;			for (j=l;j<=nm;j++) {				i=j+1;				g=rv1[i];				y=w[i];				h=s*g;				g=c*g;				z=pythag(f,h);				rv1[j]=z;				c=f/z;				s=h/z;				f=x*c+g*s;				g = g*c-x*s;				h=y*s;				y *= c;				for (jj=0;jj<n;jj++) {					x=v[jj][j];					z=v[jj][i];					v[jj][j]=x*c+z*s;					v[jj][i]=z*c-x*s;				}				z=pythag(f,h);				w[j]=z;				if (z) {					z=1.0/z;					c=f*z;					s=h*z;				}				f=c*g+s*y;				x=c*y-s*g;				for (jj=0;jj<m;jj++) {					y=a[jj][j];					z=a[jj][i];					a[jj][j]=y*c+z*s;					a[jj][i]=z*c-y*s;				}			}			rv1[l]=0.0;			rv1[k]=f;			w[k]=x;		}	}	free1float(rv1);}void svd_sort(float **u, float *w, float **v, int n, int m)/**********************************************************************svd_sort - sort singular values and corresponding eigenimages           in descending order**********************************************************************Input:u[][]	**********************************************************************Notes:We assume input of the singular value decomposition of a matrix a[][]of the form:                    ta[][] = u[][] w[] v[][]**********************************************************************Credits: Nils Maercklin, GeoForschungsZentrum (GFZ) Potsdam, Germany, 2001.**********************************************************************/{        int k,j,i;        float p;        for (i=0;i<n-1;i++) {                p=w[k=i];                for (j=i+1;j<=n;j++)                        if (w[j] >= p) p=w[k=j];                if (k != i) {                        w[k]=w[i];                        w[i]=p;                        for (j=0;j<n;j++) {                                p=v[j][i];                                v[j][i]=v[j][k];                                v[j][k]=p;                        }                        for (j=0;j<m;j++) {                                p=u[j][i];                                u[j][i]=u[j][k];                                u[j][k]=p;                        }                }        }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -