SparseTable.hpp
Go to the documentation of this file.
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 <boost/range/iterator_range.hpp>
42 #include <opm/common/ErrorMacros.hpp>
43 
44 #include <ostream>
45 
46 namespace Opm
47 {
48 
53  template <typename T>
54  class SparseTable
55  {
56  public:
59  {
60  }
61 
67  template <typename DataIter, typename IntegerIter>
68  SparseTable(DataIter data_beg, DataIter data_end,
69  IntegerIter rowsize_beg, IntegerIter rowsize_end)
70  : data_(data_beg, data_end)
71  {
72  setRowStartsFromSizes(rowsize_beg, rowsize_end);
73  }
74 
75 
82  template <typename DataIter, typename IntegerIter>
83  void assign(DataIter data_beg, DataIter data_end,
84  IntegerIter rowsize_beg, IntegerIter rowsize_end)
85  {
86  data_.assign(data_beg, data_end);
87  setRowStartsFromSizes(rowsize_beg, rowsize_end);
88  }
89 
90 
94  template <typename IntegerIter>
95  void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
96  {
97  typedef typename std::vector<T>::size_type sz_t;
98 
99  sz_t ndata = std::accumulate(rowsize_beg, rowsize_end, sz_t(0));
100  data_.resize(ndata);
101  setRowStartsFromSizes(rowsize_beg, rowsize_end);
102  }
103 
104 
106  template <typename DataIter>
107  void appendRow(DataIter row_beg, DataIter row_end)
108  {
109  data_.insert(data_.end(), row_beg, row_end);
110  if (row_start_.empty()) {
111  row_start_.reserve(2);
112  row_start_.push_back(0);
113  }
114  row_start_.push_back(data_.size());
115  }
116 
118  bool empty() const
119  {
120  return row_start_.empty();
121  }
122 
124  int size() const
125  {
126  return empty() ? 0 : row_start_.size() - 1;
127  }
128 
130  void reserve(int exptd_nrows, int exptd_ndata)
131  {
132  row_start_.reserve(exptd_nrows + 1);
133  data_.reserve(exptd_ndata);
134  }
135 
137  void swap(SparseTable<T>& other)
138  {
139  row_start_.swap(other.row_start_);
140  data_.swap(other.data_);
141  }
142 
144  int dataSize() const
145  {
146  return data_.size();
147  }
148 
150  int rowSize(int row) const
151  {
152 #ifndef NDEBUG
153  OPM_ERROR_IF(row < 0 || row >= size(), "Row index " << row << " is out of range");
154 #endif
155  return row_start_[row + 1] - row_start_[row];
156  }
157 
159  void clear()
160  {
161  data_.clear();
162  row_start_.clear();
163  }
164 
166  typedef boost::iterator_range<const T*> row_type;
167  typedef boost::iterator_range<T*> mutable_row_type;
168 
170  row_type operator[](int row) const
171  {
172  assert(row >= 0 && row < size());
173  const T* start_ptr = data_.empty() ? 0 : &data_[0];
174  return row_type(start_ptr + row_start_[row], start_ptr + row_start_[row + 1]);
175  }
176 
178  mutable_row_type operator[](int row)
179  {
180  assert(row >= 0 && row < size());
181  T* start_ptr = data_.empty() ? 0 : &data_[0];
182  return mutable_row_type(start_ptr + row_start_[row], start_ptr + row_start_[row + 1]);
183  }
184 
186  bool operator==(const SparseTable& other) const
187  {
188  return data_ == other.data_ && row_start_ == other.row_start_;
189  }
190 
191  template<class charT, class traits>
192  void print(std::basic_ostream<charT, traits>& os) const
193  {
194  os << "Number of rows: " << size() << '\n';
195 
196  os << "Row starts = [";
197  std::copy(row_start_.begin(), row_start_.end(),
198  std::ostream_iterator<int>(os, " "));
199  os << "\b]\n";
200 
201  os << "Data values = [";
202  std::copy(data_.begin(), data_.end(),
203  std::ostream_iterator<T>(os, " "));
204  os << "\b]\n";
205  }
206  const T data(int i)const {
207  return data_[i];
208  }
209 
210  private:
211  std::vector<T> data_;
212  // Like in the compressed row sparse matrix format,
213  // row_start_.size() is equal to the number of rows + 1.
214  std::vector<int> row_start_;
215 
216  template <class IntegerIter>
217  void setRowStartsFromSizes(IntegerIter rowsize_beg, IntegerIter rowsize_end)
218  {
219  // Since we do not store the row sizes, but cumulative row sizes,
220  // we have to create the cumulative ones.
221  int num_rows = rowsize_end - rowsize_beg;
222  if (num_rows < 1) {
223  OPM_THROW(std::runtime_error, "Must have at least one row. Got " << num_rows << " rows.");
224  }
225 #ifndef NDEBUG
226  if (*std::min_element(rowsize_beg, rowsize_end) < 0) {
227  OPM_THROW(std::runtime_error, "All row sizes must be at least 0.");
228  }
229 #endif
230  row_start_.resize(num_rows + 1);
231  row_start_[0] = 0;
232  std::partial_sum(rowsize_beg, rowsize_end, row_start_.begin() + 1);
233  // Check that data_ and row_start_ match.
234  if (int(data_.size()) != row_start_.back()) {
235  OPM_THROW(std::runtime_error, "End of row start indices different from data size.");
236  }
237 
238  }
239  };
240 
241 } // namespace Opm
242 
243 
244 #endif // OPM_SPARSETABLE_HEADER
SparseTable(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
Definition: SparseTable.hpp:68
int rowSize(int row) const
Returns the size of a table row.
Definition: SparseTable.hpp:150
const T data(int i) const
Definition: SparseTable.hpp:206
bool operator==(const SparseTable &other) const
Equality.
Definition: SparseTable.hpp:186
Definition: AnisotropicEikonal.hpp:43
boost::iterator_range< const T * > row_type
Defining the row type, returned by operator[].
Definition: SparseTable.hpp:166
boost::iterator_range< T * > mutable_row_type
Definition: SparseTable.hpp:167
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:107
void print(std::basic_ostream< charT, traits > &os) const
Definition: SparseTable.hpp:192
void assign(DataIter data_beg, DataIter data_end, IntegerIter rowsize_beg, IntegerIter rowsize_end)
Definition: SparseTable.hpp:83
bool empty() const
True if the table contains no rows.
Definition: SparseTable.hpp:118
void swap(SparseTable< T > &other)
Swap contents for other SparseTable
Definition: SparseTable.hpp:137
int size() const
Returns the number of rows in the table.
Definition: SparseTable.hpp:124
row_type operator[](int row) const
Returns a row of the table.
Definition: SparseTable.hpp:170
SparseTable()
Default constructor. Yields an empty SparseTable.
Definition: SparseTable.hpp:58
void clear()
Makes the table empty().
Definition: SparseTable.hpp:159
int dataSize() const
Returns the number of data elements.
Definition: SparseTable.hpp:144
Definition: TofDiscGalReorder.hpp:38
void reserve(int exptd_nrows, int exptd_ndata)
Allocate storage for table of expected size.
Definition: SparseTable.hpp:130
mutable_row_type operator[](int row)
Returns a mutable row of the table.
Definition: SparseTable.hpp:178
void allocate(IntegerIter rowsize_beg, IntegerIter rowsize_end)
Definition: SparseTable.hpp:95