Skip to content
Snippets Groups Projects
Matrix.cpp 42.3 KiB
Newer Older
    indxrow[i]=static_cast<int>(irow);
    indxcol[i]=static_cast<int>(icol);
    
    if (V[icol][icol] == 0.0)
          {
            std::cerr<<"Error doing G-J elem on a singular matrix"<<std::endl;
            return 1;
    const T pivDiv= T(1.0)/V[icol][icol];
Stuart Ansell's avatar
Stuart Ansell committed
    }
        const T div_num=V[ll][icol];
Stuart Ansell's avatar
Stuart Ansell committed
  // Un-roll interchanges
Stuart Ansell's avatar
Stuart Ansell committed
  return 0;  
}

template<typename T>
std::vector<T>
Matrix<T>::Faddeev(Matrix<T>& InvOut)
Stuart Ansell's avatar
Stuart Ansell committed
    Return the polynominal for the matrix
    and the inverse. 
Stuart Ansell's avatar
Stuart Ansell committed
    The polynomial is such that
Stuart Ansell's avatar
Stuart Ansell committed
    \f[
      det(sI-A)=s^n+a_{n-1}s^{n-1} \dots +a_0
    \f]
    @param InvOut ::: output 
    @return Matrix self Polynomial (low->high coefficient order)
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (nx!=ny)
    throw Kernel::Exception::MisMatch<size_t>(nx,ny,"Matrix::Faddev(Matrix)");
Stuart Ansell's avatar
Stuart Ansell committed

  Matrix<T>& A(*this);
  Matrix<T> B(A);
  Matrix<T> Ident(nx,ny);
Stuart Ansell's avatar
Stuart Ansell committed
  Ident.identityMatrix();
Stuart Ansell's avatar
Stuart Ansell committed

  T tVal=B.Trace();                     // Trace of the matrix
  std::vector<T> Poly;
  Poly.push_back(1);
  Poly.push_back(tVal);

  for(size_t i=0;i<nx-2;i++)   // skip first (just copy) and last (to keep B-1)
Stuart Ansell's avatar
Stuart Ansell committed
    {
      B=A*B - Ident*tVal;
      tVal=B.Trace();
Stuart Ansell's avatar
Stuart Ansell committed
    }
  // Last on need to keep B;
  InvOut=B;
  B=A*B - Ident*tVal;
  tVal=B.Trace();
Stuart Ansell's avatar
Stuart Ansell committed
  
  InvOut-= Ident* (-Poly[nx-1]);
  InvOut/= Poly.back();
  return Poly;
}

template<typename T>
T
Matrix<T>::Invert()
Stuart Ansell's avatar
Stuart Ansell committed
    If the Matrix is square then invert the matrix
    using LU decomposition
    @return Determinant (0 if the matrix is singular)
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (nx!=ny && nx<1)
    return 0;
  
  int* indx=new int[nx];   // Set in lubcmp

  double* col=new double[nx];
  int d;
  Matrix<T> Lcomp(*this);
  Lcomp.lubcmp(indx,d);
Stuart Ansell's avatar
Stuart Ansell committed
  double det=static_cast<double>(d);
Stuart Ansell's avatar
Stuart Ansell committed
    det *= Lcomp.V[j][j];
  
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
      col[j]=1.0;
      Lcomp.lubksb(indx,col);
Stuart Ansell's avatar
Stuart Ansell committed
    } 
  delete [] indx;
  delete [] col;
  return static_cast<T>(det);
}

template<typename T>
T
Matrix<T>::determinant() const
Stuart Ansell's avatar
Stuart Ansell committed
    Calculate the derminant of the matrix
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (nx!=ny)
        "Determinant error :: Matrix is not NxN");
Stuart Ansell's avatar
Stuart Ansell committed

  Matrix<T> Mt(*this);         //temp copy
  T D=Mt.factor();
  return D;
}

