示例#1
0
CAMLprim value ml_gsl_linalg_bidiag_unpack2(value A, value TAU_U, value TAU_V, value V)
{
  _DECLARE_MATRIX2(A, V);
  _DECLARE_VECTOR2(TAU_U, TAU_V);
  _CONVERT_MATRIX2(A, V);
  _CONVERT_VECTOR2(TAU_U, TAU_V);
  gsl_linalg_bidiag_unpack2(&m_A, &v_TAU_U, &v_TAU_V, &m_V);
  return Val_unit;
}
示例#2
0
int
gsl_linalg_SV_decomp (gsl_matrix * A, gsl_matrix * V, gsl_vector * S, 
                      gsl_vector * work)
{
  size_t a, b, i, j, iter;

  const size_t M=A->size1;
  const size_t N=A->size2;
  size_t K;
  if (M<N) K=M;
  else K=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);
    }

  /* Handle the case of N=1 (SVD of a column vector) */

  if (N == 1)
    {
      gsl_vector_view column=gsl_matrix_column (A, 0);
      double norm=gsl_blas_dnrm2 (&column.vector);

      gsl_vector_set (S, 0, norm); 
      gsl_matrix_set (V, 0, 0, 1.0);
      
      if (norm != 0.0)
        {
          gsl_blas_dscal (1.0/norm, &column.vector);
        }

      return GSL_SUCCESS;
    }
  
  {
    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);

    //std::cout << "A: " << gsl_matrix_get(A,0,0) << " "
    //<< gsl_matrix_get(A,M-1,N-1) << std::endl;
    //std::cout << "S: " << S->data[0] << " " 
    //<< S->data[S->size-1] 
    //<< std::endl;
    
    gsl_linalg_bidiag_unpack2 (A, S, &f.vector, V);

    //std::cout << "S2: " << S->data[0] << " " 
    //<< S->data[S->size-1] 
    //<< std::endl;
    
    /* apply reduction steps to B=(S,Sd) */
    
    chop_small_elements (S, &f.vector);
    
    //std::cout << "S3: " << S->data[0] << " " 
    //<< S->data[S->size-1] 
    //<< std::endl;
    
    /* Progressively reduce the matrix until it is diagonal */
    
    b=N - 1;
    iter=0;

    while (b > 0)
      {
        double fbm1=gsl_vector_get (&f.vector, b - 1);

        if (fbm1 == 0.0 || gsl_isnan (fbm1))
          {
            b--;
            continue;
          }

	//std::cout << "b,fbm1: " << b << " " << fbm1 << std::endl;
        
        /* Find the largest unreduced block (a,b) starting from b
           and working backwards */

        a=b - 1;

        while (a > 0)
          {
            double fam1=gsl_vector_get (&f.vector, a - 1);

            if (fam1 == 0.0 || gsl_isnan (fam1))
              {
                break;
              }
            
            a--;

	    //std::cout << "a,fam1: " << a << " " << fam1 << std::endl;
          }

        iter++;
        
        if (iter > 100 * N) 
          {
            GSL_ERROR("SVD decomposition failed to converge", GSL_EMAXITER);
          }

        
        {
          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);
          
          int rescale=0;
          double scale=1; 
          double norm=0;

          /* Find the maximum absolute values of the diagonal and subdiagonal */

          for (i=0; i < n_block; i++) 
            {
              double s_i=gsl_vector_get (&S_block.vector, i);
              double a=fabs(s_i);
              if (a > norm) norm=a;
	      //std::cout << "aa: " << a << std::endl;
            }

          for (i=0; i < n_block - 1; i++) 
            {
              double f_i=gsl_vector_get (&f_block.vector, i);
              double a=fabs(f_i);
              if (a > norm) norm=a;
	      //std::cout << "aa2: " << a << std::endl;
            }

          /* Temporarily scale the submatrix if necessary */

          if (norm > GSL_SQRT_DBL_MAX)
            {
              scale=(norm / GSL_SQRT_DBL_MAX);
              rescale=1;
            }
          else if (norm < GSL_SQRT_DBL_MIN && norm > 0)
            {
              scale=(norm / GSL_SQRT_DBL_MIN);
              rescale=1;
            }

	  //std::cout << "rescale: " << rescale << std::endl;

          if (rescale) 
            {
              gsl_blas_dscal(1.0 / scale, &S_block.vector);
              gsl_blas_dscal(1.0 / scale, &f_block.vector);
            }

          /* Perform the implicit QR step */

	  /*
	  for(size_t ii=0;ii<M;ii++) {
	    for(size_t jj=0;jj<N;jj++) {
	    std::cout << ii << "." << jj << "." 
	    << gsl_matrix_get(A,ii,jj) << std::endl;
	    }
	  }
	  for(size_t ii=0;ii<N;ii++) {
	    for(size_t jj=0;jj<N;jj++) {
	    std::cout << "V: " << ii << "." << jj << "." 
	    << gsl_matrix_get(V,ii,jj) << std::endl;
	    }
	  }
	  */

          qrstep (&S_block.vector, &f_block.vector, &U_block.matrix, 
		  &V_block.matrix);

	  /*
	  for(size_t ii=0;ii<M;ii++) {
	    for(size_t jj=0;jj<N;jj++) {
	    std::cout << ii << " " << jj << " " 
	    << gsl_matrix_get(A,ii,jj) << std::endl;
	    }
	  }
	  for(size_t ii=0;ii<N;ii++) {
	    for(size_t jj=0;jj<N;jj++) {
	    std::cout << "V: " << ii << " " << jj << " " 
	    << gsl_matrix_get(V,ii,jj) << std::endl;
	    }
	  }
	  */

          /* remove any small off-diagonal elements */
          
          chop_small_elements (&S_block.vector, &f_block.vector);
          
          /* Undo the scaling if needed */

          if (rescale)
            {
              gsl_blas_dscal(scale, &S_block.vector);
              gsl_blas_dscal(scale, &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;
}
示例#3
0
 /**
  * C++ version of gsl_linalg_bidiag_unpack2().
  * @param A A matrix
  * @param tau_U A vector
  * @param tau_V A vector
  * @param V AN orthogonal matrix
  * @return Error code on failure
  */
 inline int bidiag_unpack2( matrix& A, vector& tau_U, vector& tau_V, matrix& V ){
   return gsl_linalg_bidiag_unpack2( A.get(), tau_U.get(), tau_V.get(), V.get() ); } 
示例#4
0
int
gsl_linalg_SV_decomp (gsl_matrix * A, gsl_matrix * V, gsl_vector * S, 
                      gsl_vector * work)
{
  size_t a, b, i, j, iter;

  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);
    }

  /* Handle the case of N = 1 (SVD of a column vector) */

  if (N == 1)
    {
      gsl_vector_view column = gsl_matrix_column (A, 0);
      double norm = gsl_blas_dnrm2 (&column.vector);

      gsl_vector_set (S, 0, norm); 
      gsl_matrix_set (V, 0, 0, 1.0);
      
      if (norm != 0.0)
        {
          gsl_blas_dscal (1.0/norm, &column.vector);
        }

      return GSL_SUCCESS;
    }
  
  {
    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;
    iter = 0;

    while (b > 0)
      {
        double fbm1 = gsl_vector_get (&f.vector, b - 1);

        if (fbm1 == 0.0 || gsl_isnan (fbm1))
          {
            b--;
            continue;
          }
        
        /* Find the largest unreduced block (a,b) starting from b
           and working backwards */
        
        a = b - 1;
        
        while (a > 0)
          {
            double fam1 = gsl_vector_get (&f.vector, a - 1);

            if (fam1 == 0.0 || gsl_isnan (fam1))
              {
                break;
              }
            
            a--;
          }

        iter++;
        
        if (iter > 100 * N) 
          {
            GSL_ERROR("SVD decomposition failed to converge", GSL_EMAXITER);
          }

        
        {
          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;
}