39 #ifndef GMM_DENSE_HOUSEHOLDER_H
40 #define GMM_DENSE_HOUSEHOLDER_H
51 template <
typename Matrix,
typename VecX,
typename VecY>
52 inline void rank_one_update(Matrix &A,
const VecX& x,
53 const VecY& y, row_major) {
54 typedef typename linalg_traits<Matrix>::value_type T;
56 GMM_ASSERT2(N <= vect_size(x) && mat_ncols(A) <= vect_size(y),
57 "dimensions mismatch");
58 typename linalg_traits<VecX>::const_iterator itx = vect_const_begin(x);
59 for (
size_type i = 0; i < N; ++i, ++itx) {
60 typedef typename linalg_traits<Matrix>::sub_row_type row_type;
61 row_type row = mat_row(A, i);
62 typename linalg_traits<typename org_type<row_type>::t>::iterator
63 it = vect_begin(row), ite = vect_end(row);
64 typename linalg_traits<VecY>::const_iterator ity = vect_const_begin(y);
66 for (; it != ite; ++it, ++ity) *it += conj_product(*ity, tx);
70 template <
typename Matrix,
typename VecX,
typename VecY>
71 inline void rank_one_update(Matrix &A,
const VecX& x,
72 const VecY& y, col_major) {
73 typedef typename linalg_traits<Matrix>::value_type T;
75 GMM_ASSERT2(mat_nrows(A) <= vect_size(x) && M <= vect_size(y),
76 "dimensions mismatch");
77 typename linalg_traits<VecY>::const_iterator ity = vect_const_begin(y);
78 for (
size_type i = 0; i < M; ++i, ++ity) {
79 typedef typename linalg_traits<Matrix>::sub_col_type col_type;
80 col_type col = mat_col(A, i);
81 typename linalg_traits<typename org_type<col_type>::t>::iterator
82 it = vect_begin(col), ite = vect_end(col);
83 typename linalg_traits<VecX>::const_iterator itx = vect_const_begin(x);
85 for (; it != ite; ++it, ++itx) *it += conj_product(ty, *itx);
90 template <
typename Matrix,
typename VecX,
typename VecY>
91 inline void rank_one_update(
const Matrix &AA,
const VecX& x,
93 Matrix& A =
const_cast<Matrix&
>(AA);
94 rank_one_update(A, x, y,
typename principal_orientation_type<
typename
95 linalg_traits<Matrix>::sub_orientation>::potype());
103 template <
typename Matrix,
typename VecX,
typename VecY>
104 inline void rank_two_update(Matrix &A,
const VecX& x,
105 const VecY& y, row_major) {
106 typedef typename linalg_traits<Matrix>::value_type value_type;
108 GMM_ASSERT2(N <= vect_size(x) && mat_ncols(A) <= vect_size(y),
109 "dimensions mismatch");
110 typename linalg_traits<VecX>::const_iterator itx1 = vect_const_begin(x);
111 typename linalg_traits<VecY>::const_iterator ity2 = vect_const_begin(y);
112 for (
size_type i = 0; i < N; ++i, ++itx1, ++ity2) {
113 typedef typename linalg_traits<Matrix>::sub_row_type row_type;
114 row_type row = mat_row(A, i);
115 typename linalg_traits<typename org_type<row_type>::t>::iterator
116 it = vect_begin(row), ite = vect_end(row);
117 typename linalg_traits<VecX>::const_iterator itx2 = vect_const_begin(x);
118 typename linalg_traits<VecY>::const_iterator ity1 = vect_const_begin(y);
119 value_type tx = *itx1, ty = *ity2;
120 for (; it != ite; ++it, ++ity1, ++itx2)
121 *it += conj_product(*ity1, tx) + conj_product(*itx2, ty);
125 template <
typename Matrix,
typename VecX,
typename VecY>
126 inline void rank_two_update(Matrix &A,
const VecX& x,
127 const VecY& y, col_major) {
128 typedef typename linalg_traits<Matrix>::value_type value_type;
130 GMM_ASSERT2(mat_nrows(A) <= vect_size(x) && M <= vect_size(y),
131 "dimensions mismatch");
132 typename linalg_traits<VecX>::const_iterator itx2 = vect_const_begin(x);
133 typename linalg_traits<VecY>::const_iterator ity1 = vect_const_begin(y);
134 for (
size_type i = 0; i < M; ++i, ++ity1, ++itx2) {
135 typedef typename linalg_traits<Matrix>::sub_col_type col_type;
136 col_type col = mat_col(A, i);
137 typename linalg_traits<typename org_type<col_type>::t>::iterator
138 it = vect_begin(col), ite = vect_end(col);
139 typename linalg_traits<VecX>::const_iterator itx1 = vect_const_begin(x);
140 typename linalg_traits<VecY>::const_iterator ity2 = vect_const_begin(y);
141 value_type ty = *ity1, tx = *itx2;
142 for (; it != ite; ++it, ++itx1, ++ity2)
143 *it += conj_product(ty, *itx1) + conj_product(tx, *ity2);
148 template <
typename Matrix,
typename VecX,
typename VecY>
149 inline void rank_two_update(
const Matrix &AA,
const VecX& x,
151 Matrix& A =
const_cast<Matrix&
>(AA);
152 rank_two_update(A, x, y,
typename principal_orientation_type<
typename
153 linalg_traits<Matrix>::sub_orientation>::potype());
161 template <
typename VECT>
void house_vector(
const VECT &VV) {
162 VECT &V =
const_cast<VECT &
>(VV);
163 typedef typename linalg_traits<VECT>::value_type T;
164 typedef typename number_traits<T>::magnitude_type R;
166 R mu =
vect_norm2(V), abs_v0 = gmm::abs(V[0]);
168 gmm::scale(V, (abs_v0 == R(0)) ? T(R(1) / mu)
169 : (safe_divide(T(abs_v0), V[0]) / (abs_v0 + mu)));
170 if (gmm::real(V[vect_size(V)-1]) * R(0) != R(0))
gmm::clear(V);
174 template <
typename VECT>
void house_vector_last(
const VECT &VV) {
175 VECT &V =
const_cast<VECT &
>(VV);
176 typedef typename linalg_traits<VECT>::value_type T;
177 typedef typename number_traits<T>::magnitude_type R;
180 R mu =
vect_norm2(V), abs_v0 = gmm::abs(V[m-1]);
182 gmm::scale(V, (abs_v0 == R(0)) ? T(R(1) / mu)
183 : ((abs_v0 / V[m-1]) / (abs_v0 + mu)));
184 if (gmm::real(V[0]) * R(0) != R(0))
gmm::clear(V);
193 template <
typename MAT,
typename VECT1,
typename VECT2>
inline
194 void row_house_update(
const MAT &AA,
const VECT1 &V,
const VECT2 &WW) {
195 VECT2 &W =
const_cast<VECT2 &
>(WW); MAT &A =
const_cast<MAT &
>(AA);
196 typedef typename linalg_traits<MAT>::value_type value_type;
197 typedef typename number_traits<value_type>::magnitude_type magnitude_type;
201 rank_one_update(A, V, W);
205 template <
typename MAT,
typename VECT1,
typename VECT2>
inline
206 void col_house_update(
const MAT &AA,
const VECT1 &V,
const VECT2 &WW) {
207 VECT2 &W =
const_cast<VECT2 &
>(WW); MAT &A =
const_cast<MAT &
>(AA);
208 typedef typename linalg_traits<MAT>::value_type value_type;
209 typedef typename number_traits<value_type>::magnitude_type magnitude_type;
213 rank_one_update(A, W, V);
222 template <
typename MAT1,
typename MAT2>
223 void Hessenberg_reduction(
const MAT1& AA,
const MAT2 &QQ,
bool compute_Q){
224 MAT1& A =
const_cast<MAT1&
>(AA); MAT2& Q =
const_cast<MAT2&
>(QQ);
225 typedef typename linalg_traits<MAT1>::value_type value_type;
226 if (compute_Q) gmm::copy(identity_matrix(), Q);
227 size_type n = mat_nrows(A);
if (n < 2)
return;
228 std::vector<value_type> v(n), w(n);
229 sub_interval SUBK(0,n);
231 sub_interval SUBI(k, n-k), SUBJ(k-1,n-k+1);
233 for (
size_type j = k; j < n; ++j) v[j-k] = A(j, k-1);
235 row_house_update(sub_matrix(A, SUBI, SUBJ), v, sub_vector(w, SUBJ));
236 col_house_update(sub_matrix(A, SUBK, SUBI), v, w);
238 if (compute_Q) col_house_update(sub_matrix(Q, SUBK, SUBI), v, w);
246 template <
typename MAT1,
typename MAT2>
247 void Householder_tridiagonalization(
const MAT1 &AA,
const MAT2 &QQ,
249 MAT1 &A =
const_cast<MAT1 &
>(AA); MAT2 &Q =
const_cast<MAT2 &
>(QQ);
250 typedef typename linalg_traits<MAT1>::value_type T;
251 typedef typename number_traits<T>::magnitude_type R;
253 size_type n = mat_nrows(A);
if (n < 2)
return;
254 std::vector<T> v(n), p(n), w(n), ww(n);
255 sub_interval SUBK(0,n);
258 sub_interval SUBI(k, n-k);
259 v.resize(n-k); p.resize(n-k); w.resize(n-k);
261 { v[l-k] = w[l-k] = A(l, k-1); A(l, k-1) = A(k-1, l) = T(0); }
264 A(k-1, k) = gmm::conj(A(k, k-1) = w[0] - T(2)*v[0]*
vect_hp(w, v)/norm);
266 gmm::mult(sub_matrix(A, SUBI), gmm::scaled(v, T(-2) / norm), p);
267 gmm::add(p, gmm::scaled(v, -
vect_hp(v, p) / norm), w);
268 rank_two_update(sub_matrix(A, SUBI), v, w);
271 if (compute_q) col_house_update(sub_matrix(Q, SUBK, SUBI), v, ww);
279 template <
typename T>
void Givens_rotation(T a, T b, T &c, T &s) {
280 typedef typename number_traits<T>::magnitude_type R;
281 R aa = gmm::abs(a), bb = gmm::abs(b);
282 if (bb == R(0)) { c = T(1); s = T(0);
return; }
283 if (aa == R(0)) { c = T(0); s = b / bb;
return; }
285 { T t = -safe_divide(a,b); s = T(R(1) / (sqrt(R(1)+gmm::abs_sqr(t)))); c = s * t; }
287 { T t = -safe_divide(b,a); c = T(R(1) / (sqrt(R(1)+gmm::abs_sqr(t)))); s = c * t; }
291 template <
typename T>
inline
292 void Apply_Givens_rotation_left(T &x, T &y, T c, T s)
293 { T t1=x, t2=y; x = gmm::conj(c)*t1 - gmm::conj(s)*t2; y = c*t2 + s*t1; }
296 template <
typename T>
inline
297 void Apply_Givens_rotation_right(T &x, T &y, T c, T s)
298 { T t1=x, t2=y; x = c*t1 - s*t2; y = gmm::conj(c)*t2 + gmm::conj(s)*t1; }
300 template <
typename MAT,
typename T>
302 MAT &A =
const_cast<MAT &
>(AA);
303 for (
size_type j = 0; j < mat_ncols(A); ++j)
304 Apply_Givens_rotation_left(A(i,j), A(k,j), c, s);
307 template <
typename MAT,
typename T>
309 MAT &A =
const_cast<MAT &
>(AA);
310 for (
size_type j = 0; j < mat_nrows(A); ++j)
311 Apply_Givens_rotation_right(A(j,i), A(j,k), c, s);