Bridge++  Ver. 1.2.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
eigen_QR_Cmplx.cpp
Go to the documentation of this file.
1 
14 #include "eigen_QR_Cmplx.h"
15 
16 const std::string Eigen_QR_Cmplx::class_name = "Eigen_QR_Cmplx";
17 
18 //====================================================================
19 std::valarray<double> Eigen_QR_Cmplx::solve(const double *matrix)
20 {
21  int Niter = 1000;
22  double Stop_cond = DBL_EPSILON;
23 
24  std::valarray<double> eigen_val(N2);
25 
26  for (int i = 0; i < size; ++i) {
27  m_mat[i] = matrix[i];
28  m_q[i] = 0;
29  }
30  for (int i = 0; i < N; ++i) {
31  m_q[i * N2 + i * 2] = 1;
32  }
33 
34  // change to hessenberg matrix
35  Decompose_Hessenberg_Cmplx hessenberg(N);
36  hessenberg.set_matrix(&m_mat[0]);
37  hessenberg.get_Hessenberg(&m_mat[0]);
38  hessenberg.get_Q(&m_q[0]);
39 
40  // # of unfound eigen value
41  int Neigen = N;
42  for (int i_iter = 0; i_iter < Niter; ++i_iter) {
43  int r1 = Neigen - 1;
44 
45  // ****
46  // ****
47  // *ab
48  // cd
49  double d_re = m_mat[re(r1, r1)];
50  double d_im = m_mat[im(r1, r1)];
51 
52  // get the last eigen value
53  if (Neigen == 1) {
54  eigen_val[re(0)] = d_re;
55  eigen_val[im(0)] = d_im;
56  break;
57  }
58 
59  int r2 = Neigen - 2;
60  double a_re = m_mat[re(r2, r2)];
61  double a_im = m_mat[im(r2, r2)];
62  double& c_re = m_mat[re(r1, r2)];
63  double& c_im = m_mat[im(r1, r2)];
64 
65  double norm_ad = a_re * a_re + a_im * a_im + d_re * d_re + d_im * d_im;
66  double norm_c = c_re * c_re + c_im * c_im;
67 
68  if (norm_c < norm_ad * Stop_cond * Stop_cond) {
69  // When c is very small, d become eigen value.
70  eigen_val[re(r1)] = d_re;
71  eigen_val[im(r1)] = d_im;
72  c_re = c_im = 0;
73  d_re = a_re;
74  d_im = a_im;
75  Neigen -= 1;
76  }
77 
78  // shift
79  for (int r = 0; r < Neigen; ++r) {
80  m_mat[re(r, r)] -= d_re;
81  m_mat[im(r, r)] -= d_im;
82  }
83 
84  // qr step
85  qr_step(Neigen);
86 
87  // shift back
88  for (int r = 0; r < Neigen; ++r) {
89  m_mat[re(r, r)] += d_re;
90  m_mat[im(r, r)] += d_im;
91  }
92  }
93 
94  return eigen_val;
95 }
96 
97 
98 //====================================================================
99 void Eigen_QR_Cmplx::qr_step(const int rank)
100 {
101  std::valarray<double> tau(rank * 2);
102  for (int r = 0; r < rank - 1; ++r) {
103  // diagnal part
104  double& alpha_re = m_mat[re(r, r)];
105  double& alpha_im = m_mat[im(r, r)];
106  // sub diagnal part
107  double& v1_re = m_mat[re(r + 1, r)];
108  double& v1_im = m_mat[im(r + 1, r)];
109 
110  double nu = alpha_re * alpha_re + alpha_im * alpha_im + v1_re * v1_re + v1_im * v1_im;
111 
112  nu = std::sqrt(nu) * ((alpha_re < 0) ? -1 : 1);
113  tau[re(r)] = alpha_re + nu;
114  tau[im(r)] = alpha_im;
115 
116  double norm2_sigma = tau[re(r)] * tau[re(r)] + tau[im(r)] * tau[im(r)];
117  double inv_sigma_re = tau[re(r)] / norm2_sigma;
118  double inv_sigma_im = -tau[im(r)] / norm2_sigma;
119 
120  // householder factor
121  tau[re(r)] /= nu;
122  tau[im(r)] /= nu;
123 
124  alpha_re = -nu;
125  alpha_im = 0;
126 
127  // householder vector
128  double v_re = v1_re;
129  double v_im = v1_im;
130  v1_re = v_re * inv_sigma_re - v_im * inv_sigma_im;
131  v1_im = v_im * inv_sigma_re + v_re * inv_sigma_im;
132 
133  // v = (1, v_1)^T
134  for (int j = r + 1; j < N; ++j) {
135  // va = <v|a_j>
136  double va_re = m_mat[re(r, j)];
137  double va_im = m_mat[im(r, j)];
138  va_re += v1_re * m_mat[re(r + 1, j)] + v1_im * m_mat[im(r + 1, j)];
139  va_im += v1_re * m_mat[im(r + 1, j)] - v1_im * m_mat[re(r + 1, j)];
140 
141  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
142  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
143  // i = r
144  m_mat[re(r, j)] -= beta_re;
145  m_mat[im(r, j)] -= beta_im;
146  // i = r+1
147  m_mat[re(r + 1, j)] -= beta_re * v1_re - beta_im * v1_im;
148  m_mat[im(r + 1, j)] -= beta_re * v1_im + beta_im * v1_re;
149  }
150 
151  // Q -> Q Q_r
152  for (int i = 0; i < N; ++i) {
153  // va = <v|Q_i^*>
154  double va_re = m_q[re(i, r)];
155  double va_im = -m_q[im(i, r)];
156  va_re += v1_re * m_q[re(i, r + 1)] - v1_im * m_q[im(i, r + 1)];
157  va_im -= v1_re * m_q[im(i, r + 1)] + v1_im * m_q[re(i, r + 1)];
158 
159  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
160  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
161  // j = r
162  m_q[re(i, r)] -= beta_re;
163  m_q[im(i, r)] += beta_im;
164  // j = r+1
165  m_q[re(i, r + 1)] -= beta_re * v1_re - beta_im * v1_im;
166  m_q[im(i, r + 1)] += beta_re * v1_im + beta_im * v1_re;
167  }
168  }
169 
170  //A -> RQ
171  for (int r = 0; r < rank - 1; ++r) {
172  double v1_re = m_mat[re(r + 1, r)];
173  double v1_im = m_mat[im(r + 1, r)];
174  m_mat[re(r + 1, r)] = m_mat[im(r + 1, r)] = 0;
175  for (int i = 0; i <= r + 1; ++i) {
176  double va_re = m_mat[re(i, r)];
177  double va_im = -m_mat[im(i, r)];
178  va_re += v1_re * m_mat[re(i, r + 1)] - v1_im * m_mat[im(i, r + 1)];
179  va_im -= v1_re * m_mat[im(i, r + 1)] + v1_im * m_mat[re(i, r + 1)];
180 
181  // beta = tau^* * va
182  // a_i^* -= bata * v
183  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
184  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
185  // j = r
186  m_mat[re(i, r)] -= beta_re;
187  m_mat[im(i, r)] += beta_im;
188  // j = r+1
189  m_mat[re(i, r + 1)] -= beta_re * v1_re - beta_im * v1_im;
190  m_mat[im(i, r + 1)] += beta_re * v1_im + beta_im * v1_re;
191  }
192  }
193 }
194 
195 
196 //====================================================================
197 void Eigen_QR_Cmplx::get_Q(double *q)
198 {
199  for (int i = 0; i < size; ++i) {
200  q[i] = m_q[i];
201  }
202 }
203 
204 
205 //====================================================================
206 void Eigen_QR_Cmplx::get_R(double *r)
207 {
208  for (int i = 0; i < size; ++i) {
209  r[i] = m_mat[i];
210  }
211 
212  /*
213  for (int i = 0; i < N; ++i) {
214  for (int j = i; j < N; ++j) {
215  r[re(i,j)] = m_mat[re(i,j)];
216  r[im(i,j)] = m_mat[im(i,j)];
217  }
218  }
219  */
220 }
221 
222 
223 //====================================================================
void get_R(double *r)
size_t im(const size_t i, const size_t j)
size_t re(const size_t i, const size_t j)
std::valarray< double > solve(const double *matrix)
void qr_step(const int rank)
std::valarray< double > m_mat
void get_Q(double *q)
std::valarray< double > m_q
static const std::string class_name