Skip to content
Snippets Groups Projects
Matrix.cpp 48 KiB
Newer Older
template <typename T>
T Matrix<T>::determinant() const
/**
  Calculate the derminant of the matrix
  @return Determinant of matrix.
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
  if (m_numRows != m_numColumns)
    throw Kernel::Exception::MisMatch<size_t>(
        m_numRows, m_numColumns, "Determinant error :: Matrix is not square");
Stuart Ansell's avatar
Stuart Ansell committed

  Matrix<T> Mt(*this); // temp copy
  T D = Mt.factor();
Stuart Ansell's avatar
Stuart Ansell committed
  return D;
}

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

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

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

template <typename T>
T Matrix<T>::compSum() const
/**
  Add up each component sums for the matrix
  @return \f$ \sum_i \sum_j V_{ij}^2 \f$
 */
Stuart Ansell's avatar
Stuart Ansell committed
{
  T sum(0);
  for (size_t i = 0; i < m_numRows; i++) {
    for (size_t j = 0; j < m_numColumns; j++) {
      sum += m_rawData[i][j] * m_rawData[i][j];
Stuart Ansell's avatar
Stuart Ansell committed
  return sum;
}

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

  if (m_numRows != m_numColumns || m_numRows < 2) {
    std::cerr << "Error with lubcmp\n";
  std::vector<double> result(m_numRows);
  interchange = 1;
  for (int i = 0; i < static_cast<int>(m_numRows); i++) {
    for (int j = 0; j < static_cast<int>(m_numRows); j++)
      if ((temp = fabs(m_rawData[i][j])) > big)
        big = temp;

    if (big == 0.0) {
      for (int j = 0; j < static_cast<int>(m_numRows); j++) {
        rowperm[j] = j;
      }
Stuart Ansell's avatar
Stuart Ansell committed
      return;
    }
Stuart Ansell's avatar
Stuart Ansell committed

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

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

template <typename T>
void Matrix<T>::lubksb(const int *rowperm, double *b)
/**
  Implements a separation of the Matrix
  into a triangular matrix
Stuart Ansell's avatar
Stuart Ansell committed
{
Stuart Ansell's avatar
Stuart Ansell committed

  for (int i = 0; i < static_cast<int>(m_numRows); i++) {
    int ip = rowperm[i];
    double sum = b[ip];
    b[ip] = b[i];
    if (ii != -1)
      for (int j = ii; j < i; j++)
        sum -= m_rawData[i][j] * b[j];
    else if (sum != 0.)
      ii = i;
    b[i] = sum;
  }

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

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

template <typename T>
std::vector<T> Matrix<T>::Diagonal() const
/**
  Returns the diagonal form as a vector
  @return Diagonal elements
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
  const size_t Msize = (m_numColumns > m_numRows) ? m_numRows : m_numColumns;
Stuart Ansell's avatar
Stuart Ansell committed
  std::vector<T> Diag(Msize);
  for (size_t i = 0; i < Msize; i++) {
    Diag[i] = m_rawData[i][i];
Stuart Ansell's avatar
Stuart Ansell committed
  return Diag;
}

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

template <typename T>
void Matrix<T>::sortEigen(Matrix<T> &DiagMatrix)
/**
  Sorts the eigenvalues into increasing
  size. Moves the EigenVectors correspondingly
  @param DiagMatrix :: matrix of the EigenValues
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
  if (m_numColumns != m_numRows || m_numRows != DiagMatrix.m_numRows ||
      m_numRows != DiagMatrix.m_numColumns) {
    std::cerr << "Matrix not Eigen Form\n";
    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);
Stuart Ansell's avatar
Stuart Ansell committed
  Matrix<T> EigenVec(*this);
  for (size_t Icol = 0; Icol < m_numRows; Icol++) {
    for (size_t j = 0; j < m_numRows; j++) {
      m_rawData[j][Icol] = EigenVec[j][index[Icol]];
    DiagMatrix[Icol][Icol] = X[index[Icol]];
Stuart Ansell's avatar
Stuart Ansell committed
}

template <typename T>
int Matrix<T>::Diagonalise(Matrix<T> &EigenVec, Matrix<T> &DiagMatrix) const
/**
  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 (m_numRows != m_numColumns || m_numRows < 1) {
    std::cerr << "Matrix not square\n";
  for (size_t i = 0; i < m_numRows; i++)
    for (size_t j = i + 1; j < m_numRows; j++)
      if (fabs(m_rawData[i][j] - m_rawData[j][i]) > 1e-6) {
        std::cerr << "Matrix not symmetric\n";
        std::cerr << (*this);
        return 0;
      }

Stuart Ansell's avatar
Stuart Ansell committed
  Matrix<T> A(*this);
  // Make V an identity matrix
  EigenVec.setMem(m_numRows, m_numRows);
Stuart Ansell's avatar
Stuart Ansell committed
  EigenVec.identityMatrix();
  DiagMatrix.setMem(m_numRows, m_numRows);
Stuart Ansell's avatar
Stuart Ansell committed
  DiagMatrix.zeroMatrix();

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

  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 ip = 0; ip < m_numRows - 1; ip++)
      for (size_t iq = ip + 1; iq < m_numRows; iq++)
        sm += fabs(A.m_rawData[ip][iq]);

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

    // Threshold large for first 5 sweeps
        (i < 6) ? 0.2 * sm / static_cast<int>(m_numRows * m_numRows) : 0.0;
    for (int ip = 0; ip < static_cast<int>(m_numRows) - 1; ip++) {
      for (int iq = ip + 1; iq < static_cast<int>(m_numRows); iq++) {
        double g = 100.0 * fabs(A.m_rawData[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.m_rawData[ip][iq] = 0;
        else if (fabs(A.m_rawData[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.m_rawData[ip][iq] / h; // tanAngle=1/(2theta)
            double theta = 0.5 * h / A.m_rawData[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.m_rawData[ip][iq];
          ZeroComp[ip] -= h;
          ZeroComp[iq] += h;
          Diag[ip] -= h;
          Diag[iq] += h;
          A.m_rawData[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>(m_numRows); j++)
            A.rotate(tau, sinAngle, ip, j, iq, j);
          for (int j = 0; j < static_cast<int>(m_numRows); j++)
            EigenVec.rotate(tau, sinAngle, j, ip, j, iq);
          iteration++;
    for (size_t j = 0; j < m_numRows; j++) {
      B[j] += ZeroComp[j];
      Diag[j] = B[j];
      ZeroComp[j] = 0.0;
Stuart Ansell's avatar
Stuart Ansell committed
    }
  std::cerr << "Error :: Iterations are a problem\n";
Stuart Ansell's avatar
Stuart Ansell committed
  return 0;
}

template <typename T>
bool Matrix<T>::isRotation() const
/** Check if a matrix represents a proper rotation
@ return :: true/false
*/
{
  if (this->m_numRows != this->m_numColumns)
    throw(std::invalid_argument("matrix is not square"));
  //  std::cout << "Matrix determinant-1 is " << (this->determinant()-1) <<
  if (fabs(this->determinant() - 1) > 1e-5) {
    Matrix<T> prod(m_numRows, m_numColumns),
        ident(m_numRows, m_numColumns, true);
    prod = this->operator*(this->Tprime());
    //    std::cout << "Matrix * Matrix' = " << std::endl << prod << '\n';
template <typename T>
bool Matrix<T>::isOrthogonal() const
/** Check if a matrix is orthogonal. Same as isRotation, but allows determinant
to be -1
  if (this->m_numRows != this->m_numColumns)
    throw(std::invalid_argument("matrix is not square"));
  if (fabs(fabs(this->determinant()) - 1.) > 1e-5) {
    Matrix<T> prod(m_numRows, m_numColumns),
        ident(m_numRows, m_numColumns, true);
    prod = this->operator*(this->Tprime());
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->m_numRows != this->m_numColumns)
    throw(std::invalid_argument("matrix is not square"));
  if (fabs(this->determinant()) < 1e-10)
    throw(std::invalid_argument("Determinant is too small"));
  for (size_t i = 0; i < this->m_numColumns; ++i) {
    double spself = 0.;
    for (size_t j = 0; j < this->m_numRows; ++j)
      spself += (m_rawData[j][i] * m_rawData[j][i]);
    for (size_t k = i + 1; k < this->m_numColumns; ++k) {
      double spother = 0;
      for (size_t j = 0; j < this->m_numRows; ++j)
        spother += (m_rawData[j][i] * m_rawData[j][k]);
      for (size_t j = 0; j < this->m_numRows; ++j)
        m_rawData[j][k] -= static_cast<T>(m_rawData[j][i] * spother / spself);
  std::vector<T> scale(this->m_numRows);
  for (size_t i = 0; i < this->m_numColumns; ++i) {
    T currentScale{0};
    for (size_t j = 0; j < this->m_numRows; ++j)
      currentScale += (m_rawData[j][i] * m_rawData[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(m_numRows, m_numColumns),
      change(m_numRows, m_numColumns, true);
  for (size_t i = 0; i < this->m_numColumns; ++i)
    scalingMatrix[i][i] = static_cast<T>(1.0 / scale[i]);
  if (this->determinant() < 0.) {
    scale[0] = -scale[0];
    change[0][0] = static_cast<T>(-1);
template <typename T>
void Matrix<T>::print() const
/**
  Simple print out routine
 */
Stuart Ansell's avatar
Stuart Ansell committed
{
  write(std::cout, 10);
Stuart Ansell's avatar
Stuart Ansell committed
}

/** 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 < m_numRows; i++) {
    for (size_t j = 0; j < m_numColumns; j++) {
      m_rawData[i][j] = static_cast<T>(rng.nextValue());
template <typename T>
void Matrix<T>::write(std::ostream &Fh, const int blockCnt) const
/**
  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 : m_numColumns);
  do {
    const size_t ACnt = BCnt;
    BCnt += blockNumber;
    if (BCnt > m_numColumns) {
      BCnt = m_numColumns;
Stuart Ansell's avatar
Stuart Ansell committed

      Fh << " ----- " << ACnt << " " << BCnt << " ------ \n";
    for (size_t i = 0; i < m_numRows; i++) {
      for (size_t j = ACnt; j < BCnt; j++) {
        Fh << std::setw(10) << m_rawData[i][j] << "  ";
  } while (BCnt < m_numColumns);
Stuart Ansell's avatar
Stuart Ansell committed

  Fh.flags(oldFlags);
}

template <typename T>
std::string Matrix<T>::str() const
/**
  Convert the matrix into a simple linear string expression
  @return String value of output
*/
Stuart Ansell's avatar
Stuart Ansell committed
{
  std::ostringstream cx;
  for (size_t i = 0; i < m_numRows; i++) {
    for (size_t j = 0; j < m_numColumns; j++) {
      cx << std::setprecision(6) << m_rawData[i][j] << " ";
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) {
 * 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) {
      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) {
* 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) {
    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.");
  if (!is)
    throw std::invalid_argument("Expected number of columns when reading "
                                "Matrix from stream, found something else.");
  if (dump != ')')
    throw std::invalid_argument("Expected closing parenthesis after ncols when "
                                "reading Matrix from stream, found something "
                                "else.");
  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.m_rawData[row][col] = value;
    } catch (boost::bad_lexical_cast &) {
      throw std::invalid_argument(
          "Unexpected type found while reading Matrix from stream: \"" +
          value_str + "\"");
    if (col == ncols) // New row
Stuart Ansell's avatar
Stuart Ansell committed
///\cond TEMPLATE

template class MANTID_KERNEL_DLL Matrix<double>;
// The explicit template instantiation for int does not have an export macro
// since this produces a warning on "gcc: warning: type attributes ignored after
// type is already define" The reason for this is the use of Matrix<int>
// in a template specialization above, causing an implicit sepcialization.
// This, most likely, obtains a visibility setting from the general template
// definition.
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