3 * Copyright (C) 2007 Patrick Alken
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.
21 #include <gsl/gsl_matrix.h>
22 #include <gsl/gsl_vector.h>
23 #include <gsl/gsl_linalg.h>
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_complex.h>
26 #include <gsl/gsl_complex_math.h>
27 #include <gsl/gsl_blas.h>
28 #include <gsl/gsl_errno.h>
31 * This module contains routines related to the Cholesky decomposition
32 * of a complex Hermitian positive definite matrix.
35 static void cholesky_complex_conj_vector(gsl_vector_complex *v);
38 gsl_linalg_complex_cholesky_decomp()
39 Perform the Cholesky decomposition on a Hermitian positive definite
40 matrix. See Golub & Van Loan, "Matrix Computations" (3rd ed),
43 Inputs: A - (input/output) complex postive definite matrix
45 Return: success or error
47 The lower triangle of A is overwritten with the Cholesky decomposition
51 gsl_linalg_complex_cholesky_decomp(gsl_matrix_complex *A)
53 const size_t N = A->size1;
57 GSL_ERROR("cholesky decomposition requires square matrix", GSL_ENOTSQR);
65 for (j = 0; j < N; ++j)
67 z = gsl_matrix_complex_get(A, j, j);
72 gsl_vector_complex_const_view aj =
73 gsl_matrix_complex_const_subrow(A, j, 0, j);
75 gsl_blas_zdotc(&aj.vector, &aj.vector, &z);
81 GSL_ERROR("matrix is not positive definite", GSL_EDOM);
85 GSL_SET_COMPLEX(&z, ajj, 0.0);
86 gsl_matrix_complex_set(A, j, j, z);
90 gsl_vector_complex_view av =
91 gsl_matrix_complex_subcolumn(A, j, j + 1, N - j - 1);
95 gsl_vector_complex_view aj =
96 gsl_matrix_complex_subrow(A, j, 0, j);
97 gsl_matrix_complex_view am =
98 gsl_matrix_complex_submatrix(A, j + 1, 0, N - j - 1, j);
100 cholesky_complex_conj_vector(&aj.vector);
102 gsl_blas_zgemv(CblasNoTrans,
109 cholesky_complex_conj_vector(&aj.vector);
112 gsl_blas_zdscal(1.0 / ajj, &av.vector);
116 /* Now store L^H in upper triangle */
117 for (i = 1; i < N; ++i)
119 for (j = 0; j < i; ++j)
121 z = gsl_matrix_complex_get(A, i, j);
122 gsl_matrix_complex_set(A, j, i, gsl_complex_conjugate(z));
128 } /* gsl_linalg_complex_cholesky_decomp() */
131 gsl_linalg_complex_cholesky_solve()
132 Solve A x = b where A is in cholesky form
136 gsl_linalg_complex_cholesky_solve (const gsl_matrix_complex * cholesky,
137 const gsl_vector_complex * b,
138 gsl_vector_complex * x)
140 if (cholesky->size1 != cholesky->size2)
142 GSL_ERROR ("cholesky matrix must be square", GSL_ENOTSQR);
144 else if (cholesky->size1 != b->size)
146 GSL_ERROR ("matrix size must match b size", GSL_EBADLEN);
148 else if (cholesky->size2 != x->size)
150 GSL_ERROR ("matrix size must match solution size", GSL_EBADLEN);
154 gsl_vector_complex_memcpy (x, b);
156 /* solve for y using forward-substitution, L y = b */
158 gsl_blas_ztrsv (CblasLower, CblasNoTrans, CblasNonUnit, cholesky, x);
160 /* perform back-substitution, L^H x = y */
162 gsl_blas_ztrsv (CblasLower, CblasConjTrans, CblasNonUnit, cholesky, x);
166 } /* gsl_linalg_complex_cholesky_solve() */
169 gsl_linalg_complex_cholesky_svx()
170 Solve A x = b in place where A is in cholesky form
174 gsl_linalg_complex_cholesky_svx (const gsl_matrix_complex * cholesky,
175 gsl_vector_complex * x)
177 if (cholesky->size1 != cholesky->size2)
179 GSL_ERROR ("cholesky matrix must be square", GSL_ENOTSQR);
181 else if (cholesky->size2 != x->size)
183 GSL_ERROR ("matrix size must match solution size", GSL_EBADLEN);
187 /* solve for y using forward-substitution, L y = b */
189 gsl_blas_ztrsv (CblasLower, CblasNoTrans, CblasNonUnit, cholesky, x);
191 /* perform back-substitution, L^H x = y */
193 gsl_blas_ztrsv (CblasLower, CblasConjTrans, CblasNonUnit, cholesky, x);
197 } /* gsl_linalg_complex_cholesky_svx() */
199 /********************************************
200 * INTERNAL ROUTINES *
201 ********************************************/
204 cholesky_complex_conj_vector(gsl_vector_complex *v)
208 for (i = 0; i < v->size; ++i)
210 gsl_complex z = gsl_vector_complex_get(v, i);
211 gsl_vector_complex_set(v, i, gsl_complex_conjugate(z));
213 } /* cholesky_complex_conj_vector() */