Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_Vector.H
Go to the documentation of this file.
1#ifndef AMREX_VECTOR_H_
2#define AMREX_VECTOR_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_BLassert.H>
6#include <AMReX_Extension.H>
7#include <AMReX_INT.H>
8#ifdef AMREX_SPACEDIM
9#include <AMReX_Array.H>
10#include <AMReX_TypeTraits.H>
11#endif
12
13#include <algorithm>
14#include <memory>
15#include <string>
16#include <vector>
17
18namespace amrex {
24template <class T, class Allocator=std::allocator<T> >
25class Vector
26 :
27 public std::vector<T, Allocator>
28{
29public:
30
31 using std::vector<T, Allocator>::vector;
32 using typename std::vector<T, Allocator>::size_type;
33
34 [[nodiscard]] T& operator[] (size_type i) noexcept
35 {
36 AMREX_ASSERT_WITH_MESSAGE(i < (this->std::vector<T, Allocator>::size()),
37 "Out of bound error, index: " + std::to_string(i) + " size: " + std::to_string(size()));
38 return this->std::vector<T, Allocator>::operator[](i);
39 }
40
41 [[nodiscard]] const T& operator[] (size_type i) const noexcept
42 {
43 AMREX_ASSERT_WITH_MESSAGE(i < (this->std::vector<T, Allocator>::size()),
44 "Out of bound error, index: " + std::to_string(i) + " size: " + std::to_string(size()));
45 return this->std::vector<T, Allocator>::operator[](i);
46 }
47
49 [[nodiscard]] T* dataPtr () noexcept { return this->data(); }
51 [[nodiscard]] const T* dataPtr () const noexcept { return this->data(); }
52
53 [[nodiscard]] Long size () const noexcept {return static_cast<Long>(std::vector<T, Allocator>::size());}
54
55};
56
57}
58
59namespace amrex
60{
62
63 template <class T, typename = typename T::FABType>
65 {
67 r.reserve(a.size());
68 for (auto& x : a) { r.push_back(&x); }
69 return r;
70 }
71
72 template <class T, std::size_t N, typename = typename T::FABType>
74 {
76 r.reserve(a.size());
77 for (auto& x : a) { r.push_back(&x); }
78 return r;
79 }
80
81 template <class T>
82 [[nodiscard]] Vector<T*> GetVecOfPtrs (const Vector<std::unique_ptr<T> >& a)
83 {
85 r.reserve(a.size());
86 for (const auto& x : a) { r.push_back(x.get()); }
87 return r;
88 }
89
91
92 template <class T, typename = typename T::FABType>
94 {
96 r.reserve(a.size());
97 for (const auto& x : a) { r.push_back(&x); }
98 return r;
99 }
100
101 template <class T, std::size_t N, typename = typename T::FABType>
102 [[nodiscard]] Vector<Array<T,N> const*> GetVecOfConstPtrs (Vector<Array<T,N>> const& a)
103 {
104 Vector<Array<T,N> const*> r;
105 r.reserve(a.size());
106 for (auto& x : a) { r.push_back(&x); }
107 return r;
108 }
109
110 template <class T>
111 [[nodiscard]] Vector<const T*> GetVecOfConstPtrs (const Vector<std::unique_ptr<T> >& a)
112 {
114 r.reserve(a.size());
115 for (const auto& x : a) { r.push_back(x.get()); }
116 return r;
117 }
118
119 template <class T, typename = typename T::FABType>
121 {
122 return {a.begin(), a.end()};
123 }
124
126
127 template <class T>
128 [[nodiscard]] Vector<Vector<T*> > GetVecOfVecOfPtrs (const Vector<Vector<std::unique_ptr<T> > >& a)
129 {
131 r.reserve(a.size());
132 for (const auto& x : a) { r.push_back(GetVecOfPtrs(x)); }
133 return r;
134 }
135
137
138#ifdef AMREX_SPACEDIM
139 template <class T>
140 [[nodiscard]] Vector<std::array<T*,AMREX_SPACEDIM> >
141 GetVecOfArrOfPtrs (const Vector<std::array<std::unique_ptr<T>,AMREX_SPACEDIM> >& a)
142 {
144 r.reserve(a.size());
145 for (const auto& x : a) { r.push_back(GetArrOfPtrs(x)); }
146 return r;
147 }
148
149 template <class T>
150 [[nodiscard]] Vector<std::array<T const*,AMREX_SPACEDIM> >
151 GetVecOfArrOfPtrsConst (const Vector<std::array<std::unique_ptr<T>,AMREX_SPACEDIM> >& a)
152 {
154 r.reserve(a.size());
155 for (const auto& x : a) { r.push_back(GetArrOfConstPtrs(x)); }
156 return r;
157 }
158
159 template <class T>
160 [[nodiscard]] Vector<std::array<T const*,AMREX_SPACEDIM> >
161 GetVecOfArrOfConstPtrs (const Vector<std::array<std::unique_ptr<T>,AMREX_SPACEDIM> >& a)
162 {
164 r.reserve(a.size());
165 for (const auto& x : a) { r.push_back(GetArrOfConstPtrs(x)); }
166 return r;
167 }
168
169 template <class T, std::enable_if_t<IsFabArray<T>::value ||
170 IsBaseFab<T>::value,
171 int> = 0 >
172 [[nodiscard]] Vector<std::array<T const*,AMREX_SPACEDIM> >
173 GetVecOfArrOfConstPtrs (const Vector<std::array<T,AMREX_SPACEDIM> >& a)
174 {
176 r.reserve(a.size());
177 for (const auto& x : a) { r.push_back(GetArrOfConstPtrs(x)); }
178 return r;
179 }
180
181 template <class T, std::enable_if_t<IsFabArray<T>::value ||
182 IsBaseFab<T>::value,
183 int> = 0 >
184 [[nodiscard]] Vector<std::array<T*, AMREX_SPACEDIM> >
185 GetVecOfArrOfPtrs(Vector<std::array<T, AMREX_SPACEDIM> >& a)
186 {
188 r.reserve(a.size());
189 for (auto &x: a) { r.push_back(GetArrOfPtrs(x)); }
190 return r;
191 }
192#endif
193
195
196 template <class T>
198 {
199 std::for_each(a.begin(), a.end(), [](T*& p) { p = nullptr; });
200 }
201
202 template <class T>
203 void FillNull (Vector<std::unique_ptr<T> >& a)
204 {
205 std::for_each(a.begin(), a.end(), [](std::unique_ptr<T>& p) { p.reset(); });
206 }
207
209
210 template <class T>
212 std::sort(vec.begin(), vec.end());
213 auto it = std::unique(vec.begin(), vec.end());
214 vec.erase(it, vec.end());
215 }
216
217 namespace detail {
218 template <class T, class H>
219 std::size_t removeDupDoit (Vector<T>& vec, std::size_t start, std::size_t stop)
220 {
221 std::size_t N = stop-start;
222 if (N < 2) { return stop; }
223
224 T* const data = vec.data() + start;
225 T const sentinel = data[0]; // duplicates will be set to sentinel and removed later
226 H const hasher;
227 for (std::size_t i = 1; i < N; ) {
228 if (data[i] == sentinel) {
229 ++i;
230 continue;
231 }
232
233 std::size_t const hash = hasher(data[i]) % N;
234 if (i == hash) { // data[i] in correct hash position
235 ++i;
236 continue;
237 }
238
239 if (data[i] == data[hash]) {
240 data[i] = sentinel; // because it's a duplicate
241 ++i;
242 continue;
243 }
244
245 if (data[hash] == sentinel) {
246 std::swap(data[hash], data[i]);
247 // after swap, new data[i] holds sentinel
248 // newdata[hash] in correct hash poitiion
249 ++i;
250 continue;
251 }
252
253 std::size_t const hashhash = hasher(data[hash]) % N;
254 if (hashhash != hash) { // data[hash] not in correct has poision, thus will yield it's position
255 std::swap(data[i], data[hash]);
256 // after swap, new data[hash] in correct hash position
257 // new data[i] not sure
258 if (hash < i) { // we have seen new data[i]
259 ++i;
260 } // else next iteration we will work on data[i]
261 } else { // data[hash] in correct hash position, but data[i] is not because of hash collision
262 ++i;
263 }
264 }
265
266 // Now there are three types for data[i]
267 // (1) sentinel
268 // (2) data[i] != sentinel and hash(data[i]) == i
269 // (3) data[i] != sentinel and hash(data[i]) != i because of hash collision
270 // All type 2s are unique, and all sentinels except one can be removed.
271 // We will move all type 2s to the beginning, all sentinels to the end.
272 // This will leave all type 3s in the middle. Then we will work on the middle
273 // part plus one sentinel.
274
275 std::size_t swapPos = 0;
276 for (std::size_t i = 0; i < N; ++i) {
277 // move type 2 to the beginning pointed to by swapPos
278 if (data[i] != sentinel && i == hasher(data[i]) % N) {
279 std::swap(data[i], data[swapPos++]);
280 }
281 }
282
283 // Now we have moved all type 2 elements to the beginning, [0,swapPos)
284
285 std::size_t sentinelPos = N;
286 for (std::size_t i = swapPos; i < sentinelPos; ) {
287 // move type 1 to the end
288 if(data[i] == sentinel) {
289 std::swap(data[i], data[--sentinelPos]);
290 } else {
291 ++i;
292 }
293 }
294
295 // recursively work on the middle part
296 return detail::removeDupDoit<T,H>(vec, start+swapPos, start+sentinelPos+1);
297 }
298 }
299
300 template <class T, class H>
302 // https://stackoverflow.com/questions/1532819/algorithm-efficient-way-to-remove-duplicate-integers-from-an-array
303 std::size_t pos = detail::removeDupDoit<T,H>(vec, 0, vec.size());
304 vec.erase(vec.begin()+pos, vec.end());
305 }
306}
307
308#endif
#define AMREX_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:37
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
T & operator[](size_type i) noexcept
Definition AMReX_Vector.H:34
T * dataPtr() noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:49
Long size() const noexcept
Definition AMReX_Vector.H:53
const T * dataPtr() const noexcept
get access to the underlying data pointer
Definition AMReX_Vector.H:51
amrex_long Long
Definition AMReX_INT.H:30
std::array< T, N > Array
Definition AMReX_Array.H:25
std::size_t removeDupDoit(Vector< T > &vec, std::size_t start, std::size_t stop)
Definition AMReX_Vector.H:219
Definition AMReX_Amr.cpp:49
std::array< T const *, 3 > GetArrOfConstPtrs(const std::array< T, 3 > &a) noexcept
Definition AMReX_Array.H:1016
Vector< std::array< T const *, 3 > > GetVecOfArrOfPtrsConst(const Vector< std::array< std::unique_ptr< T >, 3 > > &a)
Definition AMReX_Vector.H:151
Vector< const T * > GetVecOfConstPtrs(const Vector< T > &a)
Definition AMReX_Vector.H:93
std::array< T *, 3 > GetArrOfPtrs(std::array< T, 3 > &a) noexcept
Definition AMReX_Array.H:1004
Vector< T * > GetVecOfPtrs(Vector< T > &a)
Definition AMReX_Vector.H:64
void FillNull(Vector< T * > &a)
Definition AMReX_Vector.H:197
Vector< Vector< T * > > GetVecOfVecOfPtrs(const Vector< Vector< std::unique_ptr< T > > > &a)
Definition AMReX_Vector.H:128
Vector< std::array< T const *, 3 > > GetVecOfArrOfConstPtrs(const Vector< std::array< std::unique_ptr< T >, 3 > > &a)
Definition AMReX_Vector.H:161
Vector< std::array< T *, 3 > > GetVecOfArrOfPtrs(const Vector< std::array< std::unique_ptr< T >, 3 > > &a)
Definition AMReX_Vector.H:141
void RemoveDuplicates(Vector< T > &vec)
Definition AMReX_Vector.H:211
Definition AMReX_FabArrayCommI.H:1011