⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svd.c

📁 该文件为c++的数学函数库!是一个非常有用的编程工具.它含有各种数学函数,为科学计算、工程应用等程序编写提供方便!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* linalg/svd.c *  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman, Brian Gough *  * 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <config.h>#include <stdlib.h>#include <string.h>#include <gsl/gsl_math.h>#include <gsl/gsl_vector.h>#include <gsl/gsl_matrix.h>#include <gsl/gsl_blas.h>#include <gsl/gsl_linalg.h>#include "givens.c"#include "svdstep.c"/* Factorise a general M x N matrix A into, * *   A = U D V^T * * where U is a column-orthogonal M x N matrix (U^T U = I),  * D is a diagonal N x N matrix,  * and V is an N x N orthogonal matrix (V^T V = V V^T = I) * * U is stored in the original matrix A, which has the same size * * V is stored as a separate matrix (not V^T). You must take the * transpose to form the product above. * * The diagonal matrix D is stored in the vector S,  D_ii = S_i */intgsl_linalg_SV_decomp (gsl_matrix * A, gsl_matrix * V, gsl_vector * S,                       gsl_vector * work){  size_t a, b, i, j;  const size_t M = A->size1;  const size_t N = A->size2;  const size_t K = GSL_MIN (M, N);  if (M < N)    {      GSL_ERROR ("svd of MxN matrix, M<N, is not implemented", GSL_EUNIMPL);    }  else if (V->size1 != N)    {      GSL_ERROR ("square matrix V must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (V->size1 != V->size2)    {      GSL_ERROR ("matrix V must be square", GSL_ENOTSQR);    }  else if (S->size != N)    {      GSL_ERROR ("length of vector S must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (work->size != N)    {      GSL_ERROR ("length of workspace must match second dimension of matrix A",                 GSL_EBADLEN);    }    {    gsl_vector_view f = gsl_vector_subvector (work, 0, K - 1);        /* bidiagonalize matrix A, unpack A into U S V */        gsl_linalg_bidiag_decomp (A, S, &f.vector);    gsl_linalg_bidiag_unpack2 (A, S, &f.vector, V);        /* apply reduction steps to B=(S,Sd) */        chop_small_elements (S, &f.vector);        /* Progressively reduce the matrix until it is diagonal */        b = N - 1;        while (b > 0)      {        if (gsl_vector_get (&f.vector, b - 1) == 0.0)          {            b--;            continue;          }                /* Find the largest unreduced block (a,b) starting from b           and working backwards */                a = b - 1;                while (a > 0)          {            if (gsl_vector_get (&f.vector, a - 1) == 0.0)              {                break;              }                        a--;          }                {          const size_t n_block = b - a + 1;          gsl_vector_view S_block = gsl_vector_subvector (S, a, n_block);          gsl_vector_view f_block = gsl_vector_subvector (&f.vector, a, n_block - 1);                    gsl_matrix_view U_block =            gsl_matrix_submatrix (A, 0, a, A->size1, n_block);          gsl_matrix_view V_block =            gsl_matrix_submatrix (V, 0, a, V->size1, n_block);                    qrstep (&S_block.vector, &f_block.vector, &U_block.matrix, &V_block.matrix);                    /* remove any small off-diagonal elements */                    chop_small_elements (&S_block.vector, &f_block.vector);        }      }  }  /* Make singular values positive by reflections if necessary */    for (j = 0; j < K; j++)    {      double Sj = gsl_vector_get (S, j);            if (Sj < 0.0)        {          for (i = 0; i < N; i++)            {              double Vij = gsl_matrix_get (V, i, j);              gsl_matrix_set (V, i, j, -Vij);            }                    gsl_vector_set (S, j, -Sj);        }    }    /* Sort singular values into decreasing order */    for (i = 0; i < K; i++)    {      double S_max = gsl_vector_get (S, i);      size_t i_max = i;            for (j = i + 1; j < K; j++)        {          double Sj = gsl_vector_get (S, j);                    if (Sj > S_max)            {              S_max = Sj;              i_max = j;            }        }            if (i_max != i)        {          /* swap eigenvalues */          gsl_vector_swap_elements (S, i, i_max);                    /* swap eigenvectors */          gsl_matrix_swap_columns (A, i, i_max);          gsl_matrix_swap_columns (V, i, i_max);        }    }    return GSL_SUCCESS;}/* Modified algorithm which is better for M>>N */intgsl_linalg_SV_decomp_mod (gsl_matrix * A,                          gsl_matrix * X,                          gsl_matrix * V, gsl_vector * S, gsl_vector * work){  size_t i, j;  const size_t M = A->size1;  const size_t N = A->size2;  if (M < N)    {      GSL_ERROR ("svd of MxN matrix, M<N, is not implemented", GSL_EUNIMPL);    }  else if (V->size1 != N)    {      GSL_ERROR ("square matrix V must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (V->size1 != V->size2)    {      GSL_ERROR ("matrix V must be square", GSL_ENOTSQR);    }  else if (X->size1 != N)    {      GSL_ERROR ("square matrix X must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (X->size1 != X->size2)    {      GSL_ERROR ("matrix X must be square", GSL_ENOTSQR);    }  else if (S->size != N)    {      GSL_ERROR ("length of vector S must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (work->size != N)    {      GSL_ERROR ("length of workspace must match second dimension of matrix A",                 GSL_EBADLEN);    }  /* Convert A into an upper triangular matrix R */  for (i = 0; i < N; i++)    {      gsl_vector_view c = gsl_matrix_column (A, i);      gsl_vector_view v = gsl_vector_subvector (&c.vector, i, M - i);      double tau_i = gsl_linalg_householder_transform (&v.vector);      /* Apply the transformation to the remaining columns */      if (i + 1 < N)        {          gsl_matrix_view m =            gsl_matrix_submatrix (A, i, i + 1, M - i, N - (i + 1));          gsl_linalg_householder_hm (tau_i, &v.vector, &m.matrix);        }      gsl_vector_set (S, i, tau_i);    }  /* Copy the upper triangular part of A into X */  for (i = 0; i < N; i++)    {      for (j = 0; j < i; j++)        {          gsl_matrix_set (X, i, j, 0.0);        }      {        double Aii = gsl_matrix_get (A, i, i);        gsl_matrix_set (X, i, i, Aii);      }      for (j = i + 1; j < N; j++)        {          double Aij = gsl_matrix_get (A, i, j);          gsl_matrix_set (X, i, j, Aij);        }    }  /* Convert A into an orthogonal matrix L */  for (j = N; j > 0 && j--;)    {      /* Householder column transformation to accumulate L */      double tj = gsl_vector_get (S, j);      gsl_matrix_view m = gsl_matrix_submatrix (A, j, j, M - j, N - j);      gsl_linalg_householder_hm1 (tj, &m.matrix);    }  /* unpack R into X V S */  gsl_linalg_SV_decomp (X, V, S, work);  /* Multiply L by X, to obtain U = L X, stored in U */

⌨️ 快捷键说明

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