1 /* linalg/householder.c
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004, 2007 Gerard Jungman, Brian Gough
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <gsl/gsl_math.h>
23 #include <gsl/gsl_vector.h>
24 #include <gsl/gsl_matrix.h>
25 #include <gsl/gsl_blas.h>
27 #include <gsl/gsl_linalg.h>
30 gsl_linalg_householder_transform (gsl_vector * v)
32 /* replace v[0:n-1] with a householder vector (v[0:n-1]) and
33 coefficient tau that annihilate v[1:n-1] */
35 const size_t n = v->size ;
39 return 0.0; /* tau = 0 */
43 double alpha, beta, tau ;
45 gsl_vector_view x = gsl_vector_subvector (v, 1, n - 1) ;
47 double xnorm = gsl_blas_dnrm2 (&x.vector);
51 return 0.0; /* tau = 0 */
54 alpha = gsl_vector_get (v, 0) ;
55 beta = - (alpha >= 0.0 ? +1.0 : -1.0) * hypot(alpha, xnorm) ;
56 tau = (beta - alpha) / beta ;
58 gsl_blas_dscal (1.0 / (alpha - beta), &x.vector);
59 gsl_vector_set (v, 0, beta) ;
66 gsl_linalg_householder_hm (double tau, const gsl_vector * v, gsl_matrix * A)
68 /* applies a householder transformation v,tau to matrix m */
77 gsl_vector_const_view v1 = gsl_vector_const_subvector (v, 1, v->size - 1);
78 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 1, 0, A->size1 - 1, A->size2);
81 for (j = 0; j < A->size2; j++)
84 gsl_vector_view A1j = gsl_matrix_column(&A1.matrix, j);
85 gsl_blas_ddot (&A1j.vector, &v1.vector, &wj);
86 wj += gsl_matrix_get(A,0,j);
89 double A0j = gsl_matrix_get (A, 0, j);
90 gsl_matrix_set (A, 0, j, A0j - tau * wj);
93 gsl_blas_daxpy (-tau * wj, &v1.vector, &A1j.vector);
100 for (j = 0; j < A->size2; j++)
102 /* Compute wj = Akj vk */
104 double wj = gsl_matrix_get(A,0,j);
106 for (i = 1; i < A->size1; i++) /* note, computed for v(0) = 1 above */
108 wj += gsl_matrix_get(A,i,j) * gsl_vector_get(v,i);
111 /* Aij = Aij - tau vi wj */
115 double A0j = gsl_matrix_get (A, 0, j);
116 gsl_matrix_set (A, 0, j, A0j - tau * wj);
121 for (i = 1; i < A->size1; i++)
123 double Aij = gsl_matrix_get (A, i, j);
124 double vi = gsl_vector_get (v, i);
125 gsl_matrix_set (A, i, j, Aij - tau * vi * wj);
135 gsl_linalg_householder_mh (double tau, const gsl_vector * v, gsl_matrix * A)
137 /* applies a householder transformation v,tau to matrix m from the
138 right hand side in order to zero out rows */
143 /* A = A - tau w v' */
147 gsl_vector_const_view v1 = gsl_vector_const_subvector (v, 1, v->size - 1);
148 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 0, 1, A->size1, A->size2-1);
151 for (i = 0; i < A->size1; i++)
154 gsl_vector_view A1i = gsl_matrix_row(&A1.matrix, i);
155 gsl_blas_ddot (&A1i.vector, &v1.vector, &wi);
156 wi += gsl_matrix_get(A,i,0);
159 double Ai0 = gsl_matrix_get (A, i, 0);
160 gsl_matrix_set (A, i, 0, Ai0 - tau * wi);
163 gsl_blas_daxpy(-tau * wi, &v1.vector, &A1i.vector);
170 for (i = 0; i < A->size1; i++)
172 double wi = gsl_matrix_get(A,i,0);
174 for (j = 1; j < A->size2; j++) /* note, computed for v(0) = 1 above */
176 wi += gsl_matrix_get(A,i,j) * gsl_vector_get(v,j);
182 double Ai0 = gsl_matrix_get (A, i, 0);
183 gsl_matrix_set (A, i, 0, Ai0 - tau * wi);
188 for (j = 1; j < A->size2; j++)
190 double vj = gsl_vector_get (v, j);
191 double Aij = gsl_matrix_get (A, i, j);
192 gsl_matrix_set (A, i, j, Aij - tau * wi * vj);
202 gsl_linalg_householder_hv (double tau, const gsl_vector * v, gsl_vector * w)
204 /* applies a householder transformation v to vector w */
205 const size_t N = v->size;
211 /* compute d = v'w */
213 double d0 = gsl_vector_get(w,0);
216 gsl_vector_const_view v1 = gsl_vector_const_subvector(v, 1, N-1);
217 gsl_vector_view w1 = gsl_vector_subvector(w, 1, N-1);
219 gsl_blas_ddot (&v1.vector, &w1.vector, &d1);
223 /* compute w = w - tau (v) (v'w) */
226 double w0 = gsl_vector_get (w,0);
227 gsl_vector_set (w, 0, w0 - tau * d);
230 gsl_blas_daxpy (-tau * d, &v1.vector, &w1.vector);
238 gsl_linalg_householder_hm1 (double tau, gsl_matrix * A)
240 /* applies a householder transformation v,tau to a matrix being
241 build up from the identity matrix, using the first column of A as
242 a householder vector */
248 gsl_matrix_set (A, 0, 0, 1.0);
250 for (j = 1; j < A->size2; j++)
252 gsl_matrix_set (A, 0, j, 0.0);
255 for (i = 1; i < A->size1; i++)
257 gsl_matrix_set (A, i, 0, 0.0);
267 gsl_matrix_view A1 = gsl_matrix_submatrix (A, 1, 0, A->size1 - 1, A->size2);
268 gsl_vector_view v1 = gsl_matrix_column (&A1.matrix, 0);
271 for (j = 1; j < A->size2; j++)
273 double wj = 0.0; /* A0j * v0 */
275 gsl_vector_view A1j = gsl_matrix_column(&A1.matrix, j);
276 gsl_blas_ddot (&A1j.vector, &v1.vector, &wj);
278 /* A = A - tau v w' */
280 gsl_matrix_set (A, 0, j, - tau * wj);
282 gsl_blas_daxpy(-tau*wj, &v1.vector, &A1j.vector);
285 gsl_blas_dscal(-tau, &v1.vector);
287 gsl_matrix_set (A, 0, 0, 1.0 - tau);
293 for (j = 1; j < A->size2; j++)
295 double wj = 0.0; /* A0j * v0 */
297 for (i = 1; i < A->size1; i++)
299 double vi = gsl_matrix_get(A, i, 0);
300 wj += gsl_matrix_get(A,i,j) * vi;
303 /* A = A - tau v w' */
305 gsl_matrix_set (A, 0, j, - tau * wj);
307 for (i = 1; i < A->size1; i++)
309 double vi = gsl_matrix_get (A, i, 0);
310 double Aij = gsl_matrix_get (A, i, j);
311 gsl_matrix_set (A, i, j, Aij - tau * vi * wj);
315 for (i = 1; i < A->size1; i++)
317 double vi = gsl_matrix_get(A, i, 0);
318 gsl_matrix_set(A, i, 0, -tau * vi);
321 gsl_matrix_set (A, 0, 0, 1.0 - tau);