// -*- c++ -*- // // $COPYRIGHT$ // //=========================================================================== #ifndef MTL_ARRAY2D_H #define MTL_ARRAY2D_H #include "mtl/mtl_config.h" #include "mtl/refcnt_ptr.h" #include "mtl/dense_iterator.h" #include "mtl/reverse_iter.h" #include "mtl/scaled1D.h" #include "mtl/initialize.h" #include "mtl/matrix_traits.h" #include "mtl/utils.h" //#include "mtl/compressed2D.h" // only for bogus :( #include "mtl/dimension.h" namespace mtl { template struct gen_array2D; //: Array 2-D Container //!category: containers //!component: type //!definition: array2D.h //!tparam: OneD - the one dimensional container the array is composed of //!models: TwoDStorage // // This is the model of TwoDStorage that implements the array // storage format. array2D is actually implemented with a // Container of 1-D Containers (whereas the other TwoDStorage types // just act like Containers of Containers). In this way the // array2D storage type is the most flexible, since many // different types of 1-D containers can be used in conjunction with // this class. The 1-D containers include linked_list // (sparse1D), tree (sparse1D), // dense (std::vector), sparse_pair // (sparse1D), and compressed // (mtl::compressed1D). // // One special feature of the array2D is that one can // swap and assign the Vectors inside the array in constant time, // as mentioned in the array interface description. // // The backbone container of the array2D is not implemented with // std::vector due to some subtle interactions between copy/default // constructors and handle objects. // //!example: array2D.cc template class array2D { typedef array2D self; typedef std::vector rep_type; typedef refcnt_ptr< rep_type > rep_ptr; typedef typename OneD_::reference OneD_reference; typedef typename OneD_::const_reference OneD_const_reference; typedef typename OneD_::value_type T; public: /**@name Type Definitions */ /* this is bogus, need a way to put the new element type "SubMatrix" into OneD */ template struct partitioned { typedef array2D type; typedef gen_array2D generator; }; #if 0 // JGS, bad to have this dependence typedef compressed2D transpose_type; /* bogus */ typedef compressed2D submatrix_type; /* bogus */ typedef compressed2D banded_view_type; /* bogus */ #else typedef array2D transpose_type; /* bogus */ typedef array2D submatrix_type; /* bogus */ typedef array2D banded_view_type; /* bogus */ #endif enum { M = 0, N = 0 }; typedef OneD_ OneD; typedef OneD& OneDRef; typedef const OneD& ConstOneDRef; typedef internal_tag storage_loc; typedef typename OneD::sparsity sparsity; typedef not_strideable strideability; /* JGS need a better name */ //: The 1D container type typedef typename rep_type::value_type value_type; //: A reference to the value type typedef typename rep_type::reference reference; //: A const reference to the value type typedef typename rep_type::const_reference const_reference; //: The integral type for dimensions and indices typedef typename rep_type::size_type size_type; #if !defined( _MSVCPP_ ) //: The iterator type typedef dense_iterator iterator; //: The const iterator type typedef dense_iterator const_iterator; #else typedef dense_iterator iterator; typedef dense_iterator const_iterator; #endif //: The reverse iterator type typedef reverse_iter reverse_iterator; //: The const reverse iterator type typedef reverse_iter const_reverse_iterator; //: A pair type for the dimension typedef dimension dim_type; //: A pair type for the bandwidth typedef dimension band_type; protected: inline void resize_oned(sparse_tag) { for (iterator i = this->begin(); i != this->end(); ++i) *i = OneD(); } inline void resize_oned(dense_tag) { for (iterator i = this->begin(); i != this->end(); ++i) *i = OneD(dim.second()); /* for (size_type i = 0; i < dim.first(); ++i) * (*rep)[i].resize(dim.second()); */ } inline void resize_banded(band_type , sparse_tag) { for (iterator i = this->begin(); i != this->end(); ++i) *i = OneD(); } inline void resize_banded(band_type bw, dense_tag) { for (iterator i = this->begin(); i != this->end(); ++i) { band_type sf = calc_start_fini(i.index(), dim.second(), bw); *i = OneD(sf.second() - sf.first()); } /* for (size_type i = 0; i < dim.first(); ++i) { * band_type sf = calc_start_fini(i, dim.second(), bw); * (*rep)[i].resize(sf.second() - sf.first()); * } */ } inline void resize_banded(band_type bw) { resize_banded(bw, sparsity()); } public: /* Constructors */ //: Default Constructor inline array2D() : dim(0,0), rep(0), start_index(0) { } //: Normal Constructor inline array2D(dim_type d, size_type start_index = 0) : dim(d), rep(new rep_type(d.first())), start_index(start_index) { resize_oned(sparsity()); } //: Banded Constructor inline array2D(dim_type d, band_type band, size_type start_index = 0) : dim(d), rep(new rep_type(d.first())), start_index(start_index) { resize_banded(band); } //: sparse banded view constructor template inline array2D(const TwoD& x, band_type, banded_tag) : dim(x.dim), rep(x.rep), start_index(x.start_index) { } //: Matrix Stream Constructor template inline array2D(MatrixStream& s, Orien) : dim(Orien::map(dim_type(s.nrows(),s.ncols()))), rep(new rep_type(Orien::map(dim_type(s.nrows(),s.ncols())).first())), start_index(0) { resize_oned(sparsity()); } //: Banded Matrix Stream Constructor template inline array2D(MatrixStream& s, Orien, band_type bw) : dim(Orien::map(dim_type(s.nrows(),s.ncols()))), rep(new rep_type(Orien::map(dim_type(s.nrows(),s.ncols())).first())), start_index(0) { resize_banded(bw); } //: Copy Constructor (shallow) inline array2D(const self& x) : dim(x.dim), rep(x.rep), start_index(x.start_index) { } /* Access Methods */ /* Iterator Access Methods */ //: Return an iterator pointing to the first 1D container inline iterator begin() { return iterator(rep->begin(), start_index); } //: Return an iterator pointing past the end of the 2D container inline iterator end() { return iterator(rep->begin(), rep->size() + start_index); } //: Return a const iterator pointing to the first 1D container inline const_iterator begin() const { return const_iterator(rep->begin(), start_index); } //: Return a const iterator pointing past the end of the 2D container inline const_iterator end() const { return const_iterator(rep->begin(), rep->size() + start_index); } /* reverse iterators */ //: Return a reverse iterator pointing to the last 1D container inline reverse_iterator rbegin() { return reverse_iterator(end()); } //: Return a reverse iterator pointing past the start of the 2D container inline reverse_iterator rend() { return reverse_iterator(begin()); } //: Return a const reverse iterator pointing to the last 1D container inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } //: Return a const reverse iterator pointing past the start of the 2D container inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } /* Element Access Methods */ //: Return a reference to the (i,j) element, where (i,j) is in the 2D coordinate system inline OneD_reference operator () (size_type i, size_type j) { return (*rep)[i][j]; } //: Return a const reference to the (i,j) element, where (i,j) is in the 2D coordinate system inline OneD_const_reference operator () (size_type i, size_type j) const { return (*rep)[i][j]; } /* Vector Access Methods */ //: Return a reference to the ith 1D container inline OneDRef operator [](size_type i) { return (*rep)[i]; } //: Return a const reference to the ith 1D container inline ConstOneDRef operator [](size_type i) const { return (*rep)[i]; } /* Size Methods */ //: The dimension of the 2D container inline size_type major() const { return dim.first(); } //: The dimension of the 1D containers inline size_type minor() const { return dim.second(); } //: The number of non-zeros inline size_type nnz() const { size_type nz = 0; for (size_type i = 0; i < rep->size(); ++i) { nz += (*rep)[i].nnz(); } return nz; } //: Capacity inline size_type capacity() const { size_type nz = 0; for (size_type i = 0; i < rep->size(); ++i) { nz += (*rep)[i].capacity(); } return nz; } inline void print() const { for (typename rep_type::const_iterator i = rep->begin(); i != rep->end(); ++i) (*i).print(); } inline size_type first_index() const { return start_index; } //: A faster specialization for copying template inline void fast_copy(const Matrix& x) { typename Matrix::const_iterator xi = x.begin(); for (iterator i = begin(); i != end(); ++i, ++xi) { typename Matrix::OneD::IndexArrayRef ind = (*xi).nz_struct(); *i = OneD(ind.begin(), ind.end(), (*xi).size()); copy(*xi, *i); } } /* JGS add sub_matrix */ protected: dim_type dim; rep_ptr rep; size_type start_index; /* index of the first row/col */ }; //: array2D generator used in matrix.h //!noindex: template struct gen_array2D { typedef gen_array2D submatrix_type; /* bogus */ #if 0 typedef gen_compressed2D transpose_type; /* bogus */ typedef gen_compressed2D banded_view_type; /* bogus */ #else typedef gen_array2D transpose_type; typedef gen_array2D banded_view_type; #endif typedef array2D type; }; } /* namespace mtl */ #endif #if 0 //: Sparse Matrix Non-Zero Info inline nz_structure< array2D > nz_struct() { return nz_structure< array2D >(*this); } //: Sparse Matrix Skeleton Constructor template inline array2D(const nz_structure& x) : rep(new rep_type(x.major())), start_index(0) { for (int i = 0; i < major_; ++i) (*rep)[i] = OneD(x[i].nz_struct()); } #endif