template<typename T>
T
Matrix<T>::factor()
Stuart Ansell's avatar
Stuart Ansell committed
     Gauss jordan diagonal factorisation 
     The diagonal is left as the values, 
     the lower part is zero.
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (nx!=ny || nx<1)
    throw std::runtime_error("Matrix::factor Matrix is not NxN");
Stuart Ansell's avatar
Stuart Ansell committed

  double deter=1.0;
  for(int i=0;i<static_cast<int>(nx)-1;i++)       //loop over each row
Stuart Ansell's avatar
Stuart Ansell committed
    {
      int jmax=i;
      double Pmax=fabs(V[i][i]);
      for(int j=i+1;j<static_cast<int>(nx);j++)     // find max in Row i
Stuart Ansell's avatar
Stuart Ansell committed
        {
Stuart Ansell's avatar
Stuart Ansell committed
            {
Stuart Ansell's avatar
Stuart Ansell committed
      if (Pmax<1e-8)         // maxtrix signular 
        {
//          std::cerr<<"Matrix Singular"<<std::endl;
Stuart Ansell's avatar
Stuart Ansell committed
      // Swap Columns
      if (i!=jmax) 
        {
Stuart Ansell's avatar
Stuart Ansell committed
      // zero all rows below diagonal
      Pmax=V[i][i];
      deter*=Pmax;
      for(int k=i+1;k<static_cast<int>(nx);k++)  // row index
Stuart Ansell's avatar
Stuart Ansell committed
        {
          const double scale=V[k][i]/Pmax;
          V[k][i]=static_cast<T>(0);
          for(int q=i+1;q<static_cast<int>(nx);q++)   //column index
            V[k][q]-=static_cast<T>(scale*V[i][q]);
        }
Stuart Ansell's avatar
Stuart Ansell committed
    }
  deter*=V[nx-1][nx-1];
  return static_cast<T>(deter);
}

template<typename T>
void 
Matrix<T>::normVert()
Stuart Ansell's avatar
Stuart Ansell committed
    Normalise EigenVectors
    Assumes that they have already been calculated
  */
{
  for(size_t i=0;i<nx;i++)
  {
    T sum=0;
    for(size_t j=0;j<ny;j++)
    {
      sum += V[i][j]*V[i][j];
    }
    sum=static_cast<T>(std::sqrt(static_cast<double>(sum)));
    for(size_t j=0;j<ny;j++)
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
    }
Stuart Ansell's avatar
Stuart Ansell committed
  return;
}

template<typename T>
T
Matrix<T>::compSum() const
Stuart Ansell's avatar
Stuart Ansell committed
    Add up each component sums for the matrix
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  T sum(0);
Stuart Ansell's avatar
Stuart Ansell committed
      sum+=V[i][j]*V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed
  return sum;
}

template<typename T>
void 
Matrix<T>::lubcmp(int* rowperm,int& interchange)
Stuart Ansell's avatar
Stuart Ansell committed
    Find biggest pivot and move to top row. Then
    divide by pivot.
    @param interchange :: odd/even nterchange (+/-1)
    @param rowperm :: row permuations [nx values]
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  double sum,dum,big,temp;

  if (nx!=ny || nx<2)
    {
      std::cerr<<"Error with lubcmp"<<std::endl;
      return;
    }
  double *vv=new double[nx];
  interchange=1;
Stuart Ansell's avatar
Stuart Ansell committed
    {
      big=0.0;
      for(int j=0;j<static_cast<int>(nx);j++)
      if ((temp=fabs(V[i][j])) > big) 
Stuart Ansell's avatar
Stuart Ansell committed

      if (big == 0.0) 
Stuart Ansell's avatar
Stuart Ansell committed
        {
Stuart Ansell's avatar
Stuart Ansell committed
      vv[i]=1.0/big;
    }

  for (int j=0;j<static_cast<int>(nx);j++)
Stuart Ansell's avatar
Stuart Ansell committed
    {
      for(int i=0;i<j;i++)
        {
          sum=V[i][j];
          for(int k=0;k<i;k++)
Stuart Ansell's avatar
Stuart Ansell committed
            sum-= V[i][k] * V[k][j];
          V[i][j]=static_cast<T>(sum);
        }
      big=0.0;
Stuart Ansell's avatar
Stuart Ansell committed
        {
          sum=V[i][j];
          for (int k=0;k<j;k++)
Stuart Ansell's avatar
Stuart Ansell committed
            sum -= V[i][k] * V[k][j];
          V[i][j]=static_cast<T>(sum);
          if ( (dum=vv[i] * fabs(sum)) >=big)
            {
              big=dum;
              imax=i;
            }
        }

      if (j!=imax)
        {
          for(int k=0;k<static_cast<int>(nx);k++)
Stuart Ansell's avatar
Stuart Ansell committed
            {                     //Interchange rows
              dum=V[imax][k];
              V[imax][k]=V[j][k];
              V[j][k]=static_cast<T>(dum);
            }
          interchange *= -1;
          vv[imax]=static_cast<T>(vv[j]);
        }
      rowperm[j]=imax;
      
      if (V[j][j] == 0.0) 
        V[j][j]=static_cast<T>(1e-14);
Stuart Ansell's avatar
Stuart Ansell committed
        {
          dum=1.0/(V[j][j]);
Stuart Ansell's avatar
Stuart Ansell committed
            V[i][j] *= static_cast<T>(dum);
        }
    }
  delete [] vv;
  return;
}

template<typename T>
void 
Matrix<T>::lubksb(const int* rowperm,double* b)
Stuart Ansell's avatar
Stuart Ansell committed
    Impliments a separation of the Matrix
    into a triangluar matrix
  */
{
  int ii= -1;
 
Stuart Ansell's avatar
Stuart Ansell committed
    {
      int ip=rowperm[i];
      double sum=b[ip];
      b[ip]=b[i];
      if (ii != -1) 
        for (int j=ii;j<i;j++) 
          sum -= V[i][j] * b[j];
      else if (sum != 0.)
Stuart Ansell's avatar
Stuart Ansell committed
        ii=i;
      b[i]=sum;
    }

  for (int i=static_cast<int>(nx)-1;i>=0;i--)
Stuart Ansell's avatar
Stuart Ansell committed
    {
      double sum=static_cast<T>(b[i]);
Stuart Ansell's avatar
Stuart Ansell committed
        sum -= V[i][j] * b[j];
      b[i]=sum/V[i][i];
    }
  return;
}

template<typename T>
void
Matrix<T>::averSymmetric()
Stuart Ansell's avatar
Stuart Ansell committed
    Simple function to create an average symmetric matrix
Stuart Ansell's avatar
Stuart Ansell committed
    out of the Matrix
  */
{
  const size_t minSize=(nx>ny) ? ny : nx;
  for(size_t i=0;i<minSize;i++)
  {
    for(size_t j=i+1;j<minSize;j++)
    {
      V[i][j]=(V[i][j]+V[j][i])/2;
      V[j][i]=V[i][j];
    }
  }
Stuart Ansell's avatar
Stuart Ansell committed
}

template<typename T> 
std::vector<T>
Matrix<T>::Diagonal() const
Stuart Ansell's avatar
Stuart Ansell committed
    Returns the diagonal form as a vector
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
Stuart Ansell's avatar
Stuart Ansell committed
  std::vector<T> Diag(Msize);
Stuart Ansell's avatar
Stuart Ansell committed
    Diag[i]=V[i][i];
Stuart Ansell's avatar
Stuart Ansell committed
  return Diag;
}

template<typename T> 
T
Matrix<T>::Trace() const
Stuart Ansell's avatar
Stuart Ansell committed
    Calculates the trace of the matrix
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  const size_t Msize=(ny>nx) ? nx : ny;
  T Trx = 0;
  for(size_t i=0; i < Msize; i++)
  {
Stuart Ansell's avatar
Stuart Ansell committed
    Trx+=V[i][i];
Stuart Ansell's avatar
Stuart Ansell committed
  return Trx;
}

template<typename T> 
void
Matrix<T>::sortEigen(Matrix<T>& DiagMatrix) 
Stuart Ansell's avatar
Stuart Ansell committed
    Sorts the eigenvalues into increasing
    size. Moves the EigenVectors correspondingly
    @param DiagMatrix :: matrix of the EigenValues
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (ny!=nx || nx!=DiagMatrix.nx || nx!=DiagMatrix.ny)
    {
      std::cerr<<"Matrix not Eigen Form"<<std::endl;
          throw(std::invalid_argument(" Matrix is not in an eigenvalue format"));
Stuart Ansell's avatar
Stuart Ansell committed
    }
  std::vector<int> index;
  std::vector<T> X=DiagMatrix.Diagonal();
  indexSort(X,index);
  Matrix<T> EigenVec(*this);
    for(size_t j=0;j<nx;j++)
    {
      V[j][Icol]=EigenVec[j][index[Icol]];
    }
    DiagMatrix[Icol][Icol]=X[index[Icol]];
Stuart Ansell's avatar
Stuart Ansell committed

  return;
}

