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 <cstddef>
39 #include <vector>
40 
41 namespace Opm {
42 
47 template <typename ValueType, unsigned N>
51 {
52 public:
55  : size_(0)
56  {
57  dataPtr_ = smallBuf_.data();
58  }
59 
61  explicit FastSmallVector(const std::size_t numElem)
62  {
63  init_(numElem);
64  }
65 
68  FastSmallVector(const std::size_t numElem, const ValueType value)
69  {
70  init_(numElem);
71 
72  std::fill_n(dataPtr_, size_, value);
73  }
74 
77  : size_(0)
78  {
79  dataPtr_ = smallBuf_.data();
80 
81  (*this) = other;
82  }
83 
86  : size_(0)
87  {
88  dataPtr_ = smallBuf_.data();
89 
90  (*this) = std::move(other);
91  }
92 
95  {
96  }
97 
98 
101  {
102  size_ = other.size_;
103  if (other.usingSmallBuf()) {
104  smallBuf_ = std::move(other.smallBuf_);
105  dataPtr_ = smallBuf_.data();
106  }
107  else {
108  data_ = std::move(other.data_);
109  dataPtr_ = data_.data();
110  }
111 
112  other.dataPtr_ = nullptr;
113  other.size_ = 0;
114 
115  return (*this);
116  }
117 
120  {
121  size_ = other.size_;
122 
123  if (other.usingSmallBuf()) {
124  smallBuf_ = other.smallBuf_;
125  dataPtr_ = smallBuf_.data();
126  }
127  else if (dataPtr_ != other.dataPtr_) {
128  data_ = other.data_;
129  dataPtr_ = data_.data();
130  }
131 
132  return (*this);
133  }
134 
136  ValueType& operator[](std::size_t idx)
137  { return dataPtr_[idx]; }
138 
140  const ValueType& operator[](std::size_t idx) const
141  { return dataPtr_[idx]; }
142 
143  using size_type = typename std::vector<ValueType>::size_type;
144 
146  size_type size() const
147  { return size_; }
148 
150  using Iterator = ValueType*;
151 
153  using ConstIterator = const ValueType*;
154 
157  { return dataPtr_; }
158 
161  { return dataPtr_ + size_; }
162 
165  { return dataPtr_; }
166 
169  { return dataPtr_ + size_; }
170 
173  { return dataPtr_; }
174 
177  { return dataPtr_ + size_; }
178 
179  size_type capacity()
180  { return this->usingSmallBuf() ? N : data_.capacity(); }
181 
182  void push_back(const ValueType& value)
183  {
184  if (this->usingSmallBuf()) {
185  if (size_ < N) {
186  // Data is contained in smallBuf_
187  smallBuf_[size_++] = value;
188  } else if (size_ == N) {
189  // Must switch from using smallBuf_ to using data_
190  data_.reserve(N + 1); // Since we will push_back to it later
191  data_.resize(N); // So we can move the existing data to it
192  std::move(smallBuf_.begin(), smallBuf_.end(), data_.begin());
193  data_.push_back(value);
194  ++size_;
195  dataPtr_ = data_.data();
196  }
197  } else {
198  // Data is contained in data_
199  data_.push_back(value);
200  ++size_;
201  dataPtr_ = data_.data();
202  }
203  }
204 
205  void resize(std::size_t numElem)
206  {
207  if (numElem == size_) return; // nothing to do
208 
209  if (this->usingSmallBuf()) {
210  if (numElem > N) {
211  data_.resize(numElem);
212  if (size_ > 0 && N > 0) {
213  std::copy_n(smallBuf_.begin(), size_, data_.begin());
214  }
215  dataPtr_ = data_.data();
216  } else if (numElem < size_) {
217  // when shrinking, remove the values after numElem so that the space
218  // is ready to use in the potentional future resize
219  for (auto ii = numElem; ii < size_; ++ii) {
220  smallBuf_[ii].~ValueType();
221  }
222  }
223  } else {
224  // when shriking to numElem < N, we do not switch back to use smallBuf_
225  data_.resize(numElem);
226  }
227  size_ = numElem;
228  }
229 
230 private:
231  void init_(std::size_t numElem)
232  {
233  size_ = numElem;
234 
235  if (size_ > N) {
236  data_.resize(size_);
237  dataPtr_ = data_.data();
238  } else
239  dataPtr_ = smallBuf_.data();
240  }
241 
242  bool usingSmallBuf() const
243  {
244  return dataPtr_ == smallBuf_.data();
245  }
246 
247  std::array<ValueType, N> smallBuf_{};
248  std::vector<ValueType> data_;
249  size_type size_;
250  ValueType* dataPtr_;
251 };
252 
253 } // namespace Opm
254 
255 #endif // OPM_FAST_SMALL_VECTOR_HPP
size_type size() const
number of elements
Definition: FastSmallVector.hpp:146
ConstIterator cend() const
To support range-for etc.
Definition: FastSmallVector.hpp:168
FastSmallVector(const FastSmallVector &other)
copy constructor
Definition: FastSmallVector.hpp:76
An implementation of vector/array based on small object optimization.
Definition: FastSmallVector.hpp:50
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
FastSmallVector(const std::size_t numElem)
constructor based on the number of the element
Definition: FastSmallVector.hpp:61
~FastSmallVector()
destructor
Definition: FastSmallVector.hpp:94
FastSmallVector(const std::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:68
ValueType & operator[](std::size_t idx)
access the idx th element
Definition: FastSmallVector.hpp:136
const ValueType & operator[](std::size_t idx) const
const access the idx th element
Definition: FastSmallVector.hpp:140
FastSmallVector(FastSmallVector &&other)
move constructor
Definition: FastSmallVector.hpp:85
Iterator begin()
To support range-for etc.
Definition: FastSmallVector.hpp:172
Iterator end()
To support range-for etc.
Definition: FastSmallVector.hpp:176
ConstIterator cbegin() const
To support range-for etc.
Definition: FastSmallVector.hpp:164
ConstIterator begin() const
To support range-for etc.
Definition: FastSmallVector.hpp:156
FastSmallVector & operator=(const FastSmallVector &other)
copy assignment
Definition: FastSmallVector.hpp:119
ConstIterator end() const
To support range-for etc.
Definition: FastSmallVector.hpp:160
FastSmallVector()
default constructor
Definition: FastSmallVector.hpp:54
ValueT * Iterator
Iterator type is a plain pointer, so be warned there is no validity checking.
Definition: FastSmallVector.hpp:150
const ValueT * ConstIterator
ConstIterator type is a plain pointer, so be warned there is no validity checking.
Definition: FastSmallVector.hpp:153
FastSmallVector & operator=(FastSmallVector &&other)
move assignment
Definition: FastSmallVector.hpp:100