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

📄 mes_svd.h

📁 矩阵运算的模板类
💻 H
📖 第 1 页 / 共 2 页
字号:
// -*- c++ -*-
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 Oh-Wook Kwon, all rights reserved. ohwook@yahoo.com
//
//                          Easy Matrix Template Library
// 
// This Easy Matrix Template Library is provided "as is" without any express 
// or implied warranty of any kind with respect to this software. 
// In particular the authors shall not be liable for any direct, 
// indirect, special, incidental or consequential damages arising 
// in any way from use of the software.
// 
// Everyone is granted permission to copy, modify and redistribute this
// Easy Matrix Template Library, provided:
//  1.  All copies contain this copyright notice.
//  2.  All modified copies shall carry a notice stating who
//      made the last modification and the date of such modification.
//  3.  No charge is made for this software or works derived from it.  
//      This clause shall not be construed as constraining other software
//      distributed on the same medium as this software, nor is a
//      distribution fee considered a charge.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Filename: mes_svd.h
// Revision:
//    1. Debugged an error in fixsvd().
//    2. Added maxIter in bisvd().
//    3. Added mes_rotsvd() and revised to support complex matrices.
//       Modified the contribution from Gary. D. Brushe.
// Note:
//    1. I strongly recommend the routines in this file be called 
//       with double precision arguments.
///////////////////////////////////////////////////////////////////////////////

#ifndef _MES_SVD_H_
#define _MES_SVD_H_

/* ------------- Singular Value Decomposition --------------------------- */
/**************************************************************************
**
** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
**
**                          Meschach Library
** 
** This Meschach Library is provided "as is" without any express 
** or implied warranty of any kind with respect to this software. 
** In particular the authors shall not be liable for any direct, 
** indirect, special, incidental or consequential damages arising 
** in any way from use of the software.
** 
** Everyone is granted permission to copy, modify and redistribute this
** Meschach Library, provided:
**  1.  All copies contain this copyright notice.
**  2.  All modified copies shall carry a notice stating who
**      made the last modification and the date of such modification.
**  3.  No charge is made for this software or works derived from it.  
**      This clause shall not be construed as constraining other software
**      distributed on the same medium as this software, nor is a
**      distribution fee considered a charge.
**
***************************************************************************/


///////////////////////////////////////////////////////////////////////////////
// External routines
//   Just for your information.
///////////////////////////////////////////////////////////////////////////////

// from Givens
//template <typename T> void	mes_givens(T x,T y,double* c,T* s);
//template <typename T> void	mes_rot_rows(Matrix<T>& mat,int i,int k,double c,T s,Matrix<T>& out);

// from Householder
//template <typename T> void	mes_hhvec(Vector<T>& vec,int i0,double* beta,Vector<T>& out,T* newval);
//template <typename T> void	mes_hhtrvec(Vector<T>& hh,double beta,int i0,Vector<T>& in,Vector<T>& out);
//template <typename T> void	mes_hhtrrows(Matrix<T>& M,int i0,int j0,Vector<T>& hh,double beta);
//template <typename T> void	mes_hhtrcols(Matrix<T>& M,int i0,int j0,Vector<T>& hh,double beta);

///////////////////////////////////////////////////////////////////////////////
// fixsvd -- fix minor details about SVD
//	-- make singular values non-negative
//	-- sort singular values in decreasing order
//	-- variables as for bisvd()
//	-- no argument checking
// Note:
//   Removed an error in quicksort.
///////////////////////////////////////////////////////////////////////////////
template <typename T> int Matrix<T>::mes_fixsvd(Vector<T>& d, Matrix<T>& U, Matrix<T>& V)
{
	const int MAX_STACK=100;
    int		i, j, k, l, r, stack[MAX_STACK], sp;
    T	tmp, dtmp;
	double v;
	int dim = d.Size();
	
    /* make singular values real non-negative */
    for ( i = 1; i <= dim; i++ ) {
		if ( real(d[i]) < 0.0 ){
			d[i] = - d[i];
			if ( NumCols(U) ){
				for ( j = 1; j <= NumRows(U); j++ )
					U[i][j] = - U[i][j];
			}
		}
	}
		
	/* sort singular values */
	/* nonrecursive implementation of quicksort due to R.Sedgewick,
	"Algorithms in C", p. 122 (1990) */
	sp = -1;
	l = 1;	r = dim;
	while(true){
		while ( r > l ){
			/* i = partition(d,l,r) */
			v = real(d[r]);
			
			i = l - 1;	    j = r;
			for ( ; ; ){	/* inequalities are "backwards" for **decreasing** order */
#if 0
				/* the old code with errors */
				while ( d[++i] > v )
					;
				while ( d[--j] < v )
					;
#endif
				/* the new code */
				while(1){
					++i;
					if(i>dim || real(d[i])<=v) break;
				}
				while(1){
					--j;
					if(j<1 || real(d[j])>=v) break;
				}

				if ( i >= j )
					break;
				/* swap entries in d */
				dtmp = d[i];
				d[i] = d[j];
				d[j] = dtmp;
				/* swap rows of U & V as well */
				if ( NumCols(U) ){
					for ( k = 1; k <= NumCols(U); k++ ) {
						tmp = U[i][k];
						U[i][k] = U[j][k];
						U[j][k] = tmp;
					}
				}
				if ( NumCols(V) ){
					for ( k = 1; k <= NumCols(V); k++ ){
						tmp = V[i][k];
						V[i][k] = V[j][k];
						V[j][k] = tmp;
					}
				}
			}
			dtmp = d[i];    d[i] = d[r];    d[r] = dtmp;
			if ( NumCols(U) ){
				for ( k = 1; k <= NumCols(U); k++ ){
					tmp = U[i][k];
					U[i][k] = U[r][k];
					U[r][k] = tmp;
				}
			}
			if ( NumCols(V) ){
				for ( k = 1; k <= NumCols(V); k++ ){
					tmp = V[i][k];
					V[i][k] = V[r][k];
					V[r][k] = tmp;
				}
			}
			/* end i = partition(...) */
			if(sp>=MAX_STACK-3) {
				cerr << "ERROR: Stack overflow in fixsvd()\n";
				assert(0);
				return 0; 
			} 
			if ( i - l > r - i ){
				stack[++sp] = l;
				stack[++sp] = i-1;
				l = i+1;
			}
			else{
				stack[++sp] = i+1;  
				stack[++sp] = r;	
				r = i-1;    
			}
		}
		if ( sp < 0 )
			break;
		r = stack[sp--];
		l = stack[sp--];
	}
	return 1;
}


