Bridge++  Version 1.5.4
 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 
103  for (int r = 0; r < rank - 1; ++r) {
104  // diagnal part
105  double& alpha_re = m_mat[re(r, r)];
106  double& alpha_im = m_mat[im(r, r)];
107  // sub diagnal part
108  double& v1_re = m_mat[re(r + 1, r)];
109  double& v1_im = m_mat[im(r + 1, r)];
110 
111  double nu = alpha_re * alpha_re + alpha_im * alpha_im + v1_re * v1_re + v1_im * v1_im;
112 
113  nu = std::sqrt(nu) * ((alpha_re < 0) ? -1 : 1);
114  tau[re(r)] = alpha_re + nu;
115  tau[im(r)] = alpha_im;
116 
117  double norm2_sigma = tau[re(r)] * tau[re(r)] + tau[im(r)] * tau[im(r)];
118  double inv_sigma_re = tau[re(r)] / norm2_sigma;
119  double inv_sigma_im = -tau[im(r)] / norm2_sigma;
120 
121  // householder factor
122  tau[re(r)] /= nu;
123  tau[im(r)] /= nu;
124 
125  alpha_re = -nu;
126  alpha_im = 0;
127 
128  // householder vector
129  double v_re = v1_re;
130  double v_im = v1_im;
131  v1_re = v_re * inv_sigma_re - v_im * inv_sigma_im;
132  v1_im = v_im * inv_sigma_re + v_re * inv_sigma_im;
133 
134  // v = (1, v_1)^T
135  for (int j = r + 1; j < N; ++j) {
136  // va = <v|a_j>
137  double va_re = m_mat[re(r, j)];
138  double va_im = m_mat[im(r, j)];
139  va_re += v1_re * m_mat[re(r + 1, j)] + v1_im * m_mat[im(r + 1, j)];
140  va_im += v1_re * m_mat[im(r + 1, j)] - v1_im * m_mat[re(r + 1, j)];
141 
142  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
143  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
144  // i = r
145  m_mat[re(r, j)] -= beta_re;
146  m_mat[im(r, j)] -= beta_im;
147  // i = r+1
148  m_mat[re(r + 1, j)] -= beta_re * v1_re - beta_im * v1_im;
149  m_mat[im(r + 1, j)] -= beta_re * v1_im + beta_im * v1_re;
150  }
151 
152  // Q -> Q Q_r
153  for (int i = 0; i < N; ++i) {
154  // va = <v|Q_i^*>
155  double va_re = m_q[re(i, r)];
156  double va_im = -m_q[im(i, r)];
157  va_re += v1_re * m_q[re(i, r + 1)] - v1_im * m_q[im(i, r + 1)];
158  va_im -= v1_re * m_q[im(i, r + 1)] + v1_im * m_q[re(i, r + 1)];
159 
160  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
161  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
162  // j = r
163  m_q[re(i, r)] -= beta_re;
164  m_q[im(i, r)] += beta_im;
165  // j = r+1
166  m_q[re(i, r + 1)] -= beta_re * v1_re - beta_im * v1_im;
167  m_q[im(i, r + 1)] += beta_re * v1_im + beta_im * v1_re;
168  }
169  }
170 
171  //A -> RQ
172  for (int r = 0; r < rank - 1; ++r) {
173  double v1_re = m_mat[re(r + 1, r)];
174  double v1_im = m_mat[im(r + 1, r)];
175  m_mat[re(r + 1, r)] = m_mat[im(r + 1, r)] = 0;
176  for (int i = 0; i <= r + 1; ++i) {
177  double va_re = m_mat[re(i, r)];
178  double va_im = -m_mat[im(i, r)];
179  va_re += v1_re * m_mat[re(i, r + 1)] - v1_im * m_mat[im(i, r + 1)];
180  va_im -= v1_re * m_mat[im(i, r + 1)] + v1_im * m_mat[re(i, r + 1)];
181 
182  // beta = tau^* * va
183  // a_i^* -= bata * v
184  double beta_re = tau[re(r)] * va_re + tau[im(r)] * va_im;
185  double beta_im = tau[re(r)] * va_im - tau[im(r)] * va_re;
186  // j = r
187  m_mat[re(i, r)] -= beta_re;
188  m_mat[im(i, r)] += beta_im;
189  // j = r+1
190  m_mat[re(i, r + 1)] -= beta_re * v1_re - beta_im * v1_im;
191  m_mat[im(i, r + 1)] += beta_re * v1_im + beta_im * v1_re;
192  }
193  }
194 }
195 
196 
197 //====================================================================
198 void Eigen_QR_Cmplx::get_Q(double *q)
199 {
200  for (int i = 0; i < size; ++i) {
201  q[i] = m_q[i];
202  }
203 }
204 
205 
206 //====================================================================
207 void Eigen_QR_Cmplx::get_R(double *r)
208 {
209  for (int i = 0; i < size; ++i) {
210  r[i] = m_mat[i];
211  }
212 
213  /*
214  for (int i = 0; i < N; ++i) {
215  for (int j = i; j < N; ++j) {
216  r[re(i,j)] = m_mat[re(i,j)];
217  r[im(i,j)] = m_mat[im(i,j)];
218  }
219  }
220  */
221 }
222 
223 
224 //====================================================================
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