// this header defines template object matrix, and also necessary row #ifndef IMS_MATRIX_H #define IMS_MATRIX_H #include <vector> namespace ims { //////////////////////////////////////////////////////////////////////////////// // row type necessary for matrix template < typename T , typename A = std::allocator<T> > class row { public: //some typedefs (see Stroustrup pp 471) typedef T value_type; typedef typename A::size_type size_type; typedef std::vector<value_type, A> data_type; //iterators //typedef data_type::iterator iterator; typedef typename data_type::const_iterator const_iterator; //references typedef typename A::reference reference; typedef typename A::const_reference const_reference; //constructors row (size_type m, value_type v = value_type()) { data = std::vector<value_type> (m,v); } //index access reference operator[] (size_type j) { return data[j]; } const_reference operator[] (size_type j) const { return data[j]; } //get iterators const_iterator begin() const { return data.begin(); } const_iterator end() const { return data.end(); } //misc size_type size() const { return data.size(); } private: //data field data_type data; }; template < typename T, typename A = std::allocator<T> > class matrix { public: //some typedefs (see Stroustrup pp 471) typedef T value_type; typedef typename A::size_type size_type; typedef row<value_type> row_type; typedef std::vector<row_type> data_type; //row iteratorsessene // typedef typename data_type::iterator row_iterator; typedef typename data_type::const_iterator const_row_iterator; //row reference types typedef row_type& row_reference; typedef const row_reference const_row_reference; //constructors matrix (size_type n, size_type m, value_type v = value_type()) { data = data_type (n, row_type (m, v)); } //index access //TODO: not good to give a reference to row, cause so, user is abled to change it row_reference operator[] (size_type i) { return data[i]; } const_row_reference operator[] (size_type i) const { return data[i]; } //get row iterator (if it works, we only take const_iterator) const_row_iterator rows_begin() const { return data.begin(); } const_row_iterator rows_end() const { return data.end(); } //misc size_type rows () const { return size_type (data.size()); } size_type cols () const; private: //data field data_type data; }; //////////////////////////////////////////////////////////////////////////////// //functions template < typename T, typename A > typename matrix<T,A>::size_type matrix<T,A>::cols() const { //TODO: somehow try to maintain original row_size for each row return size_type ((data.front()).size()); } //////////////////////////////////////////////////////////////////////////////// //IO functions //row //I /* template <typename T, typename A> std::istream& operator>> (std::istream& s, const row<T,A>& r) { T x; char t; //read in until not more while (s >> x >> t) r.push_back(x); s.clear(); //ATTENTION: for the moment only unix compatible if (t = '\n') { //all ok, pushback last element r.push_back(x); } else { //nothing ok s.clear(ios_base::badbit); } return s; } */ //O template <typename T, typename A> std::ostream& operator<< (std::ostream& s, const row<T,A>& r) { typename row<T,A>::const_iterator it = r.begin(); //for now, we just write a tab as separator for ( ; it < r.end(); ++it) { s << *it; if (it != (r.end()-1)) s << '\t'; } return s; } //matrix //I /* template <typename T, typename A> std::istream& operator>> (std::istream& s, const matrix<T,A>& m) { typename matrix<T,A>::const_row_iterator it = m.rows_begin(); for ( ; it < m.rows_end(); ++it) s << *it << '\n'; return s; } */ //O template <typename T, typename A> std::ostream& operator<< (std::ostream& s, const matrix<T,A>& m) { typename matrix<T,A>::const_row_iterator it = m.rows_begin(); for ( ; it < m.rows_end(); ++it) s << *it << '\n'; return s; } }; // namespace ims #endif