-
Notifications
You must be signed in to change notification settings - Fork 0
/
GivensQR.cpp
114 lines (94 loc) · 2.8 KB
/
GivensQR.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* @file GivensQR.cpp
* @author Melih Altun @2015-2017
**/
#include "GivensQR.h"
#define EPS 2.221E-12
// plane rotation using Givens' method
void complexGivensRotation(complex a, complex b, complex *c, complex *s)
{
double tolr = EPS, r;
if (magnitude(b) < tolr) {
*c = { 1.0, 0.0 };
*s = { 0.0, 0.0 };
}
else if (magnitude(a) < tolr) {
*c = { 0.0, 0.0 };
*s = { -1.0, 0.0 };
}
else {
r = sqrt(magnitude(a)*magnitude(a) + magnitude(b)*magnitude(b));
*c = complexDivision(complexConjugate(a), { r, 0.0 });
*s = complexDivision(complexConjugate(b), { r, 0.0 });
}
}
// QR decomposition => [Q,R] = qr(A), where: Q*R = A
void qrGivensComplex(complex A[], unsigned int N, unsigned int M, complex Q[], complex R[])
{
unsigned int i, j;
complex c, s;
complex *G, *Gt, *Rnew, *Qnew;
G = (complex*)malloc(N*N*sizeof(complex));
Gt = (complex*)malloc(N*N * sizeof(complex));
Rnew = (complex*)malloc(N*M * sizeof(complex));
Qnew = (complex*)malloc(N*N * sizeof(complex));
complexIdentity(Q, N);
copyComplexMatrix(A, N, M, R);
for (j = 0; j < M; j++) {
for (i = N - 1; i > j; i--) {
complexIdentity(G, N);
complexGivensRotation(R[lin_index((i - 1), j, M)], R[lin_index(i, j, M)], &c, &s);
G[lin_index((i - 1), (i - 1), N)] = c;
G[lin_index((i - 1), i, N)] = s;
G[lin_index(i, (i - 1), N)] = negate(complexConjugate(s));
G[lin_index(i, i, N)] = complexConjugate(c);
//R = G*R
//Q = Q*G'
hermitian(G, N, N, Gt);
complexMatrixMultiplication(G, R, N, N, M, Rnew);
complexMatrixMultiplication(Q, Gt, N, N, N, Qnew);
copyComplexMatrix(Rnew, N, M, R);
copyComplexMatrix(Qnew, N, N, Q);
}
}
delete[] G;
delete[] Gt;
delete[] Rnew;
delete[] Qnew;
}
//QR algortihm for finding eigen values and eigen vectors
void qrIteration(complex A[], unsigned int N, complex Q[], complex R[])
{
unsigned int k, maxIter = 1000;
double n1, n2, tolr = EPS;
complex *M, *V, *D, *Vnew;
M = (complex*)malloc(N*N * sizeof(complex));
V = (complex*)malloc(N*N * sizeof(complex));
D = (complex*)malloc(N * sizeof(complex));
Vnew = (complex*)malloc(N*N * sizeof(complex));
memcpy(M, A, N*N * sizeof(complex));
complexIdentity(V, N);
complexDiagonal(M, N, D);
n1 = complexVectorNorm(D,N);
for (k = 0; k < maxIter; k++) {
//[Q,R] = qr(M)
qrGivensComplex(M, N, N, Q, R);
//V = V*Q;
complexMatrixMultiplication(V, Q, N, N, N, Vnew);
copyComplexMatrix(Vnew, N, N, V);
//M = R*Q;
complexMatrixMultiplication(R, Q, N, N, N, M);
complexDiagonal(M, N, D);
n2 = complexVectorNorm(D, N);
if (fabs(n1 - n2) < tolr)
break;
n1 = n2;
}
copyComplexMatrix(V, N, N, Q);
copyComplexMatrix(M, N, N, R);
//clear memory
delete[] M;
delete[] V;
delete[] Vnew;
delete[] D;
}