///////////////////////////////////////////////////////////////////////////////
// bisvd -- svd of a bidiagonal m x n matrix represented by d (diagonal) and
//			f (super-diagonals)
//	-- returns with d set to the singular values, f zeroed
//	-- if the orthogonal operations are accumulated
//		in U, V; if U, V == I on entry, then SVD == U^T.A.V
//		where A is initial matrix
//	-- returns d on exit */
// Note:
//    The accuracy of sqrt(x^2+y^2) is critical in stability of the algorithm.
//    Must use 'pithagoras()' to be safe.
///////////////////////////////////////////////////////////////////////////////
template <typename T> int Matrix<T>::mes_bisvd(Vector<T>& dd, Vector<T>& ff, Matrix<T>& U, Matrix<T>& V, int maxIter)
{
	int	i, j, n;
	int	i_min, i_max, split, iter, isOK=1;
	T	s, z, dtmp, t11, t12, t21, t22;
	double c, size;
	bool isReal=U.IsReal();
	
	if (dd.Size()==0 || ff.Size()==0 )
		mes_error(E_NULL,"bisvd");
	if ( dd.Size() != ff.Size() + 1 )
		mes_error(E_SIZES,"bisvd");
	
    n = dd.Size();
	if ( (NumCols(U) < n ) || ( NumRows(V) < n ) )
		mes_error(E_SIZES,"bisvd");
	if ( (NumRows(U) != NumCols(U)) || 
		(NumRows(V) != NumCols(V)) )
		mes_error(E_SQUARE,"bisvd");
	   
	if ( n == 1 )
		return isOK;
	   
	size = mes_norm_inf(dd) + mes_norm_inf(ff);
	   
	i_min = 1;
	while ( i_min <= n ){	/* outer while loop */
	   /* find i_max to suit;
		submatrix i_min..i_max should be irreducible */
		i_max = n;
		for ( i = i_min; i <= n-1; i++ ){
			if ( mtl_iszero(dd[i]) || mtl_iszero(ff[i]) ) {
				i_max = i;
				if ( mtl_iszero(ff[i]) == false ) {
					/* have to ``chase'' ff[i] element out of matrix */
					z = ff[i];
					ff[i] = 0;
					for ( j = i; j <= n-1 && mtl_iszero(z)==false; j++ ) {
						mes_givens(dd[j+1],z, &c, &s);
						dd[j+1] =  c*dd[j+1] - s*z;
						if ( j+1 <= n-1 ) {
							z       = conj(s)*ff[j+1];
							ff[j+1] = c*ff[j+1];
						}
						if(NumCols(U))
							mes_rot_rows(U,i,j+1,c,s,U);
					}
				}
				break;
			}
		}
		
		
		if ( i_max <= i_min ) {
			i_min = i_max + 1;
			continue;
		}
		
		split = 0;
		iter=0;
		while ( ! split ){
			double shift;
			iter++;

			/* compute shift */
			t11 = dd[i_max-1]*conj(dd[i_max-1]) + (i_max > i_min+1 ? ff[i_max-2]*conj(ff[i_max-2]) : 0.0);
			t12 = conj(dd[i_max-1])*ff[i_max-1];
			t21 = conj(t12);
			t22 = dd[i_max]*conj(dd[i_max]) + ff[i_max-1]*conj(ff[i_max-1]);

			if(isReal){
				/* use e-val of [[t11,t12],[t12,t22]] matrix closest to t22 */
				double diff = real(t11-t22)/2;
				shift = real(t22 - t12*t12/(diff + ((diff>=0) ? 1 : -1)*pythagoras(diff,t12)));

⌨️ 快捷键说明

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