template<typename T>
int 
Matrix<T>::Diagonalise(Matrix<T>& EigenVec,Matrix<T>& DiagMatrix) const
Stuart Ansell's avatar
Stuart Ansell committed
    Attempt to diagonalise the matrix IF symmetric
    @param EigenVec :: (output) the Eigenvectors matrix 
    @param DiagMatrix :: the diagonal matrix of eigenvalues 
    @return :: 1  on success 0 on failure
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if(nx!=ny || nx<1)
    {
      std::cerr<<"Matrix not square"<<std::endl;
      return 0;
    }
  for(size_t i=0;i<nx;i++)
    for(size_t j=i+1;j<nx;j++)
Stuart Ansell's avatar
Stuart Ansell committed
      if (fabs(V[i][j]-V[j][i])>1e-6)
        {
          std::cerr<<"Matrix not symmetric"<<std::endl;
          std::cerr<< (*this);
          return 0;
        }
Stuart Ansell's avatar
Stuart Ansell committed
    
  Matrix<T> A(*this);
  //Make V an identity matrix
  EigenVec.setMem(nx,nx);
  EigenVec.identityMatrix();
  DiagMatrix.setMem(nx,nx);
  DiagMatrix.zeroMatrix();

  std::vector<double> Diag(nx);
  std::vector<double> B(nx);
  std::vector<double> ZeroComp(nx);
  //set b and d to the diagonal elements o A
