Matrix &Matrix::eigenSystem() { Matrix *values; assertDefined("eigenSystem"); assertSquare("eigenSystem"); values = new Matrix(1, maxc); // allocates space for eigen values { double *d, *e; tridiagonalize(d, e); // allocates space for 2 double arrays eigen(d, e, maxc, m); // returns eigen values in d delete values->m[0]; // save the eigen values from above routines values->m[0] = d; delete e; } transposeSelf(); // result was returned in columns so put it in rows isort(values->m[0], m, maxc); // sort rows so vector with max eigenvalue is first values->defined = true; // mark eigen value matrix as defined return *values; }
int main() { int i, j, k, n; static matrix a, p; static vector d, e, temp; double s, t; printf("n = "); scanf("%d", &n); printf("乱数の種 (正の整数) = "); scanf("%ul", &seed); seed |= 1; a = new_matrix(n, n); p = new_matrix(n, n); d = new_vector(n); e = new_vector(n); temp = new_vector(n); for (i = 0; i < n; i++) for (j = 0; j <= i; j++) a[i][j] = a[j][i] = p[i][j] = p[j][i] = rnd() - rnd(); printf("A:\n"); matprint(a, n, 7, "%10.6f"); tridiagonalize(n, p, d, e); printf("d:\n"); vecprint(d, n, 5, "% -14g"); printf("e:\n"); vecprint(e, n - 1, 5, "% -14g"); for (i = 0; i < n; i++) { for (k = 0; k < n; k++) temp[k] = a[i][k]; for (j = 0; j < n; j++) { s = 0; for (k = 0; k < n; k++) s += temp[k] * p[j][k]; a[i][j] = s; } } for (j = 0; j < n; j++) { for (k = 0; k < n; k++) temp[k] = a[k][j]; for (i = 0; i < n; i++) { s = 0; for (k = 0; k < n; k++) s += p[i][k] * temp[k]; a[i][j] = s; } } s = 0; for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (i == j) { t = a[i][j] - d[i]; s += t * t; } else if (i + 1 == j) { t = a[i][j] - e[i]; s += t * t; } else if (i == j + 1) { t = a[i][j] - e[j]; s += t * t; } else { t = a[i][j]; s += t * t; } printf("二乗平均誤差: %g\n", sqrt(s) / n); return EXIT_SUCCESS; }
double * symmetricQR(matrix A){ /* Symmetric QR for computation of eigenvalues. Source: Golub and Van Loan, Matrix Computations p. 421. Input: matrix A Square, symmetric matrix of which to compute eigenvalues Output: double *eigs (returned) Eigenvalues of the matrix */ double *eigs = (double *) malloc(A.n * sizeof(double)) ; A = tridiagonalize(A) ; int i, k; int start; int n = A.n ; int maxIt = 10000; int p,q = 0 ; double tol = 1e-14 ; int iteration = 0 ; while(q < n-1){ for (i = 0; i<n-1; i++){ if ( fabs( A.values[i+1][i] ) <= tol * (fabs( A.values[i][i] ) + fabs( A.values[i+1][i+1] )) ) { A.values[i+1][i] = 0.0; A.values[i][i+1] = 0.0; } } // find largest diagonal block in lower right of matrix start = n-q; //loop index starts with previously found diagonal block for( k = start - 1; k >= 0; k--){ //check off-diagonal entries //only above diagonal is checked because of symmetry if(k != 0){ if(A.values[k][k-1] == 0.0) q++; else break ; } } p = n - q - 1; for (k = start - 1; k > 0; k--) { if (A.values[k][k - 1] != 0) p--; else break; } if (q < n - 1 ){ A = symmetricQRStep(A, p, n-q) ; } iteration++ ; if (iteration > maxIt){ fprintf(stderr, "Max it reached. Returning.\n"); break ; } } for(i=0; i<n; i++) eigs[i] = A.values[i][i] ; qsort(eigs, n, sizeof(double), compareDoubles) ; return eigs ; }