/* * rmatrix.h * (C) Porkolab Zoltan, ELTE, Budapest, Hungary * (C) 2003 */ #ifndef RMATRIX_H #define RMATRIX_H #include <map> #include <stdexcept> template <typename T> class rmatrix { public: class index { public: index(int i, int j, int k) : i_(i), j_(j), k_(k) { } int size() const { return i_ * j_ * k_; } bool operator<( const index& rhs) const; const int i_; const int j_; const int k_; }; // in real good implementation iterator would be inherited from // map<index,T>::iterator, see: mmatrix_with_map.h typedef typename std::map<index,T>::iterator iterator; typedef typename std::map<index,T>::const_iterator const_iterator; rmatrix(int i, int j, int k) : size_(index(i,j,k)) { } int size() const { return size_.size(); } bool stored(int i, int j, int k) const; T& at(int i, int j, int k) /* throw (std::out_of_range) */; T at(int i, int j, int k) const /* throw (std::out_of_range) */; T& operator()(int i, int j, int k) /* throw () */; T operator()(int i, int j, int k) const /* throw () */; iterator begin() { return m_.begin(); } const_iterator begin() const { return m_.begin(); } iterator end() { return m_.end(); } const_iterator end() const { return m_.end(); } private: const index size_; std::map<index,T> m_; void check_range(int i,int j,int k) const /* throw (std::out_of_range) */; const_iterator stored_at(int i, int j, int k) const; }; template <typename T> bool rmatrix<T>::index::operator<( const index& rhs) const { return ( i_ < rhs.i_ ) || ( i_ == rhs.i_ && j_ < rhs.j_ ) || ( i_ == rhs.i_ && j_ == rhs.j_ && k_ < rhs.k_ ); } template <typename T> typename rmatrix<T>::const_iterator rmatrix<T>::stored_at(int i, int j, int k) const { return m_.find(index(i,j,k)); } template <typename T> bool rmatrix<T>::stored(int i, int j, int k) const { return end() != stored_at(i,j,k); } template <typename T> T& rmatrix<T>::operator()(int i, int j, int k) { // may create new entry return m_[index(i,j,k)]; } template <typename T> T rmatrix<T>::operator()(int i, int j, int k) const { const_iterator ci = stored_at(i,j,k); return ci == end() ? T() : ci->second; } template <typename T> void rmatrix<T>::check_range(int i, int j, int k) const { if ( 0 <= i && i < size_.i_ && 0 <= j && j < size_.j_ && 0 <= k && k < size_.k_ ) /* range is OK */ ; else throw std::out_of_range("bad index"); } template <typename T> T& rmatrix<T>::at(int i, int j, int k) { check_range(i,j,k); return operator()(i,j,k); } template <typename T> T rmatrix<T>::at(int i, int j, int k) const { check_range(i,j,k); return operator()(i,j,k); } #endif /* RMATRIX_H */