Skip to content
Snippets Groups Projects
Matrix.cpp 42.3 KiB
Newer Older
#include "MantidKernel/Matrix.h"
#include "MantidKernel/V3D.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/MersenneTwister.h"
#include <iostream>
using Mantid::Kernel::TimeSeriesProperty;
Stuart Ansell's avatar
Stuart Ansell committed

Stuart Ansell's avatar
Stuart Ansell committed

Stuart Ansell's avatar
Stuart Ansell committed
namespace Mantid
{

Stuart Ansell's avatar
Stuart Ansell committed
{
Stuart Ansell's avatar
Stuart Ansell committed

  namespace
  {
    //-------------------------------------------------------------------------
    // Utility methods and function objects in anonymous namespace
    //-------------------------------------------------------------------------
    /**
    \class PIndex
    \author S. Ansell
    \date Aug 2005
    \version 1.0
    \brief Class  to fill an index with a progressive count
    */
    template<typename T>
    struct PIndex
    {
    private:
      int count;    ///< counter
    public:
      /// Constructor
      PIndex() : count(0) { }
      /// functional
      std::pair<T,int> operator()(const T& A) {  return std::pair<T,int>(A,count++); }
    };

    /**
    \class PSep
    \author S. Ansell
    \date Aug 2005
    \version 1.0
    \brief Class to access the second object in index pair.
    */
    template<typename T>
    struct PSep
    {
      /// Functional to the second object
      int operator()(const std::pair<T,int>& A) {  return A.second; }
    };

    /**
    * Function to take a vector and sort the vector 
    * so as to produce an index. Leaves the vector unchanged.
    * @param pVec :: Input vector
    * @param Index :: Output vector
    */
    template<typename T>
    void
      indexSort(const std::vector<T>& pVec,std::vector<int>& Index)
    {
      Index.resize(pVec.size());
      std::vector<typename std::pair<T,int> > PartList;
      PartList.resize(pVec.size());

      transform(pVec.begin(),pVec.end(),PartList.begin(),PIndex<T>());
      sort(PartList.begin(),PartList.end());
      transform(PartList.begin(),PartList.end(),Index.begin(),PSep<T>());
      return;
    }
    template void indexSort(const std::vector<double>&,std::vector<int>&);
    template void indexSort(const std::vector<float>&,std::vector<int>&);
    template void indexSort(const std::vector<int>&,std::vector<int>&);
Stuart Ansell's avatar
Stuart Ansell committed

Matrix<T>::getVector()const
  std::vector<T> rez(nx*ny);
  size_t ic(0);
  for(size_t i=0;i<nx;i++)
  {
    for(size_t j=0;j<ny;j++)
    {
      rez[ic]=V[i][j];
      ic++;
    }
  }
  return rez;
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>::Matrix(const size_t nrow, const size_t ncol, const bool makeIdentity)
Stuart Ansell's avatar
Stuart Ansell committed
  : nx(0),ny(0),V(0)
Stuart Ansell's avatar
Stuart Ansell committed
    Constructor with pre-set sizes. Matrix is zeroed
    @param nrow :: number of rows
    @param ncol :: number of columns
    @param makeIdentity :: flag for the constructor to return an identity matrix
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  // Note:: nx,ny zeroed so setMem always works
  setMem(nrow,ncol);
  zeroMatrix();
Stuart Ansell's avatar
Stuart Ansell committed
}

template<typename T>
Matrix<T>::Matrix(const std::vector<T>& A,const std::vector<T>& B)
  : nx(0),ny(0),V(0)
Stuart Ansell's avatar
Stuart Ansell committed
    Constructor to take two vectors and multiply them to 
    construct a matrix. (assuming that we have columns x row
    vector.
    @param A :: Column vector to multiply
    @param B :: Row vector to multiply
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  // Note:: nx,ny zeroed so setMem always works
  setMem(A.size(),B.size());
Stuart Ansell's avatar
Stuart Ansell committed
      V[i][j]=A[i]*B[j];
Stuart Ansell's avatar
Stuart Ansell committed
}
Matrix<T>::Matrix(const std::vector<T>&data) : nx(0),ny(0),V(0)
        size_t numel = data.size();
        size_t nxt =(size_t)sqrt(double(numel));
        size_t test = nxt*nxt;
        if(test != numel){
                throw(std::invalid_argument("number of elements in input vector have to be square of some value"));
        }

        setMem(nxt,nxt);

        size_t ic(0);
        for(size_t i=0;i<nx;i++)
        {
                for(size_t j=0;j<ny;j++)
                {
                        V[i][j]=data[ic];
                        ic++;
                }
        }  
Stuart Ansell's avatar
Stuart Ansell committed

template<typename T>
Matrix<T>::Matrix(const Matrix<T>& A,const size_t nrow,const size_t ncol)
  : nx(A.nx-1),ny(A.ny-1),V(0)
  /**
    Constructor with for a missing row/column.
    @param A :: The input matrix
    @param nrow :: number of row to miss
    @param ncol :: number of column to miss
  */
{
  // Note:: nx,ny zeroed so setMem always works
    throw Kernel::Exception::IndexError(nrow,A.nx, "Matrix::Constructor without col");
    throw Kernel::Exception::IndexError(ncol,A.ny, "Matrix::Constructor without col");
  setMem(nx,ny);
  size_t iR(0);
  for(size_t i=0;i<=nx;i++)
  {
    if (i!=nrow)
    {
      size_t jR(0);
      for(size_t j=0;j<=ny;j++)
      {
        if (j!=ncol)
        {
          V[iR][jR]=A.V[i][j];
          jR++;
        }
      }
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>::Matrix(const Matrix<T>& A)
  : nx(0),ny(0),V(0)
Stuart Ansell's avatar
Stuart Ansell committed
    Simple copy constructor
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  // Note:: nx,ny zeroed so setMem always works
  setMem(A.nx,A.ny);
  if (nx*ny)
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
    }
Stuart Ansell's avatar
Stuart Ansell committed
}


template<typename T>
Matrix<T>&
Matrix<T>::operator=(const Matrix<T>& A)
Stuart Ansell's avatar
Stuart Ansell committed
    Simple assignment operator 
    @param A :: Object to copy
    @return the copied object
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (&A!=this)
    {
      setMem(A.nx,A.ny);
      if (nx*ny)
        for(size_t i=0;i<nx;i++)
        {
          for(size_t j=0;j<ny;j++)
          {
            V[i][j]=A.V[i][j];
          }
        }
Stuart Ansell's avatar
Stuart Ansell committed
    }
  return *this;
}

template<typename T>
Matrix<T>::~Matrix()
Stuart Ansell's avatar
Stuart Ansell committed
    Delete operator :: removes memory for 
    matrix
  */
{
  deleteMem();
}


template<typename T>
Matrix<T>&
Matrix<T>::operator+=(const Matrix<T>& A)
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix addition THIS + A  
     If the size is different then 0 is added where appropiate
     Matrix A is not expanded.
     @param A :: Matrix to add
     @return Matrix(this + A)
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  const size_t Xpt((nx>A.nx) ? A.nx : nx);
  const size_t Ypt((ny>A.ny) ? A.ny : ny);
  for(size_t i=0;i<Xpt;i++)
  {
    for(size_t j=0;j<Ypt;j++)
    {
Stuart Ansell's avatar
Stuart Ansell committed
      V[i][j]+=A.V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed

  return *this;
}

template<typename T>
Matrix<T>&
Matrix<T>::operator-=(const Matrix<T>& A)
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix subtractoin THIS - A  
     If the size is different then 0 is added where appropiate
     Matrix A is not expanded.
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  const size_t Xpt((nx>A.nx) ? A.nx : nx);
  const size_t Ypt((ny>A.ny) ? A.ny : ny);
Stuart Ansell's avatar
Stuart Ansell committed
      V[i][j]-=A.V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed

  return *this;
}

template<typename T>
Matrix<T>
Matrix<T>::operator+(const Matrix<T>& A) const
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix addition THIS + A  
     If the size is different then 0 is added where appropiate
     Matrix A is not expanded.
     @param A :: Matrix to add
     @return Matrix(this + A)
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  Matrix<T> X(*this);
  return X+=A;
}

template<typename T>
Matrix<T>
Matrix<T>::operator-(const Matrix<T>& A) const
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix subtraction THIS - A  
     If the size is different then 0 is subtracted where 
     appropiate. This matrix determines the size 
     @param A :: Matrix to add
     @return Matrix(this + A)
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  Matrix<T> X(*this);
  return X-=A;
}
Nick Draper's avatar
Nick Draper committed
  
