3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 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.
20 /* Author: G. Jungman */
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_vector.h>
26 #include <gsl/gsl_matrix.h>
27 #include <gsl/gsl_linalg.h>
31 /* [Engeln-Mullges + Uhlig, Alg. 4.42]
35 gsl_linalg_HH_solve (gsl_matrix * A, const gsl_vector * b, gsl_vector * x)
37 if (A->size1 > A->size2)
39 /* System is underdetermined. */
41 GSL_ERROR ("System is underdetermined", GSL_EINVAL);
43 else if (A->size2 != x->size)
45 GSL_ERROR ("matrix and vector sizes must be equal", GSL_EBADLEN);
51 gsl_vector_memcpy (x, b);
53 status = gsl_linalg_HH_svx (A, x);
60 gsl_linalg_HH_svx (gsl_matrix * A, gsl_vector * x)
62 if (A->size1 > A->size2)
64 /* System is underdetermined. */
66 GSL_ERROR ("System is underdetermined", GSL_EINVAL);
68 else if (A->size2 != x->size)
70 GSL_ERROR ("matrix and vector sizes must be equal", GSL_EBADLEN);
74 const size_t N = A->size1;
75 const size_t M = A->size2;
77 REAL *d = (REAL *) malloc (N * sizeof (REAL));
81 GSL_ERROR ("could not allocate memory for workspace", GSL_ENOMEM);
84 /* Perform Householder transformation. */
86 for (i = 0; i < N; i++)
88 const REAL aii = gsl_matrix_get (A, i, i);
95 for (k = i; k < M; k++)
97 REAL aki = gsl_matrix_get (A, k, i);
103 /* Rank of matrix is less than size1. */
105 GSL_ERROR ("matrix is rank deficient", GSL_ESING);
108 alpha = sqrt (r) * GSL_SIGN (aii);
110 ak = 1.0 / (r + alpha * aii);
111 gsl_matrix_set (A, i, i, aii + alpha);
115 for (k = i + 1; k < N; k++)
119 for (j = i; j < M; j++)
121 REAL ajk = gsl_matrix_get (A, j, k);
122 REAL aji = gsl_matrix_get (A, j, i);
126 max_norm = GSL_MAX (max_norm, norm);
130 for (j = i; j < M; j++)
132 REAL ajk = gsl_matrix_get (A, j, k);
133 REAL aji = gsl_matrix_get (A, j, i);
134 gsl_matrix_set (A, j, k, ajk - f * aji);
138 if (fabs (alpha) < 2.0 * GSL_DBL_EPSILON * sqrt (max_norm))
140 /* Apparent singularity. */
142 GSL_ERROR("apparent singularity detected", GSL_ESING);
145 /* Perform update of RHS. */
148 for (j = i; j < M; j++)
150 f += gsl_vector_get (x, j) * gsl_matrix_get (A, j, i);
153 for (j = i; j < M; j++)
155 REAL xj = gsl_vector_get (x, j);
156 REAL aji = gsl_matrix_get (A, j, i);
157 gsl_vector_set (x, j, xj - f * aji);
161 /* Perform back-substitution. */
163 for (i = N; i > 0 && i--;)
165 REAL xi = gsl_vector_get (x, i);
167 for (k = i + 1; k < N; k++)
169 sum += gsl_matrix_get (A, i, k) * gsl_vector_get (x, k);
172 gsl_vector_set (x, i, (xi - sum) / d[i]);