| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* eigens.c |
|
2
|
|
|
|
|
|
|
* |
|
3
|
|
|
|
|
|
|
* Eigenvalues and eigenvectors of a real symmetric matrix |
|
4
|
|
|
|
|
|
|
* |
|
5
|
|
|
|
|
|
|
* |
|
6
|
|
|
|
|
|
|
* |
|
7
|
|
|
|
|
|
|
* SYNOPSIS: |
|
8
|
|
|
|
|
|
|
* |
|
9
|
|
|
|
|
|
|
* int n; |
|
10
|
|
|
|
|
|
|
* double A[n*(n+1)/2], EV[n*n], E[n]; |
|
11
|
|
|
|
|
|
|
* void eigens( A, EV, E, n ); |
|
12
|
|
|
|
|
|
|
* |
|
13
|
|
|
|
|
|
|
* |
|
14
|
|
|
|
|
|
|
* |
|
15
|
|
|
|
|
|
|
* DESCRIPTION: |
|
16
|
|
|
|
|
|
|
* |
|
17
|
|
|
|
|
|
|
* The algorithm is due to J. vonNeumann. |
|
18
|
|
|
|
|
|
|
* - - |
|
19
|
|
|
|
|
|
|
* A[] is a symmetric matrix stored in lower triangular form. |
|
20
|
|
|
|
|
|
|
* That is, A[ row, column ] = A[ (row*row+row)/2 + column ] |
|
21
|
|
|
|
|
|
|
* or equivalently with row and column interchanged. The |
|
22
|
|
|
|
|
|
|
* indices row and column run from 0 through n-1. |
|
23
|
|
|
|
|
|
|
* |
|
24
|
|
|
|
|
|
|
* EV[] is the output matrix of eigenvectors stored columnwise. |
|
25
|
|
|
|
|
|
|
* That is, the elements of each eigenvector appear in sequential |
|
26
|
|
|
|
|
|
|
* memory order. The jth element of the ith eigenvector is |
|
27
|
|
|
|
|
|
|
* EV[ n*i+j ] = EV[i][j]. |
|
28
|
|
|
|
|
|
|
* |
|
29
|
|
|
|
|
|
|
* E[] is the output matrix of eigenvalues. The ith element |
|
30
|
|
|
|
|
|
|
* of E corresponds to the ith eigenvector (the ith row of EV). |
|
31
|
|
|
|
|
|
|
* |
|
32
|
|
|
|
|
|
|
* On output, the matrix A will have been diagonalized and its |
|
33
|
|
|
|
|
|
|
* orginal contents are destroyed. |
|
34
|
|
|
|
|
|
|
* |
|
35
|
|
|
|
|
|
|
* ACCURACY: |
|
36
|
|
|
|
|
|
|
* |
|
37
|
|
|
|
|
|
|
* The error is controlled by an internal parameter called RANGE |
|
38
|
|
|
|
|
|
|
* which is set to 1e-10. After diagonalization, the |
|
39
|
|
|
|
|
|
|
* off-diagonal elements of A will have been reduced by |
|
40
|
|
|
|
|
|
|
* this factor. |
|
41
|
|
|
|
|
|
|
* |
|
42
|
|
|
|
|
|
|
* ERROR MESSAGES: |
|
43
|
|
|
|
|
|
|
* |
|
44
|
|
|
|
|
|
|
* None. |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
Now orders output using code from TQL2 from EISPACK |
|
47
|
|
|
|
|
|
|
* |
|
48
|
|
|
|
|
|
|
*/ |
|
49
|
|
|
|
|
|
|
/* |
|
50
|
|
|
|
|
|
|
Copyright 1973, 1991 by Stephen L. Moshier |
|
51
|
|
|
|
|
|
|
Copyleft version. |
|
52
|
|
|
|
|
|
|
*/ |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
#include |
|
55
|
|
|
|
|
|
|
|
|
56
|
5
|
|
|
|
|
|
void eigens( double A[], double EV[], double E[], int N ) { |
|
57
|
|
|
|
|
|
|
int IND, L, LL, LM, M, MM, MQ, I, J, IA, LQ; |
|
58
|
|
|
|
|
|
|
int IQ, IM, IL, NLI, NMI; |
|
59
|
|
|
|
|
|
|
double ANORM, ANORMX, AIA, THR, ALM, ALL, AMM, X, Y; |
|
60
|
|
|
|
|
|
|
double SINX, SINX2, COSX, COSX2, SINCS, AIL, AIM; |
|
61
|
|
|
|
|
|
|
double RLI, RMI; |
|
62
|
|
|
|
|
|
|
static double RANGE = 1.0e-10; /*3.0517578e-5;*/ |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
/* Initialize identity matrix in EV[] */ |
|
65
|
116
|
100
|
|
|
|
|
for ( J=0; J
|
|
66
|
111
|
|
|
|
|
|
EV[J] = 0.0; |
|
67
|
5
|
|
|
|
|
|
MM = 0; |
|
68
|
26
|
100
|
|
|
|
|
for ( J=0; J
|
|
69
|
21
|
|
|
|
|
|
EV[MM + J] = 1.0; |
|
70
|
21
|
|
|
|
|
|
MM += N; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
5
|
|
|
|
|
|
ANORM=0.0; |
|
74
|
26
|
100
|
|
|
|
|
for ( I=0; I
|
|
75
|
132
|
100
|
|
|
|
|
for ( J=0; J
|
|
76
|
111
|
100
|
|
|
|
|
if ( I != J ) { |
|
77
|
90
|
|
|
|
|
|
IA = I + (J*J+J)/2; |
|
78
|
90
|
|
|
|
|
|
AIA = A[IA]; |
|
79
|
90
|
|
|
|
|
|
ANORM += AIA * AIA; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
} |
|
83
|
5
|
50
|
|
|
|
|
if ( ANORM > 0.0 ) { |
|
84
|
5
|
|
|
|
|
|
ANORM = sqrt( ANORM + ANORM ); |
|
85
|
5
|
|
|
|
|
|
ANORMX = ANORM * RANGE / N; |
|
86
|
5
|
|
|
|
|
|
THR = ANORM; |
|
87
|
|
|
|
|
|
|
|
|
88
|
113
|
100
|
|
|
|
|
while ( THR > ANORMX ) { |
|
89
|
108
|
|
|
|
|
|
THR /= N; |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
do { /* while IND != 0 */ |
|
92
|
146
|
|
|
|
|
|
IND = 0; |
|
93
|
|
|
|
|
|
|
|
|
94
|
605
|
100
|
|
|
|
|
for ( L=0; L
|
|
95
|
1753
|
100
|
|
|
|
|
for ( M=L+1; M
|
|
96
|
1294
|
|
|
|
|
|
MQ=(M*M+M)/2; |
|
97
|
1294
|
|
|
|
|
|
LM=L+MQ; |
|
98
|
1294
|
|
|
|
|
|
ALM=A[LM]; |
|
99
|
1294
|
100
|
|
|
|
|
if ( fabs(ALM) < THR ) |
|
100
|
1162
|
|
|
|
|
|
continue; |
|
101
|
|
|
|
|
|
|
|
|
102
|
132
|
|
|
|
|
|
IND=1; |
|
103
|
132
|
|
|
|
|
|
LQ=(L*L+L)/2; |
|
104
|
132
|
|
|
|
|
|
LL=L+LQ; |
|
105
|
132
|
|
|
|
|
|
MM=M+MQ; |
|
106
|
132
|
|
|
|
|
|
ALL=A[LL]; |
|
107
|
132
|
|
|
|
|
|
AMM=A[MM]; |
|
108
|
132
|
|
|
|
|
|
X=(ALL-AMM)/2.0; |
|
109
|
132
|
|
|
|
|
|
Y=ALM/sqrt(ALM*ALM+X*X); |
|
110
|
132
|
100
|
|
|
|
|
if (X >= 0.0) |
|
111
|
46
|
|
|
|
|
|
Y=-Y; |
|
112
|
132
|
|
|
|
|
|
SINX = Y / sqrt( 2.0 * (1.0 + sqrt( 1.0-Y*Y)) ); |
|
113
|
132
|
|
|
|
|
|
SINX2=SINX*SINX; |
|
114
|
132
|
|
|
|
|
|
COSX2=1.0-SINX2; |
|
115
|
132
|
|
|
|
|
|
COSX=sqrt(COSX2); |
|
116
|
132
|
|
|
|
|
|
SINCS=SINX*COSX; |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
/* ROTATE L AND M COLUMNS */ |
|
119
|
1032
|
100
|
|
|
|
|
for ( I=0; I
|
|
120
|
900
|
|
|
|
|
|
IQ=(I*I+I)/2; |
|
121
|
900
|
100
|
|
|
|
|
if ( (I != M) && (I != L) ) { |
|
|
|
100
|
|
|
|
|
|
|
122
|
636
|
100
|
|
|
|
|
IM=(I > M) ? M+IQ : I+MQ; |
|
123
|
636
|
100
|
|
|
|
|
IL=(I >= L) ? L+IQ : I+LQ; |
|
124
|
636
|
|
|
|
|
|
AIL=A[IL]; |
|
125
|
636
|
|
|
|
|
|
AIM=A[IM]; |
|
126
|
636
|
|
|
|
|
|
X=AIL*COSX-AIM*SINX; |
|
127
|
636
|
|
|
|
|
|
A[IM]=AIL*SINX+AIM*COSX; |
|
128
|
636
|
|
|
|
|
|
A[IL]=X; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
900
|
|
|
|
|
|
NLI = N*L + I; |
|
131
|
900
|
|
|
|
|
|
NMI = N*M + I; |
|
132
|
900
|
|
|
|
|
|
RLI = EV[ NLI ]; |
|
133
|
900
|
|
|
|
|
|
RMI = EV[ NMI ]; |
|
134
|
900
|
|
|
|
|
|
EV[NLI]=RLI*COSX-RMI*SINX; |
|
135
|
900
|
|
|
|
|
|
EV[NMI]=RLI*SINX+RMI*COSX; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
132
|
|
|
|
|
|
X=2.0*ALM*SINCS; |
|
139
|
132
|
|
|
|
|
|
A[LL]=ALL*COSX2+AMM*SINX2-X; |
|
140
|
132
|
|
|
|
|
|
A[MM]=ALL*SINX2+AMM*COSX2+X; |
|
141
|
132
|
|
|
|
|
|
A[LM]=(ALL-AMM)*SINCS+ALM*(COSX2-SINX2); |
|
142
|
|
|
|
|
|
|
} /* for M=L+1 to N-1 */ |
|
143
|
|
|
|
|
|
|
} /* for L=0 to N-2 */ |
|
144
|
|
|
|
|
|
|
|
|
145
|
146
|
100
|
|
|
|
|
} while ( IND != 0 ); |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
} /* while THR > ANORMX */ |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
/* Extract eigenvalues from the reduced matrix */ |
|
151
|
5
|
|
|
|
|
|
L=0; |
|
152
|
26
|
100
|
|
|
|
|
for ( J=0; J
|
|
153
|
21
|
|
|
|
|
|
L=L+J+1; |
|
154
|
21
|
|
|
|
|
|
E[J]=A[L-1]; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
/* from TQL2, order eigenvalues and -vectors */ |
|
158
|
|
|
|
|
|
|
int II; |
|
159
|
21
|
100
|
|
|
|
|
for ( II = 1; II < N; II++) { |
|
160
|
16
|
|
|
|
|
|
I = II - 1; |
|
161
|
16
|
|
|
|
|
|
int K = I; |
|
162
|
16
|
|
|
|
|
|
double P = E[I]; |
|
163
|
61
|
100
|
|
|
|
|
for ( J = II; J < N; J++ ) { |
|
164
|
45
|
100
|
|
|
|
|
if (E[J] >= P) continue; |
|
165
|
12
|
|
|
|
|
|
K = J; |
|
166
|
12
|
|
|
|
|
|
P = E[J]; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
16
|
100
|
|
|
|
|
if (K == I) continue; |
|
169
|
11
|
|
|
|
|
|
E[K] = E[I]; |
|
170
|
11
|
|
|
|
|
|
E[I] = P; |
|
171
|
72
|
100
|
|
|
|
|
for ( J = 0; J < N; J++ ) { |
|
172
|
61
|
|
|
|
|
|
P = EV[ N*I+J ]; |
|
173
|
61
|
|
|
|
|
|
EV[ N*I+J ] = EV[ N*K+J ]; |
|
174
|
61
|
|
|
|
|
|
EV[ N*K+J ] = P; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
} |
|
177
|
5
|
|
|
|
|
|
} |