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

📄 eigen.c

📁 时间序列工具
💻 C
字号:
#include <math.h>#include <stdlib.h>#include <stdio.h>#include "tisean_cec.h"typedef double doublereal;typedef int integer;#define abs(x) (((x)>=0.0)?(x):-(x))#define min(x,y) (((x)<=(y))?(x):(y))#define max(x,y) (((x)>=(y))?(x):(y))static doublereal c_b10 = 1.;extern void check_alloc(void*);double d_sign(double *a,double *b){  double x;  x = (*a >= 0 ? *a : - *a);  return ( *b >= 0 ? x : -x);}doublereal pythag(doublereal *a, doublereal *b){    doublereal ret_val, d__1, d__2, d__3;    static doublereal p, r__, s, t, u;    d__1 = abs(*a), d__2 = abs(*b);    p = max(d__1,d__2);    if (p == 0.) {	goto L20;    }    d__2 = abs(*a), d__3 = abs(*b);    d__1 = min(d__2,d__3) / p;    r__ = d__1 * d__1;L10:    t = r__ + 4.;    if (t == 4.) {	goto L20;    }    s = r__ / t;    u = s * 2. + 1.;    p = u * p;    d__1 = s / u;    r__ = d__1 * d__1 * r__;    goto L10;L20:    ret_val = p;    return ret_val;}int tred2(integer *nm, integer *n, doublereal *a, 	doublereal *d__, doublereal *e, doublereal *z__){    integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2, i__3;    doublereal d__1;    double sqrt(doublereal), d_sign(doublereal *, doublereal *);    static doublereal f, g, h__;    static integer i__, j, k, l;    static doublereal hh;    static integer ii, jp1;    static doublereal scale;/*     this subroutine is a translation of the algol procedure tred2, *//*     num. math. 11, 181-195(1968) by martin, reinsch, and wilkinson. *//*     handbook for auto. comp., vol.ii-linear algebra, 212-226(1971). *//*     this subroutine reduces a real symmetric matrix to a *//*     symmetric tridiagonal matrix using and accumulating *//*     orthogonal similarity transformations. *//*     on input *//*        nm must be set to the row dimension of two-dimensional *//*          array parameters as declared in the calling program *//*          dimension statement. *//*        n is the order of the matrix. *//*        a contains the real symmetric input matrix.  only the *//*          lower triangle of the matrix need be supplied. *//*     on output *//*        d contains the diagonal elements of the tridiagonal matrix. *//*        e contains the subdiagonal elements of the tridiagonal *//*          matrix in its last n-1 positions.  e(1) is set to zero. *//*        z contains the orthogonal transformation matrix *//*          produced in the reduction. *//*        a and z may coincide.  if distinct, a is unaltered. *//*     questions and comments should be directed to burton s. garbow, *//*     mathematics and computer science div, argonne national laboratory *//*     this version dated august 1983. *//*     ------------------------------------------------------------------ */    z_dim1 = *nm;    z_offset = 1 + z_dim1 * 1;    z__ -= z_offset;    --e;    --d__;    a_dim1 = *nm;    a_offset = 1 + a_dim1 * 1;    a -= a_offset;    i__1 = *n;    for (i__ = 1; i__ <= i__1; ++i__) {	i__2 = *n;	for (j = i__; j <= i__2; ++j) {	    z__[j + i__ * z_dim1] = a[j + i__ * a_dim1];	}	d__[i__] = a[*n + i__ * a_dim1];    }    if (*n == 1) {	goto L510;    }    i__1 = *n;    for (ii = 2; ii <= i__1; ++ii) {	i__ = *n + 2 - ii;	l = i__ - 1;	h__ = 0.;	scale = 0.;	if (l < 2) {	    goto L130;	}	i__2 = l;	for (k = 1; k <= i__2; ++k) {	    scale += (d__1 = d__[k], abs(d__1));	}	if (scale != 0.) {	    goto L140;	}L130:	e[i__] = d__[l];	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    d__[j] = z__[l + j * z_dim1];	    z__[i__ + j * z_dim1] = 0.;	    z__[j + i__ * z_dim1] = 0.;	}	goto L290;L140:	i__2 = l;	for (k = 1; k <= i__2; ++k) {	    d__[k] /= scale;	    h__ += d__[k] * d__[k];	}	f = d__[l];	d__1 = sqrt(h__);	g = -d_sign(&d__1, &f);	e[i__] = scale * g;	h__ -= f * g;	d__[l] = f - g;	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    e[j] = 0.;	}	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    f = d__[j];	    z__[j + i__ * z_dim1] = f;	    g = e[j] + z__[j + j * z_dim1] * f;	    jp1 = j + 1;	    if (l < jp1) {		goto L220;	    }	    i__3 = l;	    for (k = jp1; k <= i__3; ++k) {		g += z__[k + j * z_dim1] * d__[k];		e[k] += z__[k + j * z_dim1] * f;	    }L220:	    e[j] = g;	}	f = 0.;	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    e[j] /= h__;	    f += e[j] * d__[j];	}	hh = f / (h__ + h__);	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    e[j] -= hh * d__[j];	}	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    f = d__[j];	    g = e[j];	    i__3 = l;	    for (k = j; k <= i__3; ++k) {		z__[k + j * z_dim1] = z__[k + j * z_dim1] - f * e[k] - g * 			d__[k];	    }	    d__[j] = z__[l + j * z_dim1];	    z__[i__ + j * z_dim1] = 0.;	}L290:	d__[i__] = h__;    }    i__1 = *n;    for (i__ = 2; i__ <= i__1; ++i__) {	l = i__ - 1;	z__[*n + l * z_dim1] = z__[l + l * z_dim1];	z__[l + l * z_dim1] = 1.;	h__ = d__[i__];	if (h__ == 0.) {	    goto L380;	}	i__2 = l;	for (k = 1; k <= i__2; ++k) {	    d__[k] = z__[k + i__ * z_dim1] / h__;	}	i__2 = l;	for (j = 1; j <= i__2; ++j) {	    g = 0.;	    i__3 = l;	    for (k = 1; k <= i__3; ++k) {		g += z__[k + i__ * z_dim1] * z__[k + j * z_dim1];	    }	    i__3 = l;	    for (k = 1; k <= i__3; ++k) {		z__[k + j * z_dim1] -= g * d__[k];	    }	}L380:	i__3 = l;	for (k = 1; k <= i__3; ++k) {	    z__[k + i__ * z_dim1] = 0.;	}    }L510:    i__1 = *n;    for (i__ = 1; i__ <= i__1; ++i__) {	d__[i__] = z__[*n + i__ * z_dim1];	z__[*n + i__ * z_dim1] = 0.;    }    z__[*n + *n * z_dim1] = 1.;    e[1] = 0.;    return 0;} int tql2(integer *nm, integer *n, doublereal *d__, 	doublereal *e, doublereal *z__, integer *ierr){    integer z_dim1, z_offset, i__1, i__2, i__3;    doublereal d__1, d__2;    double d_sign(doublereal *, doublereal *);    static doublereal c__, f, g, h__;    static integer i__, j, k, l, m;    static doublereal p, r__, s, c2, c3;    static integer l1, l2;    static doublereal s2;    static integer ii;    static doublereal dl1, el1;    static integer mml;    static doublereal tst1, tst2;    extern doublereal pythag_(doublereal *, doublereal *);/*     this subroutine is a translation of the algol procedure tql2, *//*     num. math. 11, 293-306(1968) by bowdler, martin, reinsch, and *//*     wilkinson. *//*     handbook for auto. comp., vol.ii-linear algebra, 227-240(1971). *//*     this subroutine finds the eigenvalues and eigenvectors *//*     of a symmetric tridiagonal matrix by the ql method. *//*     the eigenvectors of a full symmetric matrix can also *//*     be found if  tred2  has been used to reduce this *//*     full matrix to tridiagonal form. *//*     on input *//*        nm must be set to the row dimension of two-dimensional *//*          array parameters as declared in the calling program *//*          dimension statement. *//*        n is the order of the matrix. *//*        d contains the diagonal elements of the input matrix. *//*        e contains the subdiagonal elements of the input matrix *//*          in its last n-1 positions.  e(1) is arbitrary. *//*        z contains the transformation matrix produced in the *//*          reduction by  tred2, if performed.  if the eigenvectors *//*          of the tridiagonal matrix are desired, z must contain *//*          the identity matrix. *//*      on output *//*        d contains the eigenvalues in ascending order.  if an *//*          error exit is made, the eigenvalues are correct but *//*          unordered for indices 1,2,...,ierr-1. *//*        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 is set to *//*          zero       for normal return, *//*          j          if the j-th eigenvalue has not been *//*                     determined after 30 iterations. *//*     calls pythag for  dsqrt(a*a + b*b) . *//*     questions and comments should be directed to burton s. garbow, *//*     mathematics and computer science div, argonne national laboratory *//*     this version dated august 1983. *//*     ------------------------------------------------------------------ */    z_dim1 = *nm;    z_offset = 1 + z_dim1 * 1;    z__ -= z_offset;    --e;    --d__;    *ierr = 0;    if (*n == 1) {	goto L1001;    }    i__1 = *n;    for (i__ = 2; i__ <= i__1; ++i__) {	e[i__ - 1] = e[i__];    }    f = 0.;    tst1 = 0.;    e[*n] = 0.;    i__1 = *n;    for (l = 1; l <= i__1; ++l) {	j = 0;	h__ = (d__1 = d__[l], abs(d__1)) + (d__2 = e[l], abs(d__2));	if (tst1 < h__) {	    tst1 = h__;	}	i__2 = *n;	for (m = l; m <= i__2; ++m) {	    tst2 = tst1 + (d__1 = e[m], abs(d__1));	    if (tst2 == tst1) {		goto L120;	    }	}L120:	if (m == l) {	    goto L220;	}L130:	if (j == 30) {	    goto L1000;	}	++j;	l1 = l + 1;	l2 = l1 + 1;	g = d__[l];	p = (d__[l1] - g) / (e[l] * 2.);	r__ = pythag(&p, &c_b10);	d__[l] = e[l] / (p + d_sign(&r__, &p));	d__[l1] = e[l] * (p + d_sign(&r__, &p));	dl1 = d__[l1];	h__ = g - d__[l];	if (l2 > *n) {	    goto L145;	}	i__2 = *n;	for (i__ = l2; i__ <= i__2; ++i__) {	    d__[i__] -= h__;	}L145:	f += h__;	p = d__[m];	c__ = 1.;	c2 = c__;	el1 = e[l1];	s = 0.;	mml = m - l;	i__2 = mml;	for (ii = 1; ii <= i__2; ++ii) {	    c3 = c2;	    c2 = c__;	    s2 = s;	    i__ = m - ii;	    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__]);	    i__3 = *n;	    for (k = 1; k <= i__3; ++k) {		h__ = z__[k + (i__ + 1) * z_dim1];		z__[k + (i__ + 1) * z_dim1] = s * z__[k + i__ * z_dim1] + c__ 			* h__;		z__[k + i__ * z_dim1] = c__ * z__[k + i__ * z_dim1] - s * h__;	    }	}	p = -s * s2 * c3 * el1 * e[l] / dl1;	e[l] = s * p;	d__[l] = c__ * p;	tst2 = tst1 + (d__1 = e[l], abs(d__1));	if (tst2 > tst1) {	    goto L130;	}L220:	d__[l] += f;    }    i__1 = *n;    for (ii = 2; ii <= i__1; ++ii) {	i__ = ii - 1;	k = i__;	p = d__[i__];	i__2 = *n;	for (j = ii; j <= i__2; ++j) {	    if (d__[j] >= p) {		goto L260;	    }	    k = j;	    p = d__[j];L260:	    ;	}	if (k == i__) {	    goto L300;	}	d__[k] = d__[i__];	d__[i__] = p;	i__2 = *n;	for (j = 1; j <= i__2; ++j) {	    p = z__[j + i__ * z_dim1];	    z__[j + i__ * z_dim1] = z__[j + k * z_dim1];	    z__[j + k * z_dim1] = p;	}L300:	;    }    goto L1001;L1000:    *ierr = l;L1001:    return 0;}void eigen(double **mat,unsigned long n,double *eig){  double *trans,*off;  int ierr,i,j,nm=(int)n;  check_alloc(trans=(double*)malloc(sizeof(double)*nm*nm));  check_alloc(off=(double*)malloc(sizeof(double)*nm));  tred2(&nm,&nm,&mat[0][0],eig,off,trans);  tql2(&nm,&nm,eig,off,trans,&ierr);  if (ierr != 0) {    fprintf(stderr,"Non converging eigenvalues! Exiting\n");    exit(EIG2_TOO_MANY_ITERATIONS);  }  for (i=0;i<nm;i++)    for (j=0;j<nm;j++)      mat[i][j]=trans[i+nm*j];  free(trans);  free(off);}

⌨️ 快捷键说明

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