📄 sis2.c
字号:
{ for (k=offset;k<=l;k++) { d[k]=d[k]/scale; h+=d[k]*d[k]; } f=d[l]; g=-fsign(sqrt(h), f); e[i]=scale * g; h-=f*g; d[l]=f-g; /* form A*u */ for (j=offset; j<=l; j++) e[j]=ZERO; for (j=offset;j<=l;j++) { f=d[j]; z[j][i]=f; g= e[j] + z[j][j] * f; jp1= j + 1; if (l >= jp1) { for (k=jp1; k<=l; k++) { g+= z[k][j] * d[k]; e[k] += z[k][j] * f; } }; e[j]=g; } /* form P */ f= ZERO; for (j=offset; j<=l; j++) { e[j]=e[j]/h; f+= e[j] * d[j]; } hh= f/ (h+h); /* form Q */ for (j=offset; j<=l; j++) e[j] -= hh * d[j]; /* form reduced A */ for (j=offset; j<=l; j++) { f= d[j]; g = e[j]; for (k=j; k<=l; k++) z[k][j]= z[k][j] - f * e[k] - g * d[k]; d[j]=z[l][j]; z[i][j]=ZERO; } } /* end scale <> zero */ d[i]=h; } /* end for ii */ /*accumulation of transformation matrices */ for (i=offset + 1;i<n;i++) { l=i-1; z[n-1][l] = z[l][l]; z[l][l] = ONE; h=d[i]; if (h != ZERO) { for (k=offset; k<=l; k++) d[k]= z[k][i]/h; for (j=offset; j<=l; j++) { g= ZERO; for (k=offset;k<=l; k++) g+= z[k][i]*z[k][j]; for (k=offset;k<=l;k++) z[k][j] -= g * d[k]; } } for (k=offset;k<=l;k++) z[k][i]=ZERO; } for (i=offset;i<n;i++) { d[i]=z[n-1][i]; z[n-1][i]=ZERO; } z[n-1][n-1]=ONE; e[0]=ZERO;/*preparation for tql2.c.. reorder e[]*/for (i=1+offset;i<n;i++) e[i-1]=e[i]; /*preparation for tql2.c.. z has to be transposed for tql2 to give correct eigenvectors */for (ii=offset; ii<n; ii++) for (jj=ii; jj<n; jj++) { tmp=z[ii][jj]; z[ii][jj]=z[jj][ii]; z[jj][ii]=tmp; } return;} #include <math.h>double fsign(double, double);double pythag(double, double);/*********************************************************************** * * * tql2() * * * ***********************************************************************//*********************************************************************** Description ----------- tql2() is a translation of a Fortran version of the Algol procedure TQL2, Num. Math. 11, 293-306(1968) by Dowdler, Martin, Reinsch and Wilkinson. Handbook for Auto. Comp., vol.II-Linear Algebra, 227-240(1971). This function finds the eigenvalues and eigenvectors of a symmetric tridiagonal matrix by the QL method. Arguments --------- (input) offset the index of the leading element of the input(full) matrix to be factored. n order of the symmetric tridiagonal matrix d contains the diagonal elements of the input matrix e contains the subdiagonal elements of the input matrix in its first n-1 positions. z contains the identity matrix (output) d contains the eigenvalues in ascending order. if an error exit is made, the eigenvalues are correct but unordered for for indices 0,1,...,ierr. e has been destroyed. z contains orthonormal eigenvectors of the symmetric tridiagonal (or full) matrix. if an error exit is made, z contains the eigenvectors associated with the stored eigenvalues. ierr set to zero for normal return, j if the j-th eigenvalue has not been determined after 30 iterations. (return value) Functions used -------------- UTILITY fsign MISC pythag ***********************************************************************/long tql2(long offset, long n, double *d, double *e, double **z){ long j, last, l, l1, l2, m, i, k, iteration; double tst1, tst2, g, r, s, s2, c, c2, c3, p, f, h, el1, dl1; if (n == 1) return(0); f = ZERO; last = n - 1; tst1 = ZERO; e[last] = ZERO; for (l = offset; l < n; l++) { iteration = 0; h = fabs(d[l]) + fabs(e[l]); if (tst1 < h) tst1 = h; /* look for small sub-diagonal element */ for (m = l; m < n; m++) { tst2 = tst1 + fabs(e[m]); if (tst2 == tst1) break; } if (m != l) { while (iteration < 30) { iteration += 1; /* form shift */ l1 = l + 1; l2 = l1 + 1; g = d[l]; p = (d[l1] - g) / (2.0 * e[l]); r = pythag(p, ONE); d[l] = e[l] / (p + fsign(r, p)); d[l1] = e[l] * (p + fsign(r, p)); dl1 = d[l1]; h = g - d[l]; if (l2 < n) for (i = l2; i < n; i++) d[i] -= h; f += h; /* QL transformation */ p = d[m]; c = ONE; c2 = c; el1 = e[l1]; s = ZERO; i = m - 1; while (i >= l) { c3 = c2; c2 = c; s2 = s; g = c * e[i]; h = c * p; r = pythag(p, e[i]); e[i + 1] = s * r; s = e[i] / r; c = p / r; p = c * d[i] - s * g; d[i + 1]= h + s * (c * g + s * d[i]); /* form vector */ for (k = offset; k < n; k ++) { h = z[i + 1][k]; z[i + 1][k] = s * z[i][k] + c * h; z[i][k] = c * z[i][k] - s * h; } i--; } p = -s * s2 * c3 *el1 * e[l] / dl1; e[l] = s * p; d[l] = c * p; tst2 = tst1 + fabs(e[l]); if (tst2 <= tst1) break; if (iteration == 30) return(l); } } d[l] += f; } /* order the eigenvalues */ for (l = 1+offset; l < n; l++) { i = l - 1; k = i; p = d[i]; for (j = l; j < n; j++) { if (d[j] < p) { k = j; p = d[j]; } } /* ...and corresponding eigenvectors */ if (k != i) { d[k] = d[i]; d[i] = p; for (j = offset; j < n; j ++) { p = z[i][j]; z[i][j] = z[k][j]; z[k][j] = p; } } } return(0);} /*...... end main ............................*/double fsign(double a,double b)/************************************************************** * returns |a| if b is positive; else fsign returns -|a| * **************************************************************/ { if ((a>=0.0 && b>=0.0) || (a<0.0 && b<0.0))return(a); if ((a<0.0 && b>=0.0) || (a>=0.0 && b<0.0))return(-a);}double dmax(double a, double b)/************************************************************** * returns the larger of two double precision numbers * **************************************************************/ { if (a > b) return(a); else return(b);}double dmin(double a, double b)/************************************************************** * returns the smaller of two double precision numbers * **************************************************************/ { if (a < b) return(a); else return(b);}long imin(long a, long b)/************************************************************** * returns the smaller of two integers * **************************************************************/ { if (a < b) return(a); else return(b);}long imax(long a,long b)/************************************************************** * returns the larger of two integers * **************************************************************/ { if (a > b) return(a); else return(b);}#include <math.h>double dmax(double, double);double dmin(double, double);/************************************************************** * * * Function finds sqrt(a^2 + b^2) without overflow or * * destructive underflow. * * * **************************************************************/ /************************************************************** Funtions used ------------- UTILITY dmax, dmin **************************************************************/ double pythag(double a, double b){ double p, r, s, t, u, temp; p = dmax(fabs(a), fabs(b)); if (p != 0.0) { temp = dmin(fabs(a), fabs(b)) / p; r = temp * temp; t = 4.0 + r; while (t != 4.0) { s = r / t; u = 1.0 + 2.0 * s; p *= u; temp = s / u; r *= temp * temp; t = 4.0 + r; } } return(p);}/************************************************************** * Function forms the dot product of two vectors. * * Based on Fortran-77 routine from Linpack by J. Dongarra * **************************************************************/ extern long flag;double ddot( long n,double *dx,long incx,double *dy,long incy){ long i; double dot_product; if (n <= 0 || incx == 0 || incy == 0) return(0.0); dot_product = 0.0; if (incx == 1 && incy == 1) for (i=0; i < n; i++) dot_product += (*dx++) * (*dy++); else { if (incx < 0) dx += (-n+1) * incx; if (incy < 0) dy += (-n+1) * incy; for (i=0; i < n; i++) { dot_product += (*dx) * (*dy); dx += incx; dy += incy; } } return(dot_product);}/************************************************************** * Constant times a vector plus a vector * * Based on Fortran-77 routine from Linpack by J. Dongarra * **************************************************************/ void daxpy (long n,double da,double *dx,long incx,double *dy,long incy){ long i; if (n <= 0 || incx == 0 || incy == 0 || da == 0.0) return; if (incx == 1 && incy == 1) for (i=0; i < n; i++) { *dy += da * (*dx++); dy++; } else { if (incx < 0) dx += (-n+1) * incx; if (incy < 0) dy += (-n+1) * incy; for (i=0; i < n; i++) { *dy += da * (*dx); dx += incx; dy += incy; } } return;}/************************************************************** * Function scales a vector by a constant. * * Based on Fortran-77 routine from Linpack by J. Dongarra * **************************************************************/ void dscal(long n,double da,double *dx,long incx){ long i; if (n <= 0 || incx == 0) return; if (incx < 0) dx += (-n+1) * incx; for (i=0; i < n; i++) { *dx *= da; dx += incx; } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -