Newer
Older
Gigg, Martyn Anthony
committed
swapRows(irow,icol);
B.swapRows(irow,icol);
}
Gigg, Martyn Anthony
committed
indxrow[i]=static_cast<int>(irow);
indxcol[i]=static_cast<int>(icol);
if (V[icol][icol] == 0.0)
Gigg, Martyn Anthony
committed
{
std::cerr<<"Error doing G-J elem on a singular matrix"<<std::endl;
return 1;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
V[icol][icol]=1;
Gigg, Martyn Anthony
committed
for(size_t l=0;l<nx;l++)
Gigg, Martyn Anthony
committed
{
V[icol][l] *= pivDiv;
}
Gigg, Martyn Anthony
committed
for(size_t l=0;l<B.ny;l++)
Gigg, Martyn Anthony
committed
{
B.V[icol][l] *=pivDiv;
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
for(size_t ll=0;ll<nx;ll++)
Gigg, Martyn Anthony
committed
{
if (ll!=icol)
{
Gigg, Martyn Anthony
committed
V[ll][icol]=0.0;
Gigg, Martyn Anthony
committed
for(size_t l=0;l<nx;l++)
Gigg, Martyn Anthony
committed
{
V[ll][l] -= V[icol][l]*div_num;
}
Gigg, Martyn Anthony
committed
for(size_t l=0;l<B.ny;l++)
Gigg, Martyn Anthony
committed
{
B.V[ll][l] -= B.V[icol][l]*div_num;
}
}
}
}
Gigg, Martyn Anthony
committed
if( nx > 0 )
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
for(int l=static_cast<int>(nx)-1;l>=0;l--)
Gigg, Martyn Anthony
committed
{
if (indxrow[l] !=indxcol[l])
{
swapCols(indxrow[l],indxcol[l]);
}
}
}
return 0;
}
template<typename T>
std::vector<T>
Matrix<T>::Faddeev(Matrix<T>& InvOut)
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@param InvOut ::: output
@return Matrix self Polynomial (low->high coefficient order)
Gigg, Martyn Anthony
committed
throw Kernel::Exception::MisMatch<size_t>(nx,ny,"Matrix::Faddev(Matrix)");
Matrix<T>& A(*this);
Matrix<T> B(A);
Matrix<T> Ident(nx,ny);
T tVal=B.Trace(); // Trace of the matrix
std::vector<T> Poly;
Poly.push_back(1);
Poly.push_back(tVal);
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx-2;i++) // skip first (just copy) and last (to keep B-1)
Gigg, Martyn Anthony
committed
Poly.push_back(tVal/static_cast<T>(i+1));
}
// Last on need to keep B;
InvOut=B;
B=A*B - Ident*tVal;
tVal=B.Trace();
Gigg, Martyn Anthony
committed
Poly.push_back(tVal/static_cast<T>(nx));
InvOut-= Ident* (-Poly[nx-1]);
InvOut/= Poly.back();
return Poly;
}
template<typename T>
T
Matrix<T>::Invert()
Janik Zikovsky
committed
/**
If the Matrix is square then invert the matrix
using LU decomposition
Janik Zikovsky
committed
@return Determinant (0 if the matrix is singular)
*/
{
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);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
for(size_t j=0;j<nx;j++)
Gigg, Martyn Anthony
committed
for(size_t j=0;j<nx;j++)
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
Gigg, Martyn Anthony
committed
col[i]=0.0;
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
Gigg, Martyn Anthony
committed
V[i][j]=static_cast<T>(col[i]);
}
delete [] indx;
delete [] col;
return static_cast<T>(det);
}
template<typename T>
T
Matrix<T>::determinant() const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@return Determinant of matrix.
Gigg, Martyn Anthony
committed
throw Kernel::Exception::MisMatch<size_t>(nx,ny,
"Determinant error :: Matrix is not NxN");
Matrix<T> Mt(*this); //temp copy
T D=Mt.factor();
return D;
}
template<typename T>
T
Matrix<T>::factor()
Janik Zikovsky
committed
/**
Gauss jordan diagonal factorisation
The diagonal is left as the values,
the lower part is zero.
Janik Zikovsky
committed
@return the factored matrix
throw std::runtime_error("Matrix::factor Matrix is not NxN");
Gigg, Martyn Anthony
committed
for(int i=0;i<static_cast<int>(nx)-1;i++) //loop over each row
double Pmax=fabs(V[i][i]);
Gigg, Martyn Anthony
committed
for(int j=i+1;j<static_cast<int>(nx);j++) // find max in Row i
Gigg, Martyn Anthony
committed
if (fabs(V[i][j])>Pmax)
Gigg, Martyn Anthony
committed
Pmax=fabs(V[i][j]);
jmax=j;
}
}
// std::cerr<<"Matrix Singular"<<std::endl;
Gigg, Martyn Anthony
committed
return 0;
}
Gigg, Martyn Anthony
committed
swapCols(i,jmax);
deter*=-1; //change sign.
}
// zero all rows below diagonal
Pmax=V[i][i];
deter*=Pmax;
Gigg, Martyn Anthony
committed
for(int k=i+1;k<static_cast<int>(nx);k++) // row index
Gigg, Martyn Anthony
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]);
}
}
deter*=V[nx-1][nx-1];
return static_cast<T>(deter);
}
template<typename T>
void
Matrix<T>::normVert()
Janik Zikovsky
committed
/**
Normalise EigenVectors
Assumes that they have already been calculated
*/
{
Gigg, Martyn Anthony
committed
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++)
Gigg, Martyn Anthony
committed
V[i][j]/=sum;
Gigg, Martyn Anthony
committed
}
return;
}
template<typename T>
T
Matrix<T>::compSum() const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@return \f$ \sum_i \sum_j V_{ij}^2 \f$
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
{
for(size_t j=0;j<ny;j++)
{
Gigg, Martyn Anthony
committed
}
}
return sum;
}
template<typename T>
void
Matrix<T>::lubcmp(int* rowperm,int& interchange)
Janik Zikovsky
committed
/**
Find biggest pivot and move to top row. Then
divide by pivot.
Janik Zikovsky
committed
@param interchange :: odd/even nterchange (+/-1)
@param rowperm :: row permuations [nx values]
*/
{
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;
Gigg, Martyn Anthony
committed
for(int i=0;i<static_cast<int>(nx);i++)
for(int j=0;j<static_cast<int>(nx);j++)
Gigg, Martyn Anthony
committed
big=temp;
Gigg, Martyn Anthony
committed
delete [] vv;
return;
}
for (int j=0;j<static_cast<int>(nx);j++)
sum-= V[i][k] * V[k][j];
V[i][j]=static_cast<T>(sum);
}
big=0.0;
Gigg, Martyn Anthony
committed
for (int i=j;i<static_cast<int>(nx);i++)
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++)
{ //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);
Gigg, Martyn Anthony
committed
if (j != static_cast<int>(nx)-1)
Gigg, Martyn Anthony
committed
for(int i=j+1;i<static_cast<int>(nx);i++)
V[i][j] *= static_cast<T>(dum);
}
}
delete [] vv;
return;
}
template<typename T>
void
Matrix<T>::lubksb(const int* rowperm,double* b)
Janik Zikovsky
committed
/**
Impliments a separation of the Matrix
into a triangluar matrix
*/
{
int ii= -1;
Gigg, Martyn Anthony
committed
for(int i=0;i<static_cast<int>(nx);i++)
{
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];
for (int i=static_cast<int>(nx)-1;i>=0;i--)
Gigg, Martyn Anthony
committed
for (int j=i+1;j<static_cast<int>(nx);j++)
sum -= V[i][j] * b[j];
b[i]=sum/V[i][i];
}
return;
}
template<typename T>
void
Matrix<T>::averSymmetric()
Janik Zikovsky
committed
/**
Gigg, Martyn Anthony
committed
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];
}
}
}
template<typename T>
std::vector<T>
Matrix<T>::Diagonal() const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@return Diagonal elements
Gigg, Martyn Anthony
committed
const size_t Msize=(ny>nx) ? nx : ny;
Gigg, Martyn Anthony
committed
for(size_t i=0;i<Msize;i++)
{
Gigg, Martyn Anthony
committed
}
return Diag;
}
template<typename T>
T
Matrix<T>::Trace() const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@return Trace of matrix
Gigg, Martyn Anthony
committed
const size_t Msize=(ny>nx) ? nx : ny;
T Trx = 0;
for(size_t i=0; i < Msize; i++)
{
Gigg, Martyn Anthony
committed
}
return Trx;
}
template<typename T>
void
Matrix<T>::sortEigen(Matrix<T>& DiagMatrix)
Janik Zikovsky
committed
/**
Sorts the eigenvalues into increasing
size. Moves the EigenVectors correspondingly
Janik Zikovsky
committed
@param DiagMatrix :: matrix of the EigenValues
*/
{
if (ny!=nx || nx!=DiagMatrix.nx || nx!=DiagMatrix.ny)
{
std::cerr<<"Matrix not Eigen Form"<<std::endl;
Gigg, Martyn Anthony
committed
throw(std::invalid_argument(" Matrix is not in an eigenvalue format"));
}
std::vector<int> index;
std::vector<T> X=DiagMatrix.Diagonal();
indexSort(X,index);
Matrix<T> EigenVec(*this);
Gigg, Martyn Anthony
committed
for(size_t Icol=0;Icol<nx;Icol++)
Alex Buts
committed
{
Gigg, Martyn Anthony
committed
for(size_t j=0;j<nx;j++)
{
V[j][Icol]=EigenVec[j][index[Icol]];
}
DiagMatrix[Icol][Icol]=X[index[Icol]];
Alex Buts
committed
}
return;
}
template<typename T>
int
Matrix<T>::Diagonalise(Matrix<T>& EigenVec,Matrix<T>& DiagMatrix) const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@param EigenVec :: (output) the Eigenvectors matrix
@param DiagMatrix :: the diagonal matrix of eigenvalues
@return :: 1 on success 0 on failure
*/
{
if(nx!=ny || nx<1)
{
std::cerr<<"Matrix not square"<<std::endl;
return 0;
}
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
for(size_t j=i+1;j<nx;j++)
Gigg, Martyn Anthony
committed
std::cerr<<"Matrix not symmetric"<<std::endl;
std::cerr<< (*this);
return 0;
}
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
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
{
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
Gigg, Martyn Anthony
committed
for(size_t ip=0;ip<nx-1;ip++)
Gigg, Martyn Anthony
committed
for(size_t iq=ip+1;iq<nx;iq++)
sm+=fabs(A.V[ip][iq]);
Gigg, Martyn Anthony
committed
{
// 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;
}
double tresh= (i<6) ? 0.2*sm/static_cast<int>(nx*nx) : 0.0;
Gigg, Martyn Anthony
committed
for(int ip=0;ip<static_cast<int>(nx)-1;ip++)
Gigg, Martyn Anthony
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;
Gigg, Martyn Anthony
committed
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];
Gigg, Martyn Anthony
committed
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
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++;
}
}
}
Gigg, Martyn Anthony
committed
for(size_t j=0;j<nx;j++)
Gigg, Martyn Anthony
committed
{
B[j]+=ZeroComp[j];
Diag[j]=B[j];
ZeroComp[j]=0.0;
}
}
std::cerr<<"Error :: Iterations are a problem"<<std::endl;
return 0;
}
Savici, Andrei T.
committed
template<typename T>
bool Matrix<T>::isRotation() const
Savici, Andrei T.
committed
/** 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;
Savici, Andrei T.
committed
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);
Savici, Andrei T.
committed
}
}
Savici, Andrei T.
committed
template<typename T>
bool Matrix<T>::isOrthogonal() const
Savici, Andrei T.
committed
/** 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);
}
}
Savici, Andrei T.
committed
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)
{
Savici, Andrei T.
committed
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)
{
Savici, Andrei T.
committed
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)
{
currentScale=T(0.);
Savici, Andrei T.
committed
for (size_t j=0; j<this->nx;++j)
currentScale+=(V[j][i]*V[j][i]);
Savici, Andrei T.
committed
currentScale=static_cast<T>(sqrt(static_cast<double>(currentScale)));
Savici, Andrei T.
committed
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];
change[0][0]=(T)(-1);
Savici, Andrei T.
committed
*this = this->operator*(change);
}
return scale;
}
Janik Zikovsky
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());
}
}
}
template<typename T>
void
Matrix<T>::write(std::ostream& Fh,const int blockCnt) const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@param Fh :: file stream for output
@param blockCnt :: number of columns per line (0 == full)
*/
{
std::ios::fmtflags oldFlags=Fh.flags();
Fh.setf(std::ios::floatfield,std::ios::scientific);
Gigg, Martyn Anthony
committed
const size_t blockNumber((blockCnt>0) ? blockCnt : ny);
size_t BCnt(0);
Gigg, Martyn Anthony
committed
const size_t ACnt=BCnt;
BCnt += blockNumber;
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
BCnt=ny;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
Fh<<" ----- "<<ACnt<<" "<<BCnt<<" ------ "<<std::endl;
Gigg, Martyn Anthony
committed
}
for(size_t i=0;i<nx;i++)
{
for(size_t j=ACnt;j<BCnt;j++)
Gigg, Martyn Anthony
committed
Fh<<std::setw(10)<<V[i][j]<<" ";
}
Fh<<std::endl;
}
} while(BCnt<ny);
Fh.flags(oldFlags);
return;
}
template<typename T>
std::string
Matrix<T>::str() const
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@return String value of output
Gigg, Martyn Anthony
committed
for(size_t i=0;i<nx;i++)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
for(size_t j=0;j<ny;j++)
Gigg, Martyn Anthony
committed
{
cx<<std::setprecision(6)<<V[i][j]<<" ";
}
}
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
/**
* 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;
}
}
}
Gigg, Martyn Anthony
committed
// Symbol definitions for common types
Gigg, Martyn Anthony
committed
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);
Gigg, Martyn Anthony
committed
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, DblMatrix&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, DblMatrix&, const char);
Gigg, Martyn Anthony
committed
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);
Gigg, Martyn Anthony
committed
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, Matrix<float>&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, Matrix<float>&, const char);
Gigg, Martyn Anthony
committed
template MANTID_KERNEL_DLL std::ostream& operator<<(std::ostream&, const IntMatrix&);
template MANTID_KERNEL_DLL void dumpToStream(std::ostream&, const IntMatrix&, const char);
Gigg, Martyn Anthony
committed
template MANTID_KERNEL_DLL std::istream& operator>>(std::istream&, IntMatrix&);
template MANTID_KERNEL_DLL void fillFromStream(std::istream&, IntMatrix&, const char);
Gigg, Martyn Anthony
committed
} // namespace Kernel