Stuart Ansell's avatar
Stuart Ansell committed
    {
      Diag[i]=B[i]= A.V[i][i];
      ZeroComp[i]=0;
    }

  int iteration=0;
  for(int i=0;i<100;i++)        //max 50 iterations
    {
      double sm=0.0;           // sum of off-diagonal terms
        for(size_t iq=ip+1;iq<nx;iq++)
          sm+=fabs(A.V[ip][iq]);
Stuart Ansell's avatar
Stuart Ansell committed

      if (sm==0.0)           // Nothing to do return...
        {
          // Make OUTPUT -- D + A
          // sort Output::
          for(size_t ix=0;ix<nx;ix++)
            DiagMatrix.V[ix][ix]=static_cast<T>(Diag[ix]);
          return 1;
        }
Stuart Ansell's avatar
Stuart Ansell committed

      // Threshold large for first 5 sweeps
      double tresh= (i<6) ? 0.2*sm/static_cast<int>(nx*nx) : 0.0;
Stuart Ansell's avatar
Stuart Ansell committed

        {
          for(int iq=ip+1;iq<static_cast<int>(nx);iq++)
            {
              double g=100.0*fabs(A.V[ip][iq]);
              // After 4 sweeps skip if off diagonal small
              if (i>6 && 
                  static_cast<float>(fabs(Diag[ip]+g))==static_cast<float>(fabs(Diag[ip])) &&
                  static_cast<float>(fabs(Diag[iq]+g))==static_cast<float>(fabs(Diag[iq])))
                A.V[ip][iq]=0;

              else if (fabs(A.V[ip][iq])>tresh)
                {
                  double tanAngle,cosAngle,sinAngle;
                  double h=Diag[iq]-Diag[ip];
                  if (static_cast<float>((fabs(h)+g)) == static_cast<float>(fabs(h)))
                    tanAngle=A.V[ip][iq]/h;      // tanAngle=1/(2theta)
                  else
                    {
                      double theta=0.5*h/A.V[ip][iq];
                      tanAngle=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
                      if (theta<0.0)
                        tanAngle = -tanAngle;
                    }
                  cosAngle=1.0/sqrt(1+tanAngle*tanAngle);
                  sinAngle=tanAngle*cosAngle;
                  double tau=sinAngle/(1.0+cosAngle);
                  h=tanAngle*A.V[ip][iq];
                  ZeroComp[ip] -= h;
                  ZeroComp[iq] += h;
                  Diag[ip] -= h;
                  Diag[iq] += h;
                  A.V[ip][iq]=0;
                  // Rotations 0<j<p
                  for(int j=0;j<ip;j++)
                    A.rotate(tau,sinAngle,j,ip,j,iq);
                  for(int j=ip+1;j<iq;j++)
                    A.rotate(tau,sinAngle,ip,j,j,iq);
                  for(int j=iq+1;j<static_cast<int>(nx);j++)
                    A.rotate(tau,sinAngle,ip,j,iq,j);
                  for(int j=0;j<static_cast<int>(nx);j++)
                    EigenVec.rotate(tau,sinAngle,j,ip,j,iq);
                  iteration++;
                }
            }
        }   
Stuart Ansell's avatar
Stuart Ansell committed
    }
  std::cerr<<"Error :: Iterations are a problem"<<std::endl;
  return 0;
}

