choleskyc.c

来自「math library from gnu」· C语言 代码 · 共 214 行

C
214
字号
/* linalg/choleskyc.c *  * Copyright (C) 2007 Patrick Alken *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or (at * your option) any later version. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */#include <config.h>#include <gsl/gsl_matrix.h>#include <gsl/gsl_vector.h>#include <gsl/gsl_linalg.h>#include <gsl/gsl_math.h>#include <gsl/gsl_complex.h>#include <gsl/gsl_complex_math.h>#include <gsl/gsl_blas.h>#include <gsl/gsl_errno.h>/* * This module contains routines related to the Cholesky decomposition * of a complex Hermitian positive definite matrix. */static void cholesky_complex_conj_vector(gsl_vector_complex *v);/*gsl_linalg_complex_cholesky_decomp()  Perform the Cholesky decomposition on a Hermitian positive definitematrix. See Golub & Van Loan, "Matrix Computations" (3rd ed),algorithm 4.2.2.Inputs: A - (input/output) complex postive definite matrixReturn: success or errorThe lower triangle of A is overwritten with the Cholesky decomposition*/intgsl_linalg_complex_cholesky_decomp(gsl_matrix_complex *A){  const size_t N = A->size1;    if (N != A->size2)    {      GSL_ERROR("cholesky decomposition requires square matrix", GSL_ENOTSQR);    }  else    {      size_t i, j;      gsl_complex z;      double ajj;      for (j = 0; j < N; ++j)        {          z = gsl_matrix_complex_get(A, j, j);          ajj = GSL_REAL(z);          if (j > 0)            {              gsl_vector_complex_const_view aj =                gsl_matrix_complex_const_subrow(A, j, 0, j);              gsl_blas_zdotc(&aj.vector, &aj.vector, &z);              ajj -= GSL_REAL(z);            }          if (ajj <= 0.0)            {              GSL_ERROR("matrix is not positive definite", GSL_EDOM);            }          ajj = sqrt(ajj);          GSL_SET_COMPLEX(&z, ajj, 0.0);          gsl_matrix_complex_set(A, j, j, z);          if (j < N - 1)            {              gsl_vector_complex_view av =                gsl_matrix_complex_subcolumn(A, j, j + 1, N - j - 1);              if (j > 0)                {                  gsl_vector_complex_view aj =                    gsl_matrix_complex_subrow(A, j, 0, j);                  gsl_matrix_complex_view am =                    gsl_matrix_complex_submatrix(A, j + 1, 0, N - j - 1, j);                  cholesky_complex_conj_vector(&aj.vector);                  gsl_blas_zgemv(CblasNoTrans,                                 GSL_COMPLEX_NEGONE,                                 &am.matrix,                                 &aj.vector,                                 GSL_COMPLEX_ONE,                                 &av.vector);                  cholesky_complex_conj_vector(&aj.vector);                }              gsl_blas_zdscal(1.0 / ajj, &av.vector);            }        }      /* Now store L^H in upper triangle */      for (i = 1; i < N; ++i)        {          for (j = 0; j < i; ++j)            {              z = gsl_matrix_complex_get(A, i, j);              gsl_matrix_complex_set(A, j, i, gsl_complex_conjugate(z));            }        }      return GSL_SUCCESS;    }} /* gsl_linalg_complex_cholesky_decomp() *//*gsl_linalg_complex_cholesky_solve()  Solve A x = b where A is in cholesky form*/intgsl_linalg_complex_cholesky_solve (const gsl_matrix_complex * cholesky,                                   const gsl_vector_complex * b,                                   gsl_vector_complex * x){  if (cholesky->size1 != cholesky->size2)    {      GSL_ERROR ("cholesky matrix must be square", GSL_ENOTSQR);    }  else if (cholesky->size1 != b->size)    {      GSL_ERROR ("matrix size must match b size", GSL_EBADLEN);    }  else if (cholesky->size2 != x->size)    {      GSL_ERROR ("matrix size must match solution size", GSL_EBADLEN);    }  else    {      gsl_vector_complex_memcpy (x, b);      /* solve for y using forward-substitution, L y = b */      gsl_blas_ztrsv (CblasLower, CblasNoTrans, CblasNonUnit, cholesky, x);      /* perform back-substitution, L^H x = y */      gsl_blas_ztrsv (CblasLower, CblasConjTrans, CblasNonUnit, cholesky, x);      return GSL_SUCCESS;    }} /* gsl_linalg_complex_cholesky_solve() *//*gsl_linalg_complex_cholesky_svx()  Solve A x = b in place where A is in cholesky form*/intgsl_linalg_complex_cholesky_svx (const gsl_matrix_complex * cholesky,                                 gsl_vector_complex * x){  if (cholesky->size1 != cholesky->size2)    {      GSL_ERROR ("cholesky matrix must be square", GSL_ENOTSQR);    }  else if (cholesky->size2 != x->size)    {      GSL_ERROR ("matrix size must match solution size", GSL_EBADLEN);    }  else    {      /* solve for y using forward-substitution, L y = b */      gsl_blas_ztrsv (CblasLower, CblasNoTrans, CblasNonUnit, cholesky, x);      /* perform back-substitution, L^H x = y */      gsl_blas_ztrsv (CblasLower, CblasConjTrans, CblasNonUnit, cholesky, x);      return GSL_SUCCESS;    }} /* gsl_linalg_complex_cholesky_svx() *//******************************************** *           INTERNAL ROUTINES              * ********************************************/static voidcholesky_complex_conj_vector(gsl_vector_complex *v){  size_t i;  for (i = 0; i < v->size; ++i)    {      gsl_complex z = gsl_vector_complex_get(v, i);      gsl_vector_complex_set(v, i, gsl_complex_conjugate(z));    }} /* cholesky_complex_conj_vector() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?