Bridge++  Version 1.5.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
decompose_QR_Cmplx.cpp
Go to the documentation of this file.
1 
14 #include "decompose_QR_Cmplx.h"
15 
16 //====================================================================
17 void Decompose_QR_Cmplx::set_matrix(const double *mat)
18 {
19  // double epsilon = DBL_EPSILON;
20 
21  // matrix copy
22  for (int i = 0; i < size; ++i) {
23  m_qr[i] = mat[i];
24  }
25 
26  // Householder trans for r col.
27  for (int r = 0; r < N; ++r) {
28  // diagnal part
29  double& alpha_re = m_qr[re(r, r)];
30  double& alpha_im = m_qr[im(r, r)];
31 
32  // make Householder vector v and factor tau.
33  // H = I - tau vv^\dag
34  // H^\dag x = (beta, 0, ...)^T
35  // nu = |x| sign(Re(x_1))
36 
37  // tau = sigma / nu
38  // beta = - nu
39  // Re(sigma) = Re(x_1) + nu
40  // Im(sigma) = Im(x_1)
41  // v = (1, x_2/sigma, ..., x_n/sigma);
42 
43 
44  double nu = 0;
45  for (int i = r; i < N; ++i) {
46  nu += m_qr[re(i, r)] * m_qr[re(i, r)] + m_qr[im(i, r)] * m_qr[im(i, r)];
47  }
48 
49  /*
50  if (nu < epsilon) {
51  // assertion?
52  }
53  */
54 
55  nu = std::sqrt(nu) * ((alpha_re < 0) ? -1 : 1);
56  m_tau[re(r)] = alpha_re + nu;
57  m_tau[im(r)] = alpha_im;
58 
59  double norm2_sigma = m_tau[re(r)] * m_tau[re(r)] + m_tau[im(r)] * m_tau[im(r)];
60  double inv_sigma_re = m_tau[re(r)] / norm2_sigma;
61  double inv_sigma_im = -m_tau[im(r)] / norm2_sigma;
62 
63  m_tau[re(r)] /= nu;
64  m_tau[im(r)] /= nu;
65 
66  // m_qr[r,r] = -nu
67  // m_qr[r,i] /= sigma
68  alpha_re = -nu;
69  alpha_im = 0;
70  for (int i = r + 1; i < N; ++i) {
71  double ir_re = m_qr[re(i, r)];
72  double ir_im = m_qr[im(i, r)];
73 
74  m_qr[re(i, r)] = ir_re * inv_sigma_re - ir_im * inv_sigma_im;
75  m_qr[im(i, r)] = ir_im * inv_sigma_re + ir_re * inv_sigma_im;
76  }
77 
78  // H^\dag a_j
79  for (int j = r + 1; j < N; ++j) {
80  // va = <v|a_j>
81  double va_re = m_qr[re(r, j)];
82  double va_im = m_qr[im(r, j)];
83  for (int i = r + 1; i < N; ++i) {
84  va_re += m_qr[re(i, r)] * m_qr[re(i, j)] + m_qr[im(i, r)] * m_qr[im(i, j)];
85  va_im += m_qr[re(i, r)] * m_qr[im(i, j)] - m_qr[im(i, r)] * m_qr[re(i, j)];
86  }
87  // beta = tau^* * va
88  // a_j -= bata * v
89  double beta_re = m_tau[re(r)] * va_re + m_tau[im(r)] * va_im;
90  double beta_im = m_tau[re(r)] * va_im - m_tau[im(r)] * va_re;
91  m_qr[re(r, j)] -= beta_re;
92  m_qr[im(r, j)] -= beta_im;
93  for (int i = r + 1; i < N; ++i) {
94  double vi_re = m_qr[re(i, r)];
95  double vi_im = m_qr[im(i, r)];
96 
97  m_qr[re(i, j)] -= beta_re * vi_re - beta_im * vi_im;
98  m_qr[im(i, j)] -= beta_re * vi_im + beta_im * vi_re;
99  }
100  }
101  }
102 }
103 
104 
105 //====================================================================
106 void Decompose_QR_Cmplx::get_R(double *mat)
107 {
108  for (int i = 0; i < size; ++i) {
109  mat[i] = m_qr[i];
110  }
111  for (int i = 0; i < N; ++i) {
112  for (int j = 0; j < i; ++j) {
113  mat[re(i, j)] = mat[im(i, j)] = 0;
114  }
115  }
116 }
117 
118 
119 //====================================================================
120 void Decompose_QR_Cmplx::solve(double *vec)
121 {
122  // vec -> Q^\dag vec
123  for (int r = 0; r < N; ++r) {
124  // va = <v|vec>
125  double va_re = vec[re(r)];
126  double va_im = vec[im(r)];
127  for (int i = r + 1; i < N; ++i) {
128  va_re += m_qr[re(i, r)] * vec[re(i)] + m_qr[im(i, r)] * vec[im(i)];
129  va_im += m_qr[re(i, r)] * vec[im(i)] - m_qr[im(i, r)] * vec[re(i)];
130  }
131 
132  // beta = tau^* * va
133  // a_j -= bata * v
134  double beta_re = m_tau[re(r)] * va_re + m_tau[im(r)] * va_im;
135  double beta_im = m_tau[re(r)] * va_im - m_tau[im(r)] * va_re;
136  vec[re(r)] -= beta_re;
137  vec[im(r)] -= beta_im;
138  for (int i = r + 1; i < N; ++i) {
139  double vi_re = m_qr[re(i, r)];
140  double vi_im = m_qr[im(i, r)];
141 
142  vec[re(i)] -= beta_re * vi_re - beta_im * vi_im;
143  vec[im(i)] -= beta_re * vi_im + beta_im * vi_re;
144  }
145  }
146 
147  // vec -> R^{-1} vec
148  // Back substitution
149  for (int i = N - 1; i >= 0; --i) {
150  for (int j = i + 1; j < N; ++j) {
151  vec[re(i)] -= m_qr[re(i, j)] * vec[re(j)] - m_qr[im(i, j)] * vec[im(j)];
152  vec[im(i)] -= m_qr[re(i, j)] * vec[im(j)] + m_qr[im(i, j)] * vec[re(j)];
153  }
154  double inv = 1 / m_qr[re(i, i)];
155 
156  vec[re(i)] *= inv;
157  vec[im(i)] *= inv;
158  }
159 }
160 
161 
162 //====================================================================
164 {
165  for (int i = 0; i < size; ++i) {
166  mat[i] = 0;
167  }
168  for (int i = 0; i < N; ++i) {
169  mat[re(i, i)] = 1;
170  }
171 
172  mult_inverse(mat);
173 }
174 
175 
176 //====================================================================
178 {
179  // H^\dag a_j
180  for (int r = 0; r < N; ++r) {
181  for (int j = 0; j < N; ++j) {
182  // va = <v|a_j>
183  double va_re = mat[re(r, j)];
184  double va_im = mat[im(r, j)];
185  for (int i = r + 1; i < N; ++i) {
186  va_re += m_qr[re(i, r)] * mat[re(i, j)] + m_qr[im(i, r)] * mat[im(i, j)];
187  va_im += m_qr[re(i, r)] * mat[im(i, j)] - m_qr[im(i, r)] * mat[re(i, j)];
188  }
189 
190  // beta = tau^* * va
191  // a_j -= bata * v
192  double beta_re = m_tau[re(r)] * va_re + m_tau[im(r)] * va_im;
193  double beta_im = m_tau[re(r)] * va_im - m_tau[im(r)] * va_re;
194  mat[re(r, j)] -= beta_re;
195  mat[im(r, j)] -= beta_im;
196  for (int i = r + 1; i < N; ++i) {
197  double vi_re = m_qr[re(i, r)];
198  double vi_im = m_qr[im(i, r)];
199 
200  mat[re(i, j)] -= beta_re * vi_re - beta_im * vi_im;
201  mat[im(i, j)] -= beta_re * vi_im + beta_im * vi_re;
202  }
203  }
204  }
205 
206  // Back substitution
207  for (int i = N - 1; i >= 0; --i) {
208  for (int r = i + 1; r < N; ++r) {
209  double& qrir_re = m_qr[re(i, r)];
210  double& qrir_im = m_qr[im(i, r)];
211  for (int j = 0; j < N; ++j) {
212  mat[re(i, j)] -= qrir_re * mat[re(r, j)] - qrir_im * mat[im(r, j)];
213  mat[im(i, j)] -= qrir_re * mat[im(r, j)] + qrir_im * mat[re(r, j)];
214  }
215  }
216  for (int j = 0; j < N; ++j) {
217  double inv = 1 / m_qr[re(i, i)];
218 
219  mat[re(i, j)] *= inv;
220  mat[im(i, j)] *= inv;
221  }
222  }
223 }
224 
225 
226 //====================================================================
227 void Decompose_QR_Cmplx::get_Q(double *mat)
228 {
229  for (int i = 0; i < size; ++i) {
230  mat[i] = 0;
231  }
232  for (int i = 0; i < N; ++i) {
233  mat[re(i, i)] = 1;
234  }
235 
236  mult_Q(mat);
237 }
238 
239 
240 //====================================================================
241 void Decompose_QR_Cmplx::get_Qu(double *mat)
242 {
243  get_Q(mat);
244  std::valarray<double> sign(N);
245  for (int i = 0; i < N; ++i) {
246  sign[i] = (m_qr[re(i, i)] < 0) ? -1 : 1;
247  }
248  for (int i = 0; i < N; ++i) {
249  for (int j = 0; j < N; ++j) {
250  mat[re(i, j)] *= sign[j];
251  mat[im(i, j)] *= sign[j];
252  }
253  }
254 }
255 
256 
257 //====================================================================
258 void Decompose_QR_Cmplx::mult_Q(double *mat)
259 {
260  for (int r = N - 1; r >= 0; --r) {
261  for (int j = 0; j < N; ++j) {
262  // vm = <v|m_j>
263  double vm_re = mat[re(r, j)];
264  double vm_im = mat[im(r, j)];
265  for (int i = r + 1; i < N; ++i) {
266  vm_re += m_qr[re(i, r)] * mat[re(i, j)] + m_qr[im(i, r)] * mat[im(i, j)];
267  vm_im += m_qr[re(i, r)] * mat[im(i, j)] - m_qr[im(i, r)] * mat[re(i, j)];
268  }
269 
270  // beta = tau * va
271  // m_j -= beta * v
272  double beta_re = m_tau[re(r)] * vm_re - m_tau[im(r)] * vm_im;
273  double beta_im = m_tau[re(r)] * vm_im + m_tau[im(r)] * vm_re;
274  mat[re(r, j)] -= beta_re;
275  mat[im(r, j)] -= beta_im;
276  for (int i = r + 1; i < N; ++i) {
277  double vi_re = m_qr[re(i, r)];
278  double vi_im = m_qr[im(i, r)];
279  mat[re(i, j)] -= beta_re * vi_re - beta_im * vi_im;
280  mat[im(i, j)] -= beta_re * vi_im + beta_im * vi_re;
281  }
282  }
283  }
284 }
285 
286 
287 //====================================================================
size_t re(const size_t i, const size_t j)
std::valarray< double > m_tau
void mult_inverse(double *mat)
size_t im(const size_t i, const size_t j)
void set_matrix(const double *mat)
void solve(double *vec)
void get_R(double *mat)
void get_Q(double *mat)
std::valarray< double > m_qr
void get_Qu(double *mat)
void mult_Q(double *mat)
void get_inverse(double *mat)