bool Matrix<T>::isRotation() const
/** Check if a matrix represents a proper rotation
@ return :: true/false
*/
{
  if (this->nx != this->ny) throw(std::invalid_argument("matrix is not square"));
//  std::cout << "Matrix determinant-1 is " << (this->determinant()-1) << std::endl;
  if (fabs(this->determinant()-1) >1e-5) 
  {
    return false;
  }
  else
  {
    Matrix<T> prod(nx,ny),ident(nx,ny,true);
    prod= this->operator*(this->Tprime());
//    std::cout << "Matrix * Matrix' = " << std::endl << prod << std::endl;
    return prod.equals(ident, 1e-5);
bool Matrix<T>::isOrthogonal() const
/** Check if a matrix is orthogonal. Same as isRotation, but allows determinant to be -1
@ return :: true/false
*/
{
  if (this->nx != this->ny) throw(std::invalid_argument("matrix is not square"));
  if (fabs(fabs(this->determinant())-1.) >1e-5) 
  {
    return false;
  }
  else
  {
    Matrix<T> prod(nx,ny),ident(nx,ny,true);
    prod= this->operator*(this->Tprime());
    return prod.equals(ident, 1e-7);
  }
}



template<typename T>
std::vector<T> Matrix<T>::toRotation() 
/**
  Transform the matrix to a rotation matrix, by normalizing each column to 1
  @return :: a vector of scaling factors
  @throw :: std::invalid_argument if the absolute value of the determinant is less then 1e-10 or not square matrix
*/
{
  if (this->nx != this->ny) throw(std::invalid_argument("matrix is not square"));
  if (fabs(this->determinant()) <1e-10) throw(std::invalid_argument("Determinant is too small"));
  // step 1: orthogonalize the matrix
  for (size_t i=0; i<this->ny;++i)
  {
    for (size_t j=0; j<this->nx;++j) spself+=(V[j][i]*V[j][i]);
    for (size_t k=i+1; k<this->ny;++k) 
    {
      for (size_t j=0; j<this->nx;++j) spother+=(V[j][i]*V[j][k]);
      for (size_t j=0; j<this->nx;++j) V[j][k]-=static_cast<T>(V[j][i]*spother/spself);
    }
    
  }
  // step 2: get scales and rescsale the matrix
  std::vector<T> scale(this->nx);
  T currentScale;
  for (size_t i=0; i<this->ny;++i)
  {
    for (size_t j=0; j<this->nx;++j)
      currentScale+=(V[j][i]*V[j][i]);
    currentScale=static_cast<T>(sqrt(static_cast<double>(currentScale)));
    if (currentScale <1e-10) throw(std::invalid_argument("Scale is too small"));
    scale[i]=currentScale;
  }
  Matrix<T> scalingMatrix(nx,ny),change(nx,ny,true);
  for (size_t i=0; i<this->ny;++i) scalingMatrix[i][i]=static_cast<T>(1.0/scale[i]);
  *this = this->operator*(scalingMatrix);
  if (this->determinant() <0.)
  {
    scale[0]=-scale[0];
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
void
Matrix<T>::print() const
Stuart Ansell's avatar
Stuart Ansell committed
    Simple print out routine 
   */
{
  write(std::cout,10);
  return;
}

/** set matrix elements ito random values  in the range from  rMin to rMax*/
template<typename T>
void 
Matrix<T>::setRandom(size_t seed,double rMin,double rMax)
{
    MersenneTwister rng(seed, rMin, rMax);

    for(size_t i=0;i<nx;i++)
    {
        for(size_t j=0;j<ny;j++)
        {
            V[i][j] =static_cast<T>(rng.nextValue());
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
void
Matrix<T>::write(std::ostream& Fh,const int blockCnt) const
Stuart Ansell's avatar
Stuart Ansell committed
    Write out function for blocks of 10 Columns 
    @param Fh :: file stream for output
    @param blockCnt :: number of columns per line (0 == full)
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  std::ios::fmtflags oldFlags=Fh.flags();
  Fh.setf(std::ios::floatfield,std::ios::scientific);
  const size_t blockNumber((blockCnt>0) ? blockCnt : ny);  
  size_t BCnt(0);
Stuart Ansell's avatar
Stuart Ansell committed
  do
    {
Stuart Ansell's avatar
Stuart Ansell committed
      if (BCnt>ny)
Stuart Ansell's avatar
Stuart Ansell committed

      if (ACnt)
        Fh<<" ----- "<<ACnt<<" "<<BCnt<<" ------ "<<std::endl;
Stuart Ansell's avatar
Stuart Ansell committed
        {
Stuart Ansell's avatar
Stuart Ansell committed
    } while(BCnt<ny);

  Fh.flags(oldFlags);
  return;
}

template<typename T>
std::string
Matrix<T>::str() const
Stuart Ansell's avatar
Stuart Ansell committed
    Convert the matrix into a simple linear string expression 
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  std::ostringstream cx;
Stuart Ansell's avatar
Stuart Ansell committed
  return cx.str();
}

/**
 * Write an object to a stream. Format will be Matrix(nrows,ncols)x_00,x_01...,x_10,x_11
 * @param os :: output stream
 * @param matrix :: Matrix to write out
 * @return The output stream (of)
*/
template<typename T>
std::ostream& operator<<(std::ostream& os,const Matrix<T>& matrix)
{
  dumpToStream(os, matrix, ',');
  return os;
}

/**
 * Write a Matrix to a stream. Format will be Matrix(nrowsSEPncols)x_00SEPx_01...SEPx_10SEPx_11
 * @param os :: output stream
 * @param matrix :: Matrix to write out
 * @param delimiter :: A character to use as delimiter for the string
*/
template<typename T>
void dumpToStream(std::ostream& os, const Kernel::Matrix<T>& matrix, const char delimiter)
{
  size_t nrows(matrix.numRows()), ncols(matrix.numCols());
  os << "Matrix(" << nrows << delimiter << ncols << ")";
  for( size_t i = 0; i < nrows; ++i )
  {
    for( size_t j = 0; j < ncols; ++j )
    {
      os << matrix[i][j];
      if( i < nrows - 1 || j < ncols - 1 ) os << delimiter;
    }
  }
}

/**
* Fill an object from a stream. Format should be Matrix(nrows,ncols)x_00,x_01...,x_10,x_11
* @param is :: A stream object
* @param in :: An object to fill
* @returns A reference to the stream
*/
template<typename T>
std::istream& operator>>(std::istream& is, Kernel::Matrix<T>& in)
{
  fillFromStream(is, in, ',');
  return is;
}

/**
* Fill a Matrix from a stream using the given separator. Format should be Matrix(nrowsSEPncols)x_00SEPx_01...SEPx_10SEPx_11
* where SEP is replaced by the given separator
* @param is :: A stream object
* @param in :: An Matrix object to fill
* @param delimiter :: A single character separator that delimits the entries
*/
template<typename T>
void fillFromStream(std::istream& is, Kernel::Matrix<T>& in, const char delimiter)
{
  // Stream should start with Matrix(
  char dump;
  std::string start(7, ' ');
  for (int i = 0; i < 7; ++i)
  {
    is >> dump;
    start[i] = dump;
    if( !is ) throw std::invalid_argument("Unexpected character when reading Matrix from stream.");
  }
  if( start != "Matrix(" ) throw std::invalid_argument("Incorrect input format for Matrix stream.");
  // Now read a nrows,ncols and )
  size_t nrows(0), ncols(0);
  is >> nrows;
  if( !is ) throw std::invalid_argument("Expected number of rows when reading Matrix from stream, found something else.");
  is >> dump;
  is >> ncols;
  if( !is ) throw std::invalid_argument("Expected number of columns when reading Matrix from stream, found something else.");
  is >> dump;
  if( dump != ')' ) throw std::invalid_argument("Expected closing parenthesis after ncols when reading Matrix from stream, found something else.");

  // Resize the matrix
  in.setMem(nrows,ncols);

  // Use getline with the delimiter set to "," to read
  std::string value_str;
  size_t row(0), col(0);
  while( !is.eof() && std::getline(is, value_str, delimiter) )
  {
    try
    {
      T value = boost::lexical_cast<T>(value_str);
      in.V[row][col] = value;
    }
    catch(boost::bad_lexical_cast &)
    {
      throw std::invalid_argument("Unexpected type found while reading Matrix from stream: \"" + value_str + "\"");
    }
    ++col;
    if( col == ncols ) // New row
    {
      col = 0;
      ++row;
    }
  }
}


Stuart Ansell's avatar
Stuart Ansell committed
///\cond TEMPLATE

template class MANTID_KERNEL_DLL Matrix<double>;
template class MANTID_KERNEL_DLL Matrix<int>;
template class MANTID_KERNEL_DLL Matrix<float>;

template MANTID_KERNEL_DLL std::ostream& operator<<(std::ostream&, const DblMatrix&);
template MANTID_KERNEL_DLL void dumpToStream(std::ostream&, const DblMatrix&, const char);
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, DblMatrix&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, DblMatrix&, const char);

template MANTID_KERNEL_DLL std::ostream& operator<<(std::ostream&, const Matrix<float>&);
template MANTID_KERNEL_DLL void dumpToStream(std::ostream&, const Matrix<float>&, const char);
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, Matrix<float>&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, Matrix<float>&, const char);

template MANTID_KERNEL_DLL std::ostream& operator<<(std::ostream&, const IntMatrix&);
template MANTID_KERNEL_DLL void dumpToStream(std::ostream&, const IntMatrix&, const char);
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, IntMatrix&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, IntMatrix&, const char);
Stuart Ansell's avatar
Stuart Ansell committed
///\endcond TEMPLATE
Stuart Ansell's avatar
Stuart Ansell committed