/*
* 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 */