opm-common
FastSmallVector.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright 2019, 2025 Equinor ASA.
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 
21  Consult the COPYING file in the top-level source directory of this
22  module for the precise wording of the license and the list of
23  copyright holders.
24 */
33 #ifndef OPM_FAST_SMALL_VECTOR_HPP
34 #define OPM_FAST_SMALL_VECTOR_HPP
35 
36 #include <array>
37 #include <algorithm>
38 #include <vector>
39 
40 namespace Opm {
41 
46 template <typename ValueType, unsigned N>
50 {
51 public:
54  : size_(0)
55  {
56  dataPtr_ = smallBuf_.data();
57  }
58 
60  explicit FastSmallVector(const size_t numElem)
61  {
62  init_(numElem);
63  }
64 
67  FastSmallVector(const size_t numElem, const ValueType value)
68  {
69  init_(numElem);
70 
71  std::fill_n(dataPtr_, size_, value);
72  }
73 
76  : size_(0)
77  {
78  dataPtr_ = smallBuf_.data();
79 
80  (*this) = other;
81  }
82 
85  : size_(0)
86  {
87  dataPtr_ = smallBuf_.data();
88 
89  (*this) = std::move(other);
90  }
91 
94  {
95  }
96 
97 
100  {
101  size_ = other.size_;
102  if (other.usingSmallBuf()) {
103  smallBuf_ = std::move(other.smallBuf_);
104  dataPtr_ = smallBuf_.data();
105  }
106  else {
107  data_ = std::move(other.data_);
108  dataPtr_ = data_.data();
109  }
110 
111  other.dataPtr_ = nullptr;
112  other.size_ = 0;
113 
114  return (*this);
115  }
116 
119  {
120  size_ = other.size_;
121 
122  if (other.usingSmallBuf()) {
123  smallBuf_ = other.smallBuf_;
124  dataPtr_ = smallBuf_.data();
125  }
126  else if (dataPtr_ != other.dataPtr_) {
127  data_ = other.data_;
128  dataPtr_ = data_.data();
129  }
130 
131  return (*this);
132  }
133 
135  ValueType& operator[](size_t idx)
136  { return dataPtr_[idx]; }
137 
139  const ValueType& operator[](size_t idx) const
140  { return dataPtr_[idx]; }
141 
142  using size_type = typename std::vector<ValueType>::size_type;
143 
145  size_type size() const
146  { return size_; }
147 
149  using Iterator = ValueType*;
150 
152  using ConstIterator = const ValueType*;
153 
156  { return dataPtr_; }
157 
160  { return dataPtr_ + size_; }
161 
164  { return dataPtr_; }
165 
168  { return dataPtr_ + size_; }
169 
172  { return dataPtr_; }
173 
176  { return dataPtr_ + size_; }
177 
178  size_type capacity()
179  { return this->usingSmallBuf() ? N : data_.capacity(); }
180 
181  void push_back(const ValueType& value)
182  {
183  if (this->usingSmallBuf()) {
184  if (size_ < N) {
185  // Data is contained in smallBuf_
186  smallBuf_[size_++] = value;
187  } else if (size_ == N) {
188  // Must switch from using smallBuf_ to using data_
189  data_.reserve(N + 1); // Since we will push_back to it later
190  data_.resize(N); // So we can move the existing data to it
191  std::move(smallBuf_.begin(), smallBuf_.end(), data_.begin());
192  data_.push_back(value);
193  ++size_;
194  dataPtr_ = data_.data();
195  }
196  } else {
197  // Data is contained in data_
198  data_.push_back(value);
199  ++size_;
200  dataPtr_ = data_.data();
201  }
202  }
203 
204  void resize(size_t numElem)
205  {
206  if (numElem == size_) return; // nothing to do
207 
208  if (this->usingSmallBuf()) {
209  if (numElem > N) {
210  data_.resize(numElem);
211  if (size_ > 0 && N > 0) {
212  std::copy_n(smallBuf_.begin(), size_, data_.begin());
213  }
214  dataPtr_ = data_.data();
215  } else if (numElem < size_) {
216  // when shrinking, remove the values after numElem so that the space
217  // is ready to use in the potentional future resize
218  for (auto ii = numElem; ii < size_; ++ii) {
219  smallBuf_[ii].~ValueType();
220  }
221  }
222  } else {
223  // when shriking to numElem < N, we do not switch back to use smallBuf_
224  data_.resize(numElem);
225  }
226  size_ = numElem;
227  }
228 
229 private:
230  void init_(size_t numElem)
231  {
232  size_ = numElem;
233 
234  if (size_ > N) {
235  data_.resize(size_);
236  dataPtr_ = data_.data();
237  } else
238  dataPtr_ = smallBuf_.data();
239  }
240 
241  bool usingSmallBuf() const
242  {
243  return dataPtr_ == smallBuf_.data();
244  }
245 
246  std::array<ValueType, N> smallBuf_{};
247  std::vector<ValueType> data_;
248  size_type size_;
249  ValueType* dataPtr_;
250 };
251 
252 } // namespace Opm
253 
254 #endif // OPM_FAST_SMALL_VECTOR_HPP
size_type size() const
number of elements
Definition: FastSmallVector.hpp:145
ConstIterator cend() const
To support range-for etc.
Definition: FastSmallVector.hpp:167
ValueType & operator[](size_t idx)
access the idx th element
Definition: FastSmallVector.hpp:135
FastSmallVector(const FastSmallVector &other)
copy constructor
Definition: FastSmallVector.hpp:75
An implementation of vector/array based on small object optimization.
Definition: FastSmallVector.hpp:49
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
~FastSmallVector()
destructor
Definition: FastSmallVector.hpp:93
const ValueType & operator[](size_t idx) const
const access the idx th element
Definition: FastSmallVector.hpp:139
FastSmallVector(FastSmallVector &&other)
move constructor
Definition: FastSmallVector.hpp:84
Iterator begin()
To support range-for etc.
Definition: FastSmallVector.hpp:171
FastSmallVector(const size_t numElem, const ValueType value)
constructor based on the number of the element, and all the elements will have the same value ...
Definition: FastSmallVector.hpp:67
Iterator end()
To support range-for etc.
Definition: FastSmallVector.hpp:175
ConstIterator cbegin() const
To support range-for etc.
Definition: FastSmallVector.hpp:163
ConstIterator begin() const
To support range-for etc.
Definition: FastSmallVector.hpp:155
FastSmallVector(const size_t numElem)
constructor based on the number of the element
Definition: FastSmallVector.hpp:60
FastSmallVector & operator=(const FastSmallVector &other)
copy assignment
Definition: FastSmallVector.hpp:118
ConstIterator end() const
To support range-for etc.
Definition: FastSmallVector.hpp:159
FastSmallVector()
default constructor
Definition: FastSmallVector.hpp:53
ValueT * Iterator
Iterator type is a plain pointer, so be warned there is no validity checking.
Definition: FastSmallVector.hpp:149
const ValueT * ConstIterator
ConstIterator type is a plain pointer, so be warned there is no validity checking.
Definition: FastSmallVector.hpp:152
FastSmallVector & operator=(FastSmallVector &&other)
move assignment
Definition: FastSmallVector.hpp:99