6
6
7
7
8
8
// SVD iteration with Wilkinson shift
9
+ // W(A) -> P, Q, B, s.t. B = P * A * Q
9
10
WilkinsonShift_Result WilkinsonShiftIteration (const Matrix &matrix) {
10
11
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);
13
15
auto Q = Matrix::identity (n);
14
16
15
17
#define DELTA (i ) B.matrix[i - 1 ][i - 1 ]
16
18
#define GAMMA (i ) B.matrix[i - 1 ][i]
17
-
18
19
auto alpha = DELTA (n) * DELTA (n) + GAMMA (n - 1 ) * GAMMA (n - 1 );
19
20
auto delta = (DELTA (n - 1 ) * DELTA (n - 1 ) + GAMMA (n - 2 ) * GAMMA (n - 2 ) - alpha) / 2 ;
20
21
auto beta = DELTA (n - 1 ) * GAMMA (n - 1 );
21
22
auto mu = alpha - beta * beta / (delta + SIGN (delta) * std::sqrt (delta * delta + beta * beta));
22
23
23
24
auto y = DELTA (1 ) * DELTA (1 ) - mu;
24
25
auto z = DELTA (1 ) * GAMMA (1 );
26
+ #undef DELTA
27
+ #undef GAMMA
25
28
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;
32
32
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;
37
36
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)
39
39
c = 1 / std::sqrt (1 + t * t); // cos(theta)
40
40
s = c * t; // sin(theta)
41
41
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;
54
55
}
55
56
}
56
57
57
58
return {B, P, Q};
58
- #undef DELTA
59
- #undef GAMMA
60
59
}
61
60
62
61
// Consider position k have DELTA(k + 1) = 0
63
62
// Then we can use Givens rotation to make GAMMA(k) = 0 as well:
64
63
ReformBidiagonalization_Result ReformBidiagonalization (const Matrix &matrix, ull k) {
65
64
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);
68
68
69
69
B.print ();
70
70
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)
73
73
auto c = 1 / std::sqrt (1 + t * t); // cos(theta)
74
74
auto s = c * t; // sin(theta)
75
75
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;
78
78
79
79
B.print ();
80
80
G.print ();
@@ -83,6 +83,7 @@ ReformBidiagonalization_Result ReformBidiagonalization(const Matrix &matrix, ull
83
83
return {B, G};
84
84
}
85
85
86
- // SVDMethod_Result SVDMethod(const Matrix &matrix) {
87
- //
88
- // }
86
+ SVDMethod_Result SVDMethod (const Matrix &matrix) {
87
+
88
+
89
+ }
0 commit comments