|
10 | 10 | #include <AMReX_MemPool.H> |
11 | 11 | #include <AMReX_TypeTraits.H> |
12 | 12 |
|
| 13 | +#include <cmath> |
13 | 14 | #include <iterator> |
14 | 15 | #include <type_traits> |
15 | 16 | #include <utility> |
@@ -257,6 +258,19 @@ namespace amrex |
257 | 258 | void Initialize (); |
258 | 259 | } |
259 | 260 |
|
| 261 | + inline std::size_t grow_podvector_capacity (std::size_t s) |
| 262 | + { |
| 263 | + if (s <= 900) { |
| 264 | + // 3*sqrt(900) = 900/10. Note that we don't need to be precise |
| 265 | + // here. Even if later we change the else block to |
| 266 | + // 4*std::sqrt(s), it's not really an issue to still use 900 |
| 267 | + // here. |
| 268 | + return s + s/10; |
| 269 | + } else { |
| 270 | + return s + std::size_t(3*std::sqrt(s)); |
| 271 | + } |
| 272 | + } |
| 273 | + |
260 | 274 | template <class T, class Allocator = std::allocator<T> > |
261 | 275 | class PODVector : public Allocator |
262 | 276 | { |
@@ -295,48 +309,57 @@ namespace amrex |
295 | 309 | {} |
296 | 310 |
|
297 | 311 | explicit PODVector (size_type a_size) |
298 | | - : m_size(a_size), m_capacity(a_size) |
| 312 | + : m_size(a_size), m_capacity(grow_podvector_capacity(a_size)) |
299 | 313 | { |
300 | | - if (a_size != 0) { |
301 | | - m_data = allocate(m_size); |
302 | | - detail::maybe_init_snan(m_data, m_size, (Allocator const&)(*this)); |
| 314 | + if (m_capacity != 0) { |
| 315 | + m_data = allocate(m_capacity); |
| 316 | + if (a_size != 0) { |
| 317 | + detail::maybe_init_snan(m_data, m_size, (Allocator const&)(*this)); |
| 318 | + } |
303 | 319 | } |
304 | 320 | } |
305 | 321 |
|
306 | 322 | PODVector (size_type a_size, const value_type& a_value, |
307 | 323 | const allocator_type& a_allocator = Allocator()) |
308 | | - : Allocator(a_allocator), m_size(a_size), m_capacity(a_size) |
309 | | - { |
310 | | - if (a_size != 0) { |
311 | | - m_data = allocate(m_size); |
312 | | - detail::uninitializedFillNImpl(m_data, a_size, a_value, |
313 | | - (Allocator const&)(*this)); |
| 324 | + : Allocator(a_allocator), m_size(a_size), |
| 325 | + m_capacity(grow_podvector_capacity(a_size)) |
| 326 | + { |
| 327 | + if (m_capacity != 0) { |
| 328 | + m_data = allocate(m_capacity); |
| 329 | + if (a_size != 0) { |
| 330 | + detail::uninitializedFillNImpl(m_data, a_size, a_value, |
| 331 | + (Allocator const&)(*this)); |
| 332 | + } |
314 | 333 | } |
315 | 334 | } |
316 | 335 |
|
317 | 336 | PODVector (std::initializer_list<T> a_initializer_list, |
318 | 337 | const allocator_type& a_allocator = Allocator()) |
319 | 338 | : Allocator(a_allocator), |
320 | 339 | m_size (a_initializer_list.size()), |
321 | | - m_capacity(a_initializer_list.size()) |
| 340 | + m_capacity(grow_podvector_capacity(a_initializer_list.size())) |
322 | 341 | { |
323 | | - if (a_initializer_list.size() != 0) { |
324 | | - m_data = allocate(m_size); |
325 | | - detail::initFromListImpl(m_data, a_initializer_list, |
326 | | - (Allocator const&)(*this)); |
| 342 | + if (m_capacity != 0) { |
| 343 | + m_data = allocate(m_capacity); |
| 344 | + if (a_initializer_list.size() != 0) { |
| 345 | + detail::initFromListImpl(m_data, a_initializer_list, |
| 346 | + (Allocator const&)(*this)); |
| 347 | + } |
327 | 348 | } |
328 | 349 | } |
329 | 350 |
|
330 | 351 | PODVector (const PODVector<T, Allocator>& a_vector) |
331 | 352 | : Allocator(a_vector), |
332 | 353 | m_size (a_vector.size()), |
333 | | - m_capacity(a_vector.size()) |
| 354 | + m_capacity(a_vector.capacity()) |
334 | 355 | { |
335 | | - if (a_vector.size() != 0) { |
336 | | - m_data = allocate(m_size); |
337 | | - detail::memCopyImpl(m_data, a_vector.m_data, a_vector.nBytes(), |
338 | | - (Allocator const&)(*this), |
339 | | - (Allocator const&)a_vector); |
| 356 | + if (m_capacity != 0) { |
| 357 | + m_data = allocate(m_capacity); |
| 358 | + if (a_vector.size() != 0) { |
| 359 | + detail::memCopyImpl(m_data, a_vector.m_data, a_vector.nBytes(), |
| 360 | + (Allocator const&)(*this), |
| 361 | + (Allocator const&)a_vector); |
| 362 | + } |
340 | 363 | } |
341 | 364 | } |
342 | 365 |
|
@@ -378,7 +401,7 @@ namespace amrex |
378 | 401 | const auto other_size = a_vector.size(); |
379 | 402 | if ( other_size > m_capacity ) { |
380 | 403 | clear(); |
381 | | - reserve(other_size); |
| 404 | + reserve_doit(other_size); |
382 | 405 | } |
383 | 406 |
|
384 | 407 | m_size = other_size; |
@@ -592,7 +615,7 @@ namespace amrex |
592 | 615 |
|
593 | 616 | [[nodiscard]] size_type capacity () const noexcept { return m_capacity; } |
594 | 617 |
|
595 | | - [[nodiscard]] bool empty () const noexcept { return m_size == 0; } |
| 618 | + [[nodiscard]] bool empty () const noexcept { return m_size == 0 || m_data == nullptr; } // test m_data to avoid compiler warning |
596 | 619 |
|
597 | 620 | [[nodiscard]] T& operator[] (size_type a_index) noexcept { return m_data[a_index]; } |
598 | 621 |
|
@@ -663,9 +686,7 @@ namespace amrex |
663 | 686 | void reserve (size_type a_capacity) |
664 | 687 | { |
665 | 688 | if (m_capacity < a_capacity) { |
666 | | - auto fp = detail::allocate_in_place(m_data, a_capacity, a_capacity, |
667 | | - (Allocator&)(*this)); |
668 | | - UpdateDataPtr(fp); |
| 689 | + reserve_doit(grow_podvector_capacity(a_capacity)); |
669 | 690 | } |
670 | 691 | } |
671 | 692 |
|
@@ -701,6 +722,14 @@ namespace amrex |
701 | 722 |
|
702 | 723 | private: |
703 | 724 |
|
| 725 | + void reserve_doit (size_type a_capacity) { |
| 726 | + if (m_capacity < a_capacity) { |
| 727 | + auto fp = detail::allocate_in_place(m_data, a_capacity, a_capacity, |
| 728 | + (Allocator&)(*this)); |
| 729 | + UpdateDataPtr(fp); |
| 730 | + } |
| 731 | + } |
| 732 | + |
704 | 733 | [[nodiscard]] size_type nBytes () const noexcept |
705 | 734 | { |
706 | 735 | return m_size*sizeof(T); |
|
0 commit comments