Skip to content
This repository was archived by the owner on Jun 21, 2024. It is now read-only.

Commit dfc9ec7

Browse files
committed
fix: WilkinsonShiftIteration
1 parent df0da5a commit dfc9ec7

File tree

3 files changed

+43
-54
lines changed

3 files changed

+43
-54
lines changed

lib/HouseholderMethod/Bidiagonalization.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,9 @@ Bidiagonalization_Result BidiagonalizationMethod(const Matrix &matrix) {
2626
P.set(k, m, k, m, P_sub);
2727
U = P * U;
2828

29-
// B = P * B;
30-
31-
// TODO: WTF WHY DOESN'T THIS WORK FUCK IT
3229
auto A_sub = B.sub_matrix(k, m, k, n);
3330
A_sub = A_sub - product(v, v) * beta * A_sub;
3431
B.set(k, m, k, n, A_sub);
35-
//
36-
// B.set_col(k + 1, m, k, v.sub_vector(1, m - k));
3732

3833
if (k < n - 2) {
3934
auto [v, beta] = HouseHolderMethod(B.sub_array_row(k, k + 1, n));
@@ -43,18 +38,9 @@ Bidiagonalization_Result BidiagonalizationMethod(const Matrix &matrix) {
4338
Q.set(k + 1, n, k + 1, n, Q_sub);
4439
V = Q * V;
4540

46-
// B = B * Q;
47-
48-
// TODO: WTF WHY DOESN'T THIS WORK FUCK IT
49-
// NEVER MIND, the B.set_row was meant to store Q,
50-
// but let's skip it as it's really confusing
51-
// > what a wierd way to store stuff,
52-
// > some FORTRAN programing perhaps?
5341
auto A_sub = B.sub_matrix(k, m, k + 1, n);
5442
A_sub = A_sub - A_sub * product(v, v) * beta;
5543
B.set(k, m, k + 1, n, A_sub);
56-
//
57-
// B.set_row(k, k + 2, n, v.sub_vector(1, n - k - 1));
5844
}
5945
}
6046

lib/SVDMethod/SVDMethod.cpp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,75 @@
66

77

88
// SVD iteration with Wilkinson shift
9+
// W(A) -> P, Q, B, s.t. B = P * A * Q
910
WilkinsonShift_Result WilkinsonShiftIteration(const Matrix &matrix) {
1011
auto B = Matrix(matrix);
11-
auto n = B.rows;
12-
auto P = Matrix::identity(n);
12+
auto m = B.rows;
13+
auto n = B.cols;
14+
auto P = Matrix::identity(m);
1315
auto Q = Matrix::identity(n);
1416

1517
#define DELTA(i) B.matrix[i - 1][i - 1]
1618
#define GAMMA(i) B.matrix[i - 1][i]
17-
1819
auto alpha = DELTA(n) * DELTA(n) + GAMMA(n - 1) * GAMMA(n - 1);
1920
auto delta = (DELTA(n - 1) * DELTA(n - 1) + GAMMA(n - 2) * GAMMA(n - 2) - alpha) / 2;
2021
auto beta = DELTA(n - 1) * GAMMA(n - 1);
2122
auto mu = alpha - beta * beta / (delta + SIGN(delta) * std::sqrt(delta * delta + beta * beta));
2223

2324
auto y = DELTA(1) * DELTA(1) - mu;
2425
auto z = DELTA(1) * GAMMA(1);
26+
#undef DELTA
27+
#undef GAMMA
2528

26-
for (ull k = 0; k < n; k++) {
27-
auto t = -z / y; // tan(theta)
28-
auto c = 1 / std::sqrt(1 + t * t); // cos(theta)
29-
auto s = c * t; // sin(theta)
30-
31-
Q = Q * RotationMatrix(n, k + 1, k + 2, c, s);
29+
auto t = -z / y;
30+
auto c = 1 / std::sqrt(1 + t * t);
31+
auto s = c * t;
3232

33-
y = c * DELTA(k + 1) - s * GAMMA(k + 1);
34-
z = -s * DELTA(k + 2);
35-
GAMMA(k + 1) = s * DELTA(k + 1) + c * GAMMA(k + 1);
36-
DELTA(k + 2) = c * DELTA(k + 2);
33+
auto G1 = RotationMatrix(n, 0, 1, c, s);
34+
B = B * G1;
35+
Q = Q * G1;
3736

38-
t = -z / y; // tan(theta)
37+
for (ull k = 0; k < n - 1; k++) {
38+
t = -B.matrix[k + 1][k] / B.matrix[k][k]; // tan(theta)
3939
c = 1 / std::sqrt(1 + t * t); // cos(theta)
4040
s = c * t; // sin(theta)
4141

42-
P = RotationMatrix(n, k + 1, k + 2, c, s) * P;
43-
if (k != n - 1) {
44-
y = c * GAMMA(k + 1) - s * DELTA(k + 2);
45-
z = -s * GAMMA(k + 2);
46-
DELTA(k + 1) = s * GAMMA(k + 1) + c * DELTA(k + 2);
47-
GAMMA(k + 2) = c * GAMMA(k + 2);
48-
} else {
49-
auto gamma_k = GAMMA(k + 1);
50-
auto delta_k = DELTA(k + 2);
51-
52-
GAMMA(k + 1) = c * gamma_k - s * delta_k;
53-
DELTA(k + 2) = s * gamma_k + c * delta_k;
42+
auto G = RotationMatrix(m, k, k + 1, c, s);
43+
B = G * B;
44+
P = G * P;
45+
46+
47+
if (k != n - 2) {
48+
t = B.matrix[k][k + 2] / B.matrix[k][k + 1]; // tan(theta)
49+
c = 1 / std::sqrt(1 + t * t); // cos(theta)
50+
s = c * t; // sin(theta)
51+
52+
G = RotationMatrix(n, k + 1, k + 2, c, s);
53+
B = B * G;
54+
Q = Q * G;
5455
}
5556
}
5657

5758
return {B, P, Q};
58-
#undef DELTA
59-
#undef GAMMA
6059
}
6160

6261
// Consider position k have DELTA(k + 1) = 0
6362
// Then we can use Givens rotation to make GAMMA(k) = 0 as well:
6463
ReformBidiagonalization_Result ReformBidiagonalization(const Matrix &matrix, ull k) {
6564
auto B = Matrix(matrix);
66-
auto n = B.rows;
67-
auto G = Matrix::identity(n);
65+
auto m = B.rows;
66+
auto n = B.cols;
67+
auto G = Matrix::identity(m);
6868

6969
B.print();
7070

71-
for (ull i = k + 1; i < B.cols; i++) {
72-
auto t = B.matrix[k][i] / B.matrix[i][i] ; // tan(theta)
71+
for (ull i = k + 1; i < n; i++) {
72+
auto t = B.matrix[k][i] / B.matrix[i][i]; // tan(theta)
7373
auto c = 1 / std::sqrt(1 + t * t); // cos(theta)
7474
auto s = c * t; // sin(theta)
7575

76-
G = RotationMatrix(n, k, i, c, s) * G;
77-
B = RotationMatrix(n, k, i, c, s) * B;
76+
G = RotationMatrix(m, k, i, c, s) * G;
77+
B = RotationMatrix(m, k, i, c, s) * B;
7878

7979
B.print();
8080
G.print();
@@ -83,6 +83,7 @@ ReformBidiagonalization_Result ReformBidiagonalization(const Matrix &matrix, ull
8383
return {B, G};
8484
}
8585

86-
//SVDMethod_Result SVDMethod(const Matrix &matrix) {
87-
//
88-
//}
86+
SVDMethod_Result SVDMethod(const Matrix &matrix) {
87+
88+
89+
}

main.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
int main() {
55
auto A = Matrix(8, 5, 1, 10);
66
A = BidiagonalizationMethod(A).B;
7-
A.matrix[1][1] = 0;
7+
A.matrix[1][0] = 5;
88

9-
auto r = ReformBidiagonalization(A, 1);
9+
A.print();
10+
11+
auto r = WilkinsonShiftIteration(A);
1012

1113
r.B.print();
12-
r.G.print();
14+
(r.P * A * r.Q).print();
1315

1416
return 0;
1517
}

0 commit comments

Comments
 (0)