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

📄 svd.c

📁 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY without ev
💻 C
📖 第 1 页 / 共 2 页
字号:
        }    }  /* 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 */  {    gsl_vector_view sum = gsl_vector_subvector (work, 0, N);    for (i = 0; i < M; i++)      {        gsl_vector_view L_i = gsl_matrix_row (A, i);        gsl_vector_set_zero (&sum.vector);        for (j = 0; j < N; j++)          {            double Lij = gsl_vector_get (&L_i.vector, j);            gsl_vector_view X_j = gsl_matrix_row (X, j);            gsl_blas_daxpy (Lij, &X_j.vector, &sum.vector);          }        gsl_vector_memcpy (&L_i.vector, &sum.vector);      }  }  return GSL_SUCCESS;}/*  Solves the system A x = b using the SVD factorization * *  A = U S V^T * *  to obtain x. For M x N systems it finds the solution in the least *  squares sense.   */intgsl_linalg_SV_solve (const gsl_matrix * U,                     const gsl_matrix * V,                     const gsl_vector * S,                     const gsl_vector * b, gsl_vector * x){  if (U->size1 != b->size)    {      GSL_ERROR ("first dimension of matrix U must size of vector b",                 GSL_EBADLEN);    }  else if (U->size2 != S->size)    {      GSL_ERROR ("length of vector S must match second dimension of matrix U",                 GSL_EBADLEN);    }  else if (V->size1 != V->size2)    {      GSL_ERROR ("matrix V must be square", GSL_ENOTSQR);    }  else if (S->size != V->size1)    {      GSL_ERROR ("length of vector S must match size of matrix V",                 GSL_EBADLEN);    }  else if (V->size2 != x->size)    {      GSL_ERROR ("size of matrix V must match size of vector x", GSL_EBADLEN);    }  else    {      const size_t N = U->size2;      size_t i;      gsl_vector *w = gsl_vector_calloc (N);      gsl_blas_dgemv (CblasTrans, 1.0, U, b, 0.0, w);      for (i = 0; i < N; i++)        {          double wi = gsl_vector_get (w, i);          double alpha = gsl_vector_get (S, i);          if (alpha != 0)            alpha = 1.0 / alpha;          gsl_vector_set (w, i, alpha * wi);        }      gsl_blas_dgemv (CblasNoTrans, 1.0, V, w, 0.0, x);      gsl_vector_free (w);      return GSL_SUCCESS;    }}/* This is a the jacobi version *//* Author:  G. Jungman *//* * Algorithm due to J.C. Nash, Compact Numerical Methods for * Computers (New York: Wiley and Sons, 1979), chapter 3. * See also Algorithm 4.1 in * James Demmel, Kresimir Veselic, "Jacobi's Method is more * accurate than QR", Lapack Working Note 15 (LAWN15), October 1989. * Available from netlib. * * Based on code by Arthur Kosowsky, Rutgers University *                  kosowsky@physics.rutgers.edu   * * Another relevant paper is, P.P.M. De Rijk, "A One-Sided Jacobi * Algorithm for computing the singular value decomposition on a * vector computer", SIAM Journal of Scientific and Statistical * Computing, Vol 10, No 2, pp 359-371, March 1989. *  */intgsl_linalg_SV_decomp_jacobi (gsl_matrix * A, gsl_matrix * Q, gsl_vector * S){  if (A->size1 < A->size2)    {      /* FIXME: only implemented  M>=N case so far */      GSL_ERROR ("svd of MxN matrix, M<N, is not implemented", GSL_EUNIMPL);    }  else if (Q->size1 != A->size2)    {      GSL_ERROR ("square matrix Q must match second dimension of matrix A",                 GSL_EBADLEN);    }  else if (Q->size1 != Q->size2)    {      GSL_ERROR ("matrix Q must be square", GSL_ENOTSQR);    }  else if (S->size != A->size2)    {      GSL_ERROR ("length of vector S must match second dimension of matrix A",                 GSL_EBADLEN);    }  else    {      const size_t M = A->size1;      const size_t N = A->size2;      size_t i, j, k;      /* Initialize the rotation counter and the sweep counter. */      int count = 1;      int sweep = 0;      int sweepmax = 5*N;      double tolerance = 10 * M * GSL_DBL_EPSILON;      /* Always do at least 12 sweeps. */      sweepmax = GSL_MAX (sweepmax, 12);      /* Set Q to the identity matrix. */      gsl_matrix_set_identity (Q);      /* Store the column error estimates in S, for use during the         orthogonalization */      for (j = 0; j < N; j++)        {          gsl_vector_view cj = gsl_matrix_column (A, j);          double sj = gsl_blas_dnrm2 (&cj.vector);          gsl_vector_set(S, j, GSL_DBL_EPSILON * sj);        }          /* Orthogonalize A by plane rotations. */      while (count > 0 && sweep <= sweepmax)        {          /* Initialize rotation counter. */          count = N * (N - 1) / 2;          for (j = 0; j < N - 1; j++)            {              for (k = j + 1; k < N; k++)                {                  double a = 0.0;                  double b = 0.0;                  double p = 0.0;                  double q = 0.0;                  double cosine, sine;                  double v;                  double abserr_a, abserr_b;                  int sorted, orthog, noisya, noisyb;                  gsl_vector_view cj = gsl_matrix_column (A, j);                  gsl_vector_view ck = gsl_matrix_column (A, k);                  gsl_blas_ddot (&cj.vector, &ck.vector, &p);                  p *= 2.0 ;  /* equation 9a:  p = 2 x.y */                  a = gsl_blas_dnrm2 (&cj.vector);                  b = gsl_blas_dnrm2 (&ck.vector);                  q = a * a - b * b;                  v = hypot(p, q);                  /* test for columns j,k orthogonal, or dominant errors */                  abserr_a = gsl_vector_get(S,j);                  abserr_b = gsl_vector_get(S,k);                  sorted = (gsl_coerce_double(a) >= gsl_coerce_double(b));                  orthog = (fabs (p) <= tolerance * gsl_coerce_double(a * b));                  noisya = (a < abserr_a);                  noisyb = (b < abserr_b);                  if (sorted && (orthog || noisya || noisyb))                    {                      count--;                      continue;                    }                  /* calculate rotation angles */                  if (v == 0 || !sorted)                    {                      cosine = 0.0;                      sine = 1.0;                    }                  else                    {                      cosine = sqrt((v + q) / (2.0 * v));                      sine = p / (2.0 * v * cosine);                    }                  /* apply rotation to A */                  for (i = 0; i < M; i++)                    {                      const double Aik = gsl_matrix_get (A, i, k);                      const double Aij = gsl_matrix_get (A, i, j);                      gsl_matrix_set (A, i, j, Aij * cosine + Aik * sine);                      gsl_matrix_set (A, i, k, -Aij * sine + Aik * cosine);                    }                  gsl_vector_set(S, j, fabs(cosine) * abserr_a + fabs(sine) * abserr_b);                  gsl_vector_set(S, k, fabs(sine) * abserr_a + fabs(cosine) * abserr_b);                  /* apply rotation to Q */                  for (i = 0; i < N; i++)                    {                      const double Qij = gsl_matrix_get (Q, i, j);                      const double Qik = gsl_matrix_get (Q, i, k);                      gsl_matrix_set (Q, i, j, Qij * cosine + Qik * sine);                      gsl_matrix_set (Q, i, k, -Qij * sine + Qik * cosine);                    }                }            }          /* Sweep completed. */          sweep++;        }      /*        * Orthogonalization complete. Compute singular values.       */      {        double prev_norm = -1.0;        for (j = 0; j < N; j++)          {            gsl_vector_view column = gsl_matrix_column (A, j);            double norm = gsl_blas_dnrm2 (&column.vector);            /* Determine if singular value is zero, according to the               criteria used in the main loop above (i.e. comparison               with norm of previous column). */            if (norm == 0.0 || prev_norm == 0.0                 || (j > 0 && norm <= tolerance * prev_norm))              {                gsl_vector_set (S, j, 0.0);     /* singular */                gsl_vector_set_zero (&column.vector);   /* annihilate column */                prev_norm = 0.0;              }            else              {                gsl_vector_set (S, j, norm);    /* non-singular */                gsl_vector_scale (&column.vector, 1.0 / norm);  /* normalize column */                prev_norm = norm;              }          }      }      if (count > 0)        {          /* reached sweep limit */          GSL_ERROR ("Jacobi iterations did not reach desired tolerance",                     GSL_ETOL);        }      return GSL_SUCCESS;    }}

⌨️ 快捷键说明

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