My Project
SparseTable.hpp
1 //===========================================================================
2 //
3 // File: SparseTable.hpp
4 //
5 // Created: Fri Apr 24 09:50:27 2009
6 //
7 // Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8 //
9 // $Date$
10 //
11 // $Revision$
12 //
13 //===========================================================================
14 
15 /*
16  Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
17  Copyright 2009, 2010 Statoil ASA.
18 
19  This file is part of the Open Porous Media project (OPM).
20 
21  OPM is free software: you can redistribute it and/or modify
22  it under the terms of the GNU General Public License as published by
23  the Free Software Foundation, either version 3 of the License, or
24  (at your option) any later version.
25 
26  OPM is distributed in the hope that it will be useful,
27  but WITHOUT ANY WARRANTY; without even the implied warranty of
28  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  GNU General Public License for more details.
30 
31  You should have received a copy of the GNU General Public License
32  along with OPM. If not, see <http://www.gnu.org/licenses/>.
33 */
34 
35 #ifndef OPM_SPARSETABLE_HEADER
36 #define OPM_SPARSETABLE_HEADER
37 
38 #include <vector>
39 #include <numeric>
40 #include <algorithm>
41 #include <opm/grid/utility/ErrorMacros.hpp>
42 #include <opm/grid/utility/IteratorRange.hpp>
43 
44 #include <ostream>
45 
46 namespace Opm
47 {
48 
53  template <typename T>
55  {
56  public:
59  : row_start_(1, 0)
60  {
61  }
62 
68  template <typename DataIter, typename IntegerIter>
69  SparseTable(DataIter data_beg, DataIter data_end,
70  IntegerIter rowsize_beg, IntegerIter rowsize_end)
71  : data_(data_beg, data_end)
72  {
73  setRowStartsFromSizes(rowsize_beg, rowsize_end);
74  }
75 
76 
83  template <typename DataIter, typename IntegerIter>
84  void assign(DataIter data_beg, DataIter data_end,
85  IntegerIter rowsize_beg, IntegerIter rowsize_end)
86  {
87  data_.assign(data_beg, data_end);
88  setRowStartsFromSizes(rowsize_beg, rowsize_end);
89  }
90 
91 
95  template <typename IntegerIter>
96  void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
97  {
98  typedef typename std::vector<T>::size_type sz_t;
99 
100  sz_t ndata = std::accumulate(rowsize_beg, rowsize_end, sz_t(0));
101  data_.resize(ndata);
102  setRowStartsFromSizes(rowsize_beg, rowsize_end);
103  }
104 
105 
107  template <typename DataIter>
108  void appendRow(DataIter row_beg, DataIter row_end)
109  {
110  data_.insert(data_.end(), row_beg, row_end);
111  row_start_.push_back(data_.size());
112  }
113 
115  bool empty() const
116  {
117  return row_start_.size()==1;
118  }
119 
121  int size() const
122  {
123  return row_start_.size() - 1;
124  }
125 
127  void reserve(int exptd_nrows, int exptd_ndata)
128  {
129  row_start_.reserve(exptd_nrows + 1);
130  data_.reserve(exptd_ndata);
131  }
132 
134  void swap(SparseTable<T>& other)
135  {
136  row_start_.swap(other.row_start_);
137  data_.swap(other.data_);
138  }
139 
141  int dataSize() const
142  {
143  return data_.size();
144  }
145 
147  int rowSize(int row) const
148  {
149 #ifndef NDEBUG
150  OPM_ERROR_IF(row < 0 || row >= size(), "Row index " << row << " is out of range");
151 #endif
152  return row_start_[row + 1] - row_start_[row];
153  }
154 
156  void clear()
157  {
158  data_.clear();
159  row_start_.resize(1);
160  }
161 
165 
167  row_type operator[](int row) const
168  {
169  assert(row >= 0 && row < size());
170  return row_type{data_.begin()+ row_start_[row],
171  data_.begin() + row_start_[row + 1]};
172  }
173 
176  {
177  assert(row >= 0 && row < size());
178  return mutable_row_type{data_.begin() + row_start_[row],
179  data_.begin() + row_start_[row + 1]};
180  }
181 
184  class Iterator
185  {
186  public:
187  Iterator(const SparseTable& table, const int begin_row_index)
188  : table_(table)
189  , row_index_(begin_row_index)
190  {
191  }
192  Iterator& operator++()
193  {
194  ++row_index_;
195  return *this;
196  }
197  row_type operator*() const
198  {
199  return table_[row_index_];
200  }
201  bool operator==(const Iterator& other)
202  {
203  assert(&table_ == &other.table_);
204  return row_index_ == other.row_index_;
205  }
206  bool operator!=(const Iterator& other)
207  {
208  return !(*this == other);
209  }
210  private:
211  const SparseTable& table_;
212  int row_index_;
213  };
214 
216  Iterator begin() const
217  {
218  return Iterator(*this, 0);
219  }
220  Iterator end() const
221  {
222  return Iterator(*this, size());
223  }
224 
226  bool operator==(const SparseTable& other) const
227  {
228  return data_ == other.data_ && row_start_ == other.row_start_;
229  }
230 
231  template<class charT, class traits>
232  void print(std::basic_ostream<charT, traits>& os) const
233  {
234  os << "Number of rows: " << size() << '\n';
235 
236  os << "Row starts = [";
237  std::copy(row_start_.begin(), row_start_.end(),
238  std::ostream_iterator<int>(os, " "));
239  os << "\b]\n";
240 
241  os << "Data values = [";
242  std::copy(data_.begin(), data_.end(),
243  std::ostream_iterator<T>(os, " "));
244  os << "\b]\n";
245  }
246  const T data(int i)const {
247  return data_[i];
248  }
249 
250  private:
251  std::vector<T> data_;
252  // Like in the compressed row sparse matrix format,
253  // row_start_.size() is equal to the number of rows + 1.
254  std::vector<int> row_start_;
255 
256  template <class IntegerIter>
257  void setRowStartsFromSizes(IntegerIter rowsize_beg, IntegerIter rowsize_end)
258  {
259 #ifndef NDEBUG
260  // Check that all row sizes given are nonnegative.
261  for (auto it = rowsize_beg; it != rowsize_end; ++it) {
262  if (*it < 0) {
263  OPM_THROW(std::runtime_error, "Negative row size given.");
264  }
265  }
266 #endif
267  // Since we do not store the row sizes, but cumulative row sizes,
268  // we have to create the cumulative ones.
269  int num_rows = rowsize_end - rowsize_beg;
270  row_start_.resize(num_rows + 1);
271  row_start_[0] = 0;
272  std::partial_sum(rowsize_beg, rowsize_end, row_start_.begin() + 1);
273  // Check that data_ and row_start_ match.
274  if (int(data_.size()) != row_start_.back()) {
275  OPM_THROW(std::runtime_error, "End of row start indices different from data size.");
276  }
277 
278  }
279  };
280 
281 } // namespace Opm
282 
283 
284 #endif // OPM_SPARSETABLE_HEADER
Iterator for iterating over the container as a whole, i.e.
Definition: SparseTable.hpp:185
A SparseTable stores a table with rows of varying size as efficiently as possible.
Definition: SparseTable.hpp:55
void reserve(int exptd_nrows, int exptd_ndata)
Allocate storage for table of expected size.
Definition: SparseTable.hpp:127
void assign(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
Sets the table to contain the given data, organized into rows as indicated by the given row sizes.
Definition: SparseTable.hpp:84
bool empty() const
True if the table contains no rows.
Definition: SparseTable.hpp:115
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:108
void swap(SparseTable< T > &other)
Swap contents for other SparseTable<T>
Definition: SparseTable.hpp:134
int size() const
Returns the number of rows in the table.
Definition: SparseTable.hpp:121
row_type operator[](int row) const
Returns a row of the table.
Definition: SparseTable.hpp:167
Iterator begin() const
Iterator access.
Definition: SparseTable.hpp:216
int rowSize(int row) const
Returns the size of a table row.
Definition: SparseTable.hpp:147
int dataSize() const
Returns the number of data elements.
Definition: SparseTable.hpp:141
SparseTable(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
A constructor taking all the data for the table and row sizes.
Definition: SparseTable.hpp:69
void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
Request storage for table of given size.
Definition: SparseTable.hpp:96
SparseTable()
Default constructor. Yields an empty SparseTable.
Definition: SparseTable.hpp:58
void clear()
Makes the table empty().
Definition: SparseTable.hpp:156
bool operator==(const SparseTable &other) const
Equality.
Definition: SparseTable.hpp:226
Holds the implementation of the CpGrid as a pimple.
Definition: CellQuadrature.hpp:29
Definition: IteratorRange.hpp:50
Definition: IteratorRange.hpp:70