Matrix Template Library

/*
  Name       :   Matrix Template Library(MTL) 6.0
  Copyright  :   All rights reserved
                 You can copy and use it freely but if you want to changed it
                 you should inform the author  please mail to
dbflying@163.com
  Author     :   Dbflying
  Bug report :  
dbflying@163.com      
  Date       :   03-09-03 14:28
  Description:   Many Thanks to my friend Warren Wo(HangZhou ZheJiang province)
*/
#ifndef MATRIXH
#define MATRIXH
//------------------------------------------------------------------------
#include <complex>
#include <vector>
#include <string>
#include <cmath>
//------------------------------------------------------------------------
using namespace std;
//**namesapce soubam**//
namespace soubam{
//------------------------------------------------------------------------
const int SafeSize = 100;
//------------------------------------------------------------------------
// forward declearation
template<class T>
class CMatrix;
template<class T>
class RMatrix;
// out of range error class
class OutOfRange
{
public:
    OutOfRange(int row=-1,int col=-1,string s="Error")
    :RowIndex(row),ColIndex(col),ErrString(s){}
    int InvalidRow(){return RowIndex;}
    int InvalidCol(){return ColIndex;}
    string GetError(){return ErrString;}
private:
    int RowIndex;
    int ColIndex;
    string ErrString;
};
//------------------------------------------------------------------------
// mismatch error class
class MisMatch
{
public:
    MisMatch(string s="Error"):ErrString(s){}
    string GetError(){return ErrString;}
private:
    string ErrString;   
};
//------------------------------------------------------------------------
template<class T>
class Matrix{
public:
// constructors   
    Matrix();
    Matrix(int row,int col,T value = T(0));
    Matrix(const Matrix<T>& M);
//operator override   
    Matrix<T>& operator = (const Matrix<T>& M);
    Matrix<T>  operator + (const Matrix<T>& M);
    Matrix<T>  operator - (const Matrix<T>& M);
    Matrix<T>  operator * (const Matrix<T>& M);
    Matrix<T>  operator ^ (const int&   times);
    Matrix<T>& operator +=(const Matrix<T>& M);
    Matrix<T>& operator -=(const Matrix<T>& M);
    Matrix<T>& operator *=(const Matrix<T>& M);
    Matrix<T>& operator ^=(const int&   times);
    vector<T>& operator [](const int&     row);
    bool       operator ==(const Matrix<T>& M);
    bool       operator !=(const Matrix<T>& M);

// element access functions
    int GetRowSize()const{return RowSize;}
    int GetColSize()const{return ColSize;}
    T   GetValue(const int& row,const int& col)const
        {return matrix[row][col];}
    const vector<T> GetRowVector(const int& row)const;
    const vector<T> GetColVector(const int& col)const;
    const Matrix<T> GetRow(const int& row)const;
    const Matrix<T> GetCol(const int& col)const;
   
// modify    
    void Resize(const int& row,const int& col,T value=T(0));
    void SetValue(const int& row,const int& col,T value = T(0));    
    void AddRow(T value = T(0));
    void AddCol(T value = T(0));
    void DeleteRow(const int& row);
    void DeleteCol(const int& col);
    void InsertRow(const int& row,T value = T(0));
    void InsertCol(const int& col,T value = T(0));
    void SetRowVector(const int& row,const vector<T>& vec = vector<T>(0));
    void SetColVector(const int& col,const vector<T>& vec = vector<T>(0));
    void SwapRow(const int& row1,const int& row2);
    void SwapCol(const int& col1,const int& col2);
// special functions
    Matrix<T> Turn();
    Matrix<T> Inverse();
    Matrix<T> Unit(const int& row);
    Matrix<T> Diag();
    T         Det();
    T         Trace();
    T         Norm(const int& p=2);
    T         CondNumber();
    T         Radius();// spectral  radius
    int       Rank();
    Matrix<T> GetAij(const int& row,const int& col);
// transform
    CMatrix< complex<double> > ToCDouble(); 
protected:
    typedef vector<T>           VectorType;
    typedef vector<VectorType>  MatrixType;
    VectorType    RowVector;
    MatrixType    matrix; 
    int        RowSize;
    int        ColSize;  
 
};           
//------------------------------------------------------------------------
template<class T>
inline Matrix<T>::Matrix():RowSize(1),ColSize(1)
{
    Resize(1,1);
}
//------------------------------------------------------------------------
template<class T>
inline Matrix<T>::Matrix(int row,int col,T value):RowSize(row),ColSize(col)
{
    Resize(row,col,value);
}
//------------------------------------------------------------------------
template<class T>
inline Matrix<T>::Matrix(const Matrix<T>& M)
{
    *this = M;
}
//------------------------------------------------------------------------
template<class T> Matrix<T>&
Matrix<T>::operator = (const Matrix<T>& M)
{
    if(this!=&M)
    {
        Resize(M.GetRowSize(),M.GetColSize());       
        for(int i = 0;i< M.GetRowSize();++i)
            matrix[i] = M.GetRowVector(i);
    }              
    return *this;
}
//------------------------------------------------------------------------   
template<class T> Matrix<T>
Matrix<T>::operator + (const Matrix<T>& M)
{
    if(RowSize != M.GetRowSize() || ColSize != M.GetColSize())
        throw MisMatch("Error at + : The tow matrixs are not match for '+' .");
    Matrix<T> temp(RowSize,ColSize);
    for(int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
            temp.SetValue(i,j,(GetValue(i,j)+M.GetValue(i,j)));
    return temp;           
}
//------------------------------------------------------------------------
template<class T> Matrix<T>
Matrix<T>::operator - (const Matrix<T>& M)
{
    if(RowSize != M.GetRowSize() || ColSize != M.GetColSize())
        throw MisMatch("Error at - : The tow matrixs are not match for '-' .");
    Matrix<T> temp(RowSize,ColSize);
    for(int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
            temp.SetValue(i,j,(GetValue(i,j)-M.GetValue(i,j)));
    return temp;           
}
//------------------------------------------------------------------------
template<class T> Matrix<T>
Matrix<T>::operator * ( const Matrix<T>& M)
{
    if(ColSize != M.GetRowSize())
        throw MisMatch("Error ar * : The two matrix are not match for '*'.");
    Matrix<T> temp(RowSize,M.GetColSize());
    vector<T> vec1,vec2;
    T t;
    for(int i=0;i<RowSize;++i)
    {
         for(int j=0;j<M.GetColSize();++j)
         {
              vec1 = GetRowVector(i);
              vec2 = M.GetColVector(j);
              t=T(0);
              for(size_t k=0;k<vec1.size();++k)
                  t += vec1[k]*vec2[k];
              temp.SetValue(i,j,t);
         }
    }
    return temp;
}
//------------------------------------------------------------------------
template<class T>  Matrix<T>
Matrix<T>::operator ^(const int& times)
{
    if(times < 0)
        throw MisMatch("Error at ^ : In a^t where t<0.");
    if(RowSize != ColSize)
       throw MisMatch("Error at ^ : The matrix is not square");
    Matrix<T> M;
    M=*this;
    if(times == 0)
    {
        for(int i=0;i<RowSize;++i)
           for(int j=0;j<ColSize;++j)
               M.SetValue(i,j,T(0));
        for(int i=0;i<RowSize;++i)
           M.SetValue(i,i,T(1));
    }
    else
    {
        for(int i=0;i<times;++i)
            M = M*M ;
    }
    return M;
}
//------------------------------------------------------------------------
template<class T> Matrix<T>&
Matrix<T>::operator += ( const Matrix<T>& M)
{
    if(RowSize != M.GetRowSize()|| ColSize != M.GetColSize())
        throw  MisMatch("Error at +=: The two matrixs are not match for '+'.");
    *this = *this + M;
     return *this;
}
//------------------------------------------------------------------------
template<class T> Matrix<T>&
Matrix<T>::operator -= ( const Matrix<T>& M)
{
    if(RowSize != M.GetRowSize()|| ColSize != M.GetColSize())
        throw MisMatch("Error at -= : The two matrix are not match for '-' .");
    *this = *this - M;
    return *this;
}
//------------------------------------------------------------------------
template<class T>  Matrix<T>&
Matrix<T>::operator *= ( const Matrix<T>& M)
{
    if(ColSize != M.GetRowSize())
        throw MisMatch("Error at *= : The two matrix are not match for '*'.");
    *this = *this * M;
    return *this;
}
//------------------------------------------------------------------------
template<class T>  Matrix<T>&
Matrix<T>::operator ^=(const int& times)
{
    if( times < 0)
        throw MisMatch("Error at ^= : In a^t where t<0");       
    if(RowSize != ColSize )
        throw MisMatch("Error at ^= : The matrix is not square");
    *this=*this^times;
    return  *this;
}
//------------------------------------------------------------------------
template<class T> vector<T>&
Matrix<T>::operator [](const int& row)
{
  if(row >= RowSize || row < 0)
      throw OutOfRange(row,-1,"at []");
  return  matrix[row];   
}
//------------------------------------------------------------------------
template<class T>
bool Matrix<T>::operator ==(const Matrix<T>& M)
{
    if( RowSize != M.GetRowSize() || ColSize !=M.GetColSize())
        return false;
    for(int i=0;i<RowSize;++i)  
       for(int j=0;j<ColSize;++j)
         if(GetValue(i,j) != M.GetValue(i,j))
            return false;
    return true;  
}
//------------------------------------------------------------------------
template<class T>
bool Matrix<T>::operator !=(const Matrix<T>& M)
{
    return !(*this==M);
}
//------------------------------------------------------------------------
template<class T> const vector<T>
Matrix<T>::GetRowVector(const int& row)const
{
    if(row < 0 || row >= RowSize)
        throw OutOfRange(row,-1,"at GetRowVector");
    return matrix[row];   
}
//------------------------------------------------------------------------
template<class T> const vector<T>
Matrix<T>::GetColVector(const int& col)const
{
    if(col < 0 || col >= ColSize)
        throw OutOfRange(-1,col,"at GetColVector");
    vector<T> vec(RowSize);
    for(int i=0;i<RowSize;++i)
        vec[i]=matrix[i][col];
    return vec; 
}
//------------------------------------------------------------------------
template<class T> const Matrix<T>
Matrix<T>::GetRow(const int& row)const
{
    if(row < 0 || row >= RowSize)
      throw OutOfRange(row,-1,"at GetRow");
    Matrix<T> M(1,ColSize);
    for(int i=0;i<ColSize;++i)
        M.SetValue(0,i,GetValue(row,i));
    return M;   
}
//------------------------------------------------------------------------
template<class T> const Matrix<T>
Matrix<T>::GetCol(const int& col)const
{
    if(col < 0 || col >= ColSize)
        throw OutOfRange(-1,col,"at GetCol");
    Matrix<T> M(RowSize,1);
    for(int i=0;i<RowSize;++i)
        M.SetValue(i,0,GetValue(i,col));
    return M;         
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::Resize(const int& row,const int& col,T value)
{
    if(row <= 0 || row > SafeSize )
        throw OutOfRange(row,-1,"at Resize");
    if(col <= 0 || col > SafeSize )
        throw OutOfRange(-1,col,"at Resize");
    RowVector.resize(col,value);
    matrix.resize(row,RowVector);
    RowSize = row;
    ColSize = col;   
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::SetValue(const int& row,const int& col,T value)
{
    if(row < 0 || row >= RowSize)
        throw OutOfRange(row,-1,"at SetValue");
    if(col < 0 || col >= ColSize)
        throw OutOfRange(-1,col,"at SetValue");
    matrix[row][col]=value;   
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::AddRow(T value)
{
    vector<T> vec(matrix[0].size(),value);
    matrix.push_back(vec);
    ++RowSize;
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::AddCol(T value)
{
    for(int i=0;i<matrix.size();++i)
        matrix[i].push_back(value);
    ++ColSize;
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::DeleteRow(const int& row)
{
    if(row < 0 || row >= RowSize )
        throw OutOfRange(row,-1,"at DeleteRow");
    matrix.erase(matrix.begin() + row);
    --RowSize;
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::DeleteCol(const int& col)
{
    if(col < 0 || col >= ColSize )
        throw OutOfRange(-1,col,"at DeleteCol");
    for(int i=0;i<RowSize;++i)
        matrix[i].erase(matrix[i].begin() + col);
    --ColSize;
}
//------------------------------------------------------------------------
template<class T> void
Matrix<T>::InsertRow(const int& row,T value)
{
    if(row < 0 || row >= RowSize )
        throw OutOfRange(row,-1,"at InsertRow");
    vector<T> vec(ColSize,value);
    matrix.insert(matrix.begin()+row,vec);
    ++RowSize;
}
//------------------------------------------------------------------------
template<class T> void  
Matrix<T>::InsertCol(const int& col,T value)
{
    if(col < 0 || col >= ColSize )
        throw OutOfRange(-1,col,"at InsertCol");
    vector<T> vec(RowSize,value);
    for(int i=0;i<RowSize;++i)
        matrix[i].insert(matrix[i].begin()+col,value);
    ++ColSize;   
}
//------------------------------------------------------------------------
template<class T> void  
Matrix<T>::SetRowVector(const int& row,const vector<T>& vec)

    vector<T> tempvec(vec);
    if(row >= RowSize || row < 0 )
        throw OutOfRange(row,-1,"at SetRowVector");
    if(vec.size()!=(unsigned int)matrix[0].size())
        tempvec.resize((unsigned int)matrix[0].size());
    swap(matrix[row],tempvec);
}
//------------------------------------------------------------------------   
template<class T> void  
Matrix<T>::SetColVector(const int& col,const vector<T>& vec)
{
    if(col >= ColSize || col < 0 )
        throw OutOfRange(-1,col,"at SetColVector");
    vector<T> tempvec(vec);   
    if(vec.size()!=(unsigned int)matrix.size())
        tempvec.resize((unsigned int)matrix.size());
    for(int i = 0 ;i < RowSize ;++i)
        matrix[i][col] = tempvec[i];   
}
//------------------------------------------------------------------------   
template<class T> void  
Matrix<T>::SwapRow(const int& row1,const int& row2)
{
    if(row1 >= RowSize || row1 < 0 )
        throw OutOfRange(row1,-1,"at SwapRow");
    if(row2 >= RowSize || row2 < 0 )
        throw OutOfRange(row2,-1,"at SwapRow");
    if(row1 != row2)
        swap(matrix[row1],matrix[row2]);
}
//------------------------------------------------------------------------   
template<class T> void  
Matrix<T>::SwapCol(const int& col1,const int& col2)
{
    if(col1 >= ColSize || col1 < 0)
        throw OutOfRange(-1,col1,"at SwapCol");
    if(col2 >= ColSize || col2 < 0)
        throw OutOfRange(-1,col2,"at SwapCol");   
    if(col1 != col2)
    {
        vector<T> vec1 = GetColVector(col1);
        vector<T> vec2 = GetColVector(col2);
        swap(vec1,vec2);
        SetColVector( vec1 , col1);
        SetColVector( vec2 , col2);
    }
}
//-----------------------------------------------------------------------
template<class T> Matrix<T>
Matrix<T>::Turn()
{
    Matrix<T> temp(ColSize,RowSize);
    for(int i=0;i<temp.GetRowSize();++i)
       for(int j=0;j<temp.GetColSize();++j)
            temp.SetValue(i,j,GetValue(j,i));           
    return temp;
}
//--------------------------------------------------------------------
// Inverse function
template<class T> Matrix<T>
Matrix<T>::Inverse()
{
    T t = Det();
    if( t == T(0) )
       throw MisMatch("Error in Inverse(): The det of the matrix is zero .");  
    Matrix<T> temp(RowSize,ColSize);
    for( int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
        {
            T mi(1),n(-1);
            for(int k=0;k<i+j;++k)
                mi *= n;
            temp.SetValue(j,i,GetAij(i,j).Det()*mi);
        }   
    temp=(T(1)/t)*temp;
    return temp;
}
//--------------------------------------------------------------------
template<class T> Matrix<T>
Matrix<T>::Unit(const int& row)
{
    if(row<=0||row>SafeSize)
        throw OutOfRange(row,-1,"at Unit");
    Matrix<T> M(row,row);
    for(int i=0;i<row;++i)
        M.SetValue(i,i,T(1));
    return M;           
}
//------------------------------------------------------------------------
template<class T> Matrix<T>
Matrix<T>::Diag()
{
    if(RowSize!=ColSize)
        throw MisMatch("Error in Diag(): Row not equal to Col");
    Matrix<T> M(RowSize,1);
    for(int i=0;i<RowSize;++i)
        M.SetValue(i,0,GetValue(i,i));
    return M;
}
//--------------------------------------------------------------------
// Det function [determinant]
template<class T>
T Matrix<T>::Det()
{
    if(RowSize != ColSize)
        throw MisMatch("Error in Det(): The matrix is not square");
    if(RowSize == 1)
        return GetValue(0,0);
    if(RowSize == 2)
        return GetValue(1,1)*GetValue(0,0)-GetValue(1,0)*GetValue(0,1);
    T t(0);
    for(int i=0;i<RowSize;++i)
    {
        T mi(1),n(-1);
        for(int j=0;j<i;++j)
            mi *= n;
        t += GetValue(0,i)*GetAij(0,i).Det()*mi;
    }
    return t;
}
//--------------------------------------------------------------------
// Trace function
template<class T>
T Matrix<T>::Trace()
{  
    if(RowSize != ColSize)
        throw MisMatch("Error in Trace(): The matrix is not square");
     T t=T(0);
     for(int i=0;i<RowSize;++i)
         t += GetValue(i,i);
     return t;
}
//--------------------------------------------------------------------
// Norm function [only float,double long ,double is support]
template<class T> T
Matrix<T>::Norm(const int& p)
{
    return sqrt((((*this).Turn())*(*this)).Trace());
}
//------------------------------------------------------------------------
template<class T> T
Matrix<T>::CondNumber()
{
    Matrix<T> temp;
    temp = Inverse();
    return temp.Norm()*Norm();
}
//------------------------------------------------------------------------
template<class T> T
Matrix<T>::Radius()
{
    if(RowSize!=ColSize)
        throw MisMatch("Error in Radius() : RowSize not equal to Colszie");
    Matrix<T> A(RowSize,1,1),C,B;
    T U(0),RMD(1);
    while(1)
     {
        C=(*this)*A;
        B=C*(T(1)/C.Norm());
        RMD=(B.Turn()*C).GetValue(0,0);
        if(abs(RMD-U)<1e-6)
            break;
        U=RMD;
        A=B;
     }
     return RMD;
}
//------------------------------------------------------------------------
template<class T> int
Matrix<T>::Rank()
{
    int rank=1;
    Matrix<T> M(*this),Zero(RowSize,ColSize);
    if(M==Zero)
        return 0;
    if(RowSize>ColSize)
        M=M.Turn();
    if(M.GetRowSize()==1)
        return 1;
    bool allzero=true;   
    for(int i=0;i<M.GetRowSize();++i)
        if(M.GetValue(i,0)!=T(0))
           {
            allzero=false;
            break;
           }
    if(allzero)
       {
        M.DeleteCol(0);
        return M.Rank();
       }    
    if(M.GetValue(0,0)==T(0))
    {
         for(int i=1;i<M.GetRowSize();++i)
         {
          if(M.GetValue(i,0)!=T(0))
            {
             M.SwapRow(0,i);
             break;
            }
         }
    }
 for( i=1;i<M.GetRowSize();++i)
 {
  T first=M.GetValue(i,0);
  for( int j=0;j<M.GetColSize();++j)
   {
  T value=(M.GetValue(i,j)-first*M.GetValue(0,j)/M.GetValue(0,0));
  M.SetValue(i,j,value);
   }
 }
 rank+=M.GetAij(0,0).Rank();
 return rank;
}
//------------------------------------------------------------------------
// GetAij  function
template<class T> Matrix<T>
Matrix<T>::GetAij(const int& row ,const int& col)
{
    if(RowSize==1&&ColSize==1)
        throw MisMatch("Error in GetAij(): It should be a matrix");
    if(row < 0 || row >= RowSize)
        throw OutOfRange(row,-1,"at GetAij");
    if(col < 0 || col >= ColSize)
        throw OutOfRange(-1,col,"at GetAij");
    Matrix<T> N(*this);
    N.DeleteRow(row);
    N.DeleteCol(col);
    return N ;
}
//------------------------------------------------------------------------
template<class T> CMatrix< complex<double> >
Matrix<T>::ToCDouble()
{
    CMatrix< complex<double> > C(RowSize,ColSize);
    for(int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
            {
             complex<double> cd(GetValue(i,j));
             C.SetValue(i,j,cd);
            }
    return C;
}
//------------------------------------------------------------------------
// binary operator "*"
template<class T>  Matrix<T>
operator * (const Matrix<T>& M,T t)
{
    Matrix<T> temp(M.GetRowSize(),M.GetColSize());
    T d;
    for(int i=0;i<M.GetRowSize();++i)
        for(int j=0;j<M.GetColSize();++j)
        {
         d = M.GetValue(i,j)*t;
         temp.SetValue(i,j,d);
        }
    return   temp;
}
//--------------------------------------------------------------------
// binary operator "*"
template<class T> Matrix<T>
operator * ( T t,const Matrix<T>& M)
{
    return M*t;
}
//-----------------------------------------------------------------------
template<class T> ostream&
operator <<(ostream& o,const Matrix<T>& M)
{
    for(int i=0;i<M.GetRowSize();++i)
       {
        for(int j=0;j<M.GetColSize();++j)
                o<<M.GetValue(i,j)<<"  ";
        o<<endl;               
       }
    return o;   
}
//--------------------------------------------------------------------
template<class T> Matrix<T>
Kronecker(const Matrix<T>& M1,const Matrix<T>& M2)
{
    Matrix<T> M(M1.GetRowSize()*M2.GetRowSize(),M1.GetColSize()*M2.GetColSize());
    for(int i=0;i<M1.GetRowSize();++i)
        for(int j=0;j<M1.GetColSize();++j)
        {
         Matrix<T> temp(M2);
         temp=M1.GetValue(i,j)*temp;
         for(int k=0;k<M2.GetRowSize();++k)
            for(int l=0;l<M2.GetColSize();++l)
                M.SetValue(i*M2.GetRowSize()+k,j*M2.GetColSize()+l,temp.GetValue(k,l));
        }
    return M;   
}   
//-----------------------------------------------------------------------
    /**********RMatrix**********/
//-----------------------------------------------------------------------
template<class T >
class RMatrix : public Matrix<T>{
public:
    RMatrix():Matrix<T>(){};
    RMatrix(int row,int col,T value=T(0)):Matrix<T>(row,col,value){}
    RMatrix(RMatrix<T>& N):Matrix<T>(N){}
// operator override
    RMatrix<T>& operator = (const Matrix<T>&);
// convert function
    RMatrix<double> ToDouble();
// JACOBI µü´ú·¨Çó½âʵ¶Ô³Æ¾ØÕóÌØÕ÷Öµ¡¢ÌØÕ÷ÏòÁ¿
    RMatrix<T> Jacobi(RMatrix<T>& value=RMatrix<T>());
};
//-----------------------------------------------------------------------
template<class T> RMatrix<T>&
RMatrix<T>:: operator = (const Matrix<T>& M)
{
    if(this!=&M)
    {
        Resize(M.GetRowSize(),M.GetColSize());
        for(int i = 0;i< M.GetRowSize();++i)
            matrix[i] = M.GetRowVector(i);
    }
    return *this;
}
//-----------------------------------------------------------------------
template<class T> RMatrix<double>
RMatrix<T>::ToDouble()
{
    Matrix< double > temp(RowSize,ColSize);
    double d;
    for(int i=0;i<RowSize;++i)
         for(int j=0;j<ColSize;++j)
         {
          d = matrix[i][j];
          temp.SetValue(i,j,d);
         }
    return temp;    
}
//-----------------------------------------------------------------------
template<class T> RMatrix<T>
RMatrix<T>::Jacobi(RMatrix<T>& value)
{
    if(RowSize!=ColSize)
        throw MisMatch("Error in Jacobi(): Jacobi method requres row=col");
    if(*this!=(*this).Turn())
        throw MisMatch("Error in Jacobi() :matrix should equal to turn of matrix.");
    RMatrix<T> M(*this);
    RMatrix<T> R(RowSize,ColSize),R1(R);
    int p,q;   
    R1=R1.Unit(R1.GetRowSize());
    for( int step=0;step<50;++step)
    {   
        p=1;
        q=0;
        T MaxValue=M.GetValue(1,0);
        for(int i=1;i<M.GetRowSize();++i)
            for(int j=0;j<i;++j)
            {
                if(abs(MaxValue)<abs(M.GetValue(i,j)))
                {
                    MaxValue=M.GetValue(i,j);
                    p=i;
                    q=j;
                }
            }
        R=R.Unit(R.GetRowSize());
        T V(M.GetValue(p,q)/(M.GetValue(q,q)-M.GetValue(p,p)));
        T C(1/sqrt(V*V+1));
        T S(C*V);
        R[p][p]=C;
        R[q][q]=C;
        R[p][q]=S;
        R[q][p]=-S;          
        M=R.Turn()*M*R;
        R1=R1*R;
        if(abs(MaxValue)<=1e-6)
            {
                value = R1;
                M=M.Diag();
                return M;
            } 
    }
    value = R1;
    M=M.Diag();
    return M;
}
//-----------------------------------------------------------------------
    /**********CMatrix**********/
//-----------------------------------------------------------------------
template<class T >
class CMatrix : public Matrix<T>{
public:
    CMatrix():Matrix<T>(){};
    CMatrix(int row,int col,T value=T(0)):Matrix<T>(row,col,value){}
    CMatrix(RMatrix<T>& N):Matrix<T>(N){}
// operator override   
    CMatrix<T>& operator = (const Matrix<T>&);   
// special function
    CMatrix<T>  Turn();
    RMatrix<T>  Real();
    RMatrix<T>  Imag();
};
//-----------------------------------------------------------------------
template<class T> CMatrix<T>&
CMatrix<T>:: operator = (const Matrix<T>& M)
{
    if(this!=&M)
    {
        Resize(M.GetRowSize(),M.GetColSize());       
        for(int i = 0;i< M.GetRowSize();++i)
            matrix[i] = M.GetRowVector(i);
    }  
    return *this;
}
//-----------------------------------------------------------------------
template<class T> CMatrix<T>
CMatrix<T>::Turn()
{
    CMatrix<T> temp(ColSize,RowSize);
    for(int i=0;i<temp.GetRowSize();++i)
       for(int j=0;j<temp.GetColSize();++j)
            temp.SetValue(i,j,conj(GetValue(j,i)));
    return temp;
}
//-----------------------------------------------------------------------
template<class T> RMatrix<T>
CMatrix<T>::Real()
{
    RMatrix<T> R(RowSize,ColSize);
    for(int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
            R.SetValue(i,j,GetValue(i,j).real());
    return R;       
}
//-----------------------------------------------------------------------
template<class T> RMatrix<T>
CMatrix<T>::Imag()
{
    RMatrix<T> C(RowSize,ColSize);
    for(int i=0;i<RowSize;++i)
        for(int j=0;j<ColSize;++j)
            C.SetValue(i,j,GetValue(i,j).imag());
    return C;
}
//------------------------------------------------------------------------
}//**namespace soubam**//
//------------------------------------------------------------------------
#endif

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值