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
46namespace 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]};
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
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
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