Stuart Ansell's avatar
Stuart Ansell committed

template<typename T>
Matrix<T>
Matrix<T>::operator*(const Matrix<T>& A) const
Stuart Ansell's avatar
Stuart Ansell committed
    Matrix multiplication THIS * A  
    @param A :: Matrix to multiply by  (this->row must == A->columns)
Stuart Ansell's avatar
Stuart Ansell committed
 */
{
  if (ny!=A.nx)
    throw Kernel::Exception::MisMatch<size_t>(ny,A.nx,"Matrix::operator*(Matrix)");
Stuart Ansell's avatar
Stuart Ansell committed
  Matrix<T> X(nx,A.ny);
  for(size_t i=0;i<nx;i++)
  {
    for(size_t j=0;j<A.ny;j++)
    {
      for(size_t kk=0;kk<ny;kk++)
      {
Stuart Ansell's avatar
Stuart Ansell committed
  return X;
}

template<typename T>
std::vector<T>
Matrix<T>::operator*(const std::vector<T>& Vec) const
Stuart Ansell's avatar
Stuart Ansell committed
    Matrix multiplication THIS * Vec to produce a vec  
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  std::vector<T> Out;
    throw Kernel::Exception::MisMatch<size_t>(ny,Vec.size(),"Matrix::operator*(Vec)");
Stuart Ansell's avatar
Stuart Ansell committed

  Out.resize(nx);
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
    }
Stuart Ansell's avatar
Stuart Ansell committed
  return Out;
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
V3D 
Matrix<T>::operator*(const V3D& Vx) const
Stuart Ansell's avatar
Stuart Ansell committed
    Matrix multiplication THIS * V
Stuart Ansell's avatar
Stuart Ansell committed
 */
{
  if (ny!=3)
    throw Kernel::Exception::MisMatch<size_t>(ny,3,"Matrix::operator*(V3D)");
Stuart Ansell's avatar
Stuart Ansell committed
      X[i]+=V[i][kk]*Vx[kk];
Stuart Ansell's avatar
Stuart Ansell committed
  return X;
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>
Matrix<T>::operator*(const T& Value) const
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix multiplication THIS * Value  
     @param Value :: Scalar to multiply by
     @return V * (this)
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  Matrix<T> X(*this);
Stuart Ansell's avatar
Stuart Ansell committed
      X.V[i][j]*=Value;
Stuart Ansell's avatar
Stuart Ansell committed
  return X;
}

/**
  Matrix multiplication THIS *= A
  Note that we call operator* to avoid the problem
  of changing matrix size.
 @param A :: Matrix to multiply by  (this->row must == A->columns)
 @return This *= A
*/
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>&
Matrix<T>::operator*=(const Matrix<T>& A)
{
  if (ny!=A.nx)
    throw Kernel::Exception::MisMatch<size_t>(ny,A.nx,"Matrix*=(Matrix<T>)");
Stuart Ansell's avatar
Stuart Ansell committed
  // This construct to avoid the problem of changing size
  *this = this->operator*(A);
  return *this;
}

template<typename T>
Matrix<T>&
Matrix<T>::operator*=(const T& Value)
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix multiplication THIS * Value  
     @param Value :: Scalar to multiply matrix by
     @return *this
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
Stuart Ansell's avatar
Stuart Ansell committed
      V[i][j]*=Value;
Stuart Ansell's avatar
Stuart Ansell committed
  return *this;
}

template<typename T>
Matrix<T>&
Matrix<T>::operator/=(const T& Value)
Stuart Ansell's avatar
Stuart Ansell committed
     Matrix divishio THIS / Value  
     @param Value :: Scalar to multiply matrix by
     @return *this
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
Stuart Ansell's avatar
Stuart Ansell committed
      V[i][j]/=Value;
Stuart Ansell's avatar
Stuart Ansell committed
  return *this;
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Nick Draper's avatar
Nick Draper committed
bool
Stuart Ansell's avatar
Stuart Ansell committed
Matrix<T>::operator!=(const Matrix<T>& A) const
Nick Draper's avatar
Nick Draper committed
Element by Element comparison
@param A :: Matrix to check
@return true :: on succees
@return false :: failure
Nick Draper's avatar
Nick Draper committed
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
Nick Draper's avatar
Nick Draper committed
  return (this->operator==(A));
Stuart Ansell's avatar
Stuart Ansell committed
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
bool Matrix<T>::operator==(const Matrix<T>& A) const
Nick Draper's avatar
Nick Draper committed
Element by element comparison within tolerance.
Tolerance means that the value must be > tolerance
and less than (diff/max)>tolerance 
Stuart Ansell's avatar
Stuart Ansell committed

Nick Draper's avatar
Nick Draper committed
Always returns 0 if the Matrix have different sizes
@param A :: matrix to check.
@return true on success 
Nick Draper's avatar
Nick Draper committed
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
//---------------------------------------------------------------------------------------
template<typename T>
bool Matrix<T>::equals(const Matrix<T>& A, const double Tolerance) const
/**
Element by element comparison within tolerance.
Tolerance means that the value must be > tolerance
and less than (diff/max)>tolerance

Always returns 0 if the Matrix have different sizes
@param A :: matrix to check.
@param Tolerance :: tolerance in comparing elements
@return true on success
*/
{
Stuart Ansell's avatar
Stuart Ansell committed
  if (&A!=this)       // this == A == always true
Nick Draper's avatar
Nick Draper committed
  {
    if(A.nx!=nx || A.ny!=ny)
      return false;
Stuart Ansell's avatar
Stuart Ansell committed

Nick Draper's avatar
Nick Draper committed
    double maxS(0.0);
    double maxDiff(0.0);   // max di
Nick Draper's avatar
Nick Draper committed
      {
        const T diff=(V[i][j]-A.V[i][j]);
        if (fabs(diff)>maxDiff)
          maxDiff=fabs(diff);
        if (fabs(V[i][j])>maxS)
          maxS=fabs(V[i][j]);
      }
Stuart Ansell's avatar
Stuart Ansell committed
      if (maxDiff<Tolerance)
Nick Draper's avatar
Nick Draper committed
        return true;
Stuart Ansell's avatar
Stuart Ansell committed
      if (maxS>1.0 && (maxDiff/maxS)<Tolerance)
Nick Draper's avatar
Nick Draper committed
        return true;
      return false;
  }
Stuart Ansell's avatar
Stuart Ansell committed
  //this == this is true
Nick Draper's avatar
Nick Draper committed
  return true;
Stuart Ansell's avatar
Stuart Ansell committed
}

//---------------------------------------------------------------------------------------
/** Element by element comparison of <
Always returns false if the Matrix have different sizes
@param A :: matrix to check.
@return true if this < A
*/
template<typename T>
bool Matrix<T>::operator<(const Matrix<T>& A) const
{
  if (&A == this)       // this < A == always false
    return false;

  if(A.nx!=nx || A.ny!=ny)
    return false;

  for(size_t i=0;i<nx;i++)
    for(size_t j=0;j<ny;j++)
    {
      if (V[i][j] >= A.V[i][j])
        return false;
    }
  return true;
}


//---------------------------------------------------------------------------------------
/** Element by element comparison of >=
Always returns false if the Matrix have different sizes
@param A :: matrix to check.
@return true if this >= A
*/
template<typename T>
bool Matrix<T>::operator>=(const Matrix<T>& A) const
{
  if (&A == this)
    return true;

  if(A.nx!=nx || A.ny!=ny)
    return false;

  for(size_t i=0;i<nx;i++)
    for(size_t j=0;j<ny;j++)
    {
      if (V[i][j] < A.V[i][j])
        return false;
    }
  return true;
}


//---------------------------------------------------------------------------------------
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
void
Matrix<T>::deleteMem()
Stuart Ansell's avatar
Stuart Ansell committed
    Deletes the memory held in matrix 
  */
{
  if (V)
    {
      delete [] *V;
      delete [] V;
      V=0;
    }
  nx=0;
  ny=0;
  return;
}


/**
  Sets the memory held in matrix
  @param a :: number of rows
  @param b :: number of columns
*/
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
void
Matrix<T>::setMem(const size_t a,const size_t b)
Stuart Ansell's avatar
Stuart Ansell committed
{
  if (a==nx && b==ny) 
    return;

  deleteMem();
  if (a<=0 || b<=0)
    return;

  nx=a;
  ny=b;  
  if (nx*ny)
    {
      T* tmpX=new T[nx*ny];
      V=new T*[nx];
Stuart Ansell's avatar
Stuart Ansell committed
    }
  return;
}  


/**
  Swap rows I and J
  @param RowI :: row I to swap
  @param RowJ :: row J to swap
*/
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T> 
void
Matrix<T>::swapRows(const size_t RowI,const size_t RowJ)
Stuart Ansell's avatar
Stuart Ansell committed
{
  if (nx*ny && RowI<nx && RowJ<nx && RowI!=RowJ) 
  {
    for(size_t k=0;k<ny;k++)
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
    }
Stuart Ansell's avatar
Stuart Ansell committed
  return;
}


/**
  Swap columns I and J
  @param colI :: col I to swap
  @param colJ :: col J to swap
*/
Stuart Ansell's avatar
Stuart Ansell committed
template<typename T> 
void
Matrix<T>::swapCols(const size_t colI, const size_t colJ)
Stuart Ansell's avatar
Stuart Ansell committed
{
  if (nx*ny && colI<ny && colJ<ny && colI!=colJ) 
  {
    for(size_t k=0;k<nx;k++)
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> 
void
Matrix<T>::zeroMatrix()
Stuart Ansell's avatar
Stuart Ansell committed
    Zeros all elements of the matrix 
  */
{
  if (nx*ny)
Stuart Ansell's avatar
Stuart Ansell committed
  return;
}

template<typename T> 
void
Matrix<T>::identityMatrix()
Stuart Ansell's avatar
Stuart Ansell committed
    Makes the matrix an idenity matrix.
    Zeros all the terms outside of the square
  */
{
  if (nx*ny)
Stuart Ansell's avatar
Stuart Ansell committed
  return;
}
Matrix<T>::setColumn(const size_t nCol,const std::vector<T> &newCol)
        if(nCol>=this->ny){
                throw(std::invalid_argument("nCol requested> nCol availible"));
        }
        size_t nxM = newCol.size();
        if(nx < nxM) nxM=nx;
        for(size_t i=0; i< nxM;i++)
Matrix<T>::setRow(const size_t nRow,const std::vector<T> &newRow)
        if(nRow>=this->nx){
                throw(std::invalid_argument("nRow requested> nRow availible"));
        }
        size_t nyM = newRow.size();
        if(ny < nyM) nyM=ny;
        for(size_t j=0; j < nyM;j++)
Stuart Ansell's avatar
Stuart Ansell committed

template<typename T>
void
Matrix<T>::rotate(const double tau,const double s,const int i,const int j,
Stuart Ansell's avatar
Stuart Ansell committed
    Applies a rotation to a particular point of tan(theta)=tau.
    Note that you need both sin(theta) and tan(theta) because of 
    sign preservation. 
    @param tau :: tan(theta) 
    @param s :: sin(theta)
    @param i ::  first index (xpos) 
    @param j ::  first index (ypos) 
    @param k ::  second index (xpos) 
    @param m ::  second index (ypos) 
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  const T gg=V[i][j];
  const T hh=V[k][m]; 
  V[i][j]=static_cast<T>(gg-s*(hh+gg*tau));
  V[k][m]=static_cast<T>(hh+s*(gg-hh*tau));
  return;
}

template<typename T>
Matrix<T>
Matrix<T>::fDiagonal(const std::vector<T>& Dvec) const
Stuart Ansell's avatar
Stuart Ansell committed
    Calculate the forward diagonal product.
    Construct a matrix based on  Dvec * This, 
    where Dvec is made into a diagonal matrix.
    @param Dvec :: diagonal matrix (just centre points)
    @return D*this
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  // Note:: nx,ny zeroed so setMem always works
Stuart Ansell's avatar
Stuart Ansell committed
    {
      std::ostringstream cx;
      cx<<"Matrix::fDiagonal Size: "<<Dvec.size()<<" "<<nx<<" "<<ny;
Nick Draper's avatar
Nick Draper committed
      throw std::runtime_error(cx.str());
Stuart Ansell's avatar
Stuart Ansell committed
    }
  Matrix<T> X(Dvec.size(),ny);
  for(size_t i=0; i < Dvec.size();i++)
  {
    for(size_t j=0;j<ny;j++)
    {
Stuart Ansell's avatar
Stuart Ansell committed
      X.V[i][j]=Dvec[i]*V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed
  return X;
}

template<typename T>
Matrix<T>
Matrix<T>::bDiagonal(const std::vector<T>& Dvec) const
Stuart Ansell's avatar
Stuart Ansell committed
    Calculate the backward diagonal product.
Stuart Ansell's avatar
Stuart Ansell committed
    Construct a matrix based on 
Stuart Ansell's avatar
Stuart Ansell committed
    This * Dvec, where Dvec is made into a diagonal 
Stuart Ansell's avatar
Stuart Ansell committed
    matrix.
    @param Dvec :: diagonal matrix (just centre points)
    @return this*D
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  // Note:: nx,ny zeroed so setMem always works
Stuart Ansell's avatar
Stuart Ansell committed
    {
      std::ostringstream cx;
      cx<<"Error Matrix::bDiaognal size:: "<<Dvec.size()
Nick Draper's avatar
Nick Draper committed
      throw std::runtime_error(cx.str());
Stuart Ansell's avatar
Stuart Ansell committed
    }

  Matrix<T> X(nx,Dvec.size());
  for(size_t i=0;i<nx;i++)
  {
    for(size_t j=0;j<Dvec.size();j++)
    {
Stuart Ansell's avatar
Stuart Ansell committed
      X.V[i][j]=Dvec[j]*V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed
  return X;
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>
Matrix<T>::Tprime() const
Stuart Ansell's avatar
Stuart Ansell committed
    Transpose the matrix : 
    Has transpose for a square matrix case.
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (!nx*ny)
    return *this;

  if (nx==ny)   // inplace transpose
    {
      Matrix<T> MT(*this);
      MT.Transpose();
      return MT;
    }

  // irregular matrix
  Matrix<T> MT(ny,nx);
Stuart Ansell's avatar
Stuart Ansell committed
      MT.V[j][i]=V[i][j];

  return MT;
}

Stuart Ansell's avatar
Stuart Ansell committed
template<typename T>
Matrix<T>&
Matrix<T>::Transpose()
Stuart Ansell's avatar
Stuart Ansell committed
    Transpose the matrix : 
    Has a inplace transpose for a square matrix case.
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  if (!nx*ny)
    return *this;
  if (nx==ny)   // inplace transpose
Stuart Ansell's avatar
Stuart Ansell committed
    {
Stuart Ansell's avatar
Stuart Ansell committed
    }
Stuart Ansell's avatar
Stuart Ansell committed
  // irregular matrix
  // get some memory
  T* tmpX=new T[ny*nx];
  T** Vt=new T*[ny];
  for (size_t i=0;i<ny;i++)
  {
    Vt[i] = tmpX + (i*nx);
  } 
  for(size_t i=0;i<nx;i++)
  {
    for(size_t j=0;j<ny;j++)
    {
Stuart Ansell's avatar
Stuart Ansell committed
      Vt[j][i]=V[i][j];
Stuart Ansell's avatar
Stuart Ansell committed
  // remove old memory
Stuart Ansell's avatar
Stuart Ansell committed
  deleteMem();  // resets nx,ny
  // replace memory
  V=Vt;
  nx=ty;
  ny=tx;

  return *this;
}

template<>
int
Matrix<int>::GaussJordan(Kernel::Matrix<int>&)
Stuart Ansell's avatar
Stuart Ansell committed
    Not valid for Integer
Stuart Ansell's avatar
Stuart Ansell committed
  */
{
  return 0;
}

template<typename T>
int
Matrix<T>::GaussJordan(Matrix<T>& B)
Stuart Ansell's avatar
Stuart Ansell committed
    Invert this Matrix and solve the 
    form such that if A.x=B then  solve to generate x.  
    This requires that B is B[A.nx][Any]
    The result is placed back in B
Stuart Ansell's avatar
Stuart Ansell committed
   */
{
  // check for input errors
  if (nx!=ny || B.nx!=nx)
    return -1;
  
  // pivoted rows 
  std::vector<int> pivoted(nx);
  fill(pivoted.begin(),pivoted.end(),0);

  std::vector<int> indxcol(nx);   // Column index
Stuart Ansell's avatar
Stuart Ansell committed
  std::vector<int> indxrow(nx);   // row index

  size_t irow(0),icol(0);
  for(size_t i=0;i<nx;i++)
  {
    // Get Biggest non-pivoted item
    double bigItem=0.0;         // get point to pivot over
    for(size_t j=0;j<nx;j++)
        {
            if (pivoted[j]!= 1)  //check only non-pivots
            {
              for(size_t k=0;k<nx;k++)
        {
                if (!pivoted[k])
                      {
                        if (fabs(V[j][k]) >=bigItem)
                        {
                                bigItem=fabs(V[j][k]);
                                irow=j;
                                icol=k;
                        }
                  }
              throw std::runtime_error("Error doing G-J elem on a singular matrix");
      }
    }
    pivoted[icol]++;
    // Swap in row/col to make a diagonal item 
    if (irow != icol)