Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TLIN_SPARSEMAT_H
Toshihiro Shimizu 890ddd
#define TLIN_SPARSEMAT_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tlin_basicops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcg/tcg_hash.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace tlin {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  The tlin::sparse_matrix class implements a hash-based format for storing
Shinya Kitaoka 120a6e
  sparse
Toshihiro Shimizu 890ddd
  matrices.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  A tlin::sparse_matrix is a tlin::matrix-compliant class that allows the user
Shinya Kitaoka 120a6e
  to
Shinya Kitaoka 120a6e
  access the matrix in a purely random fashion, without sacrificing storage
Shinya Kitaoka 120a6e
  space or
Shinya Kitaoka 120a6e
  efficiency. This is achieved using a single, fast, dynamic hash container that
Shinya Kitaoka 120a6e
  maps
Toshihiro Shimizu 890ddd
  (row, col) entries into their values, the hash function being like:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    (row, col) -> row * nCols + col;    (taken modulo nBuckets)
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
  Observe that if the number of buckets of the hash map is nCols, the resulting
Toshihiro Shimizu 890ddd
  representation is similar to a CCS (Harwell-Boeing), with the difference that
Toshihiro Shimizu 890ddd
  buckets are not sorted by row.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Shinya Kitaoka 120a6e
class sparse_matrix {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  struct IdxFunctor {
Shinya Kitaoka 120a6e
    int m_cols;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    IdxFunctor(int cols) : m_cols(cols) {}
Shinya Kitaoka 120a6e
    int operator()(const std::pair<int, int=""> &key) {</int,>
Shinya Kitaoka 120a6e
      return key.first * m_cols + key.second;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  int m_rows;
Shinya Kitaoka 120a6e
  int m_cols;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tcg::hash<std::pair<int, int="">, T, IdxFunctor> m_hash;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  sparse_matrix() : m_rows(0), m_cols(0), m_hash(IdxFunctor(0)) {}
Shinya Kitaoka 120a6e
  sparse_matrix(int rows, int cols)
Shinya Kitaoka 120a6e
      : m_rows(rows), m_cols(cols), m_hash(cols) {}
Shinya Kitaoka 120a6e
  ~sparse_matrix() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  sparse_matrix(const sparse_matrix &mat)
Shinya Kitaoka 120a6e
      : m_rows(mat.m_rows), m_cols(mat.m_cols), m_hash(mat.m_hash) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  sparse_matrix &operator=(const sparse_matrix &mat) {
Shinya Kitaoka 120a6e
    m_rows = mat.m_rows, m_cols = mat.m_cols, m_hash = mat.m_hash;
Shinya Kitaoka 120a6e
    return *this;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int rows() const { return m_rows; }
Shinya Kitaoka 120a6e
  int cols() const { return m_cols; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  typedef typename tcg::hash<std::pair<int, int="">, T, IdxFunctor> HashMap;</std::pair<int,>
Shinya Kitaoka 120a6e
  tcg::hash<std::pair<int, int="">, T, IdxFunctor> &entries() { return m_hash; }</std::pair<int,>
Shinya Kitaoka 120a6e
  const tcg::hash<std::pair<int, int="">, T, IdxFunctor> &entries() const {</std::pair<int,>
Shinya Kitaoka 120a6e
    return m_hash;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //!\warning Assignments of kind: A.at(1,1) = A.at(0,0) are potentially
Shinya Kitaoka 120a6e
  //!harmful.
Shinya Kitaoka 120a6e
  //! Use A.get(x,y) on the right side instead.
Shinya Kitaoka 120a6e
  T &at(int row, int col) { return m_hash.touch(std::make_pair(row, col), 0); }
Shinya Kitaoka 120a6e
  const T get(int row, int col) const {
Shinya Kitaoka 120a6e
    typename HashMap::const_iterator it = m_hash.find(std::make_pair(row, col));
Shinya Kitaoka 120a6e
    return (it == m_hash.end()) ? 0 : it->m_val;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  const T operator()(int row, int col) const { return get(row, col); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void clear() { m_hash.clear(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  friend void swap(sparse_matrix &a, sparse_matrix &b) {
Shinya Kitaoka 120a6e
    using std::swap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    swap(a.m_rows, b.m_rows), swap(a.m_cols, b.m_cols);
Shinya Kitaoka 120a6e
    swap(a.m_hash, b.m_hash);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  The Standard matrix data type in tlin is double
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef tlin::sparse_matrix<double> spmat;</double>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TLIN_SPARSEMAT_H