10#include <initializer_list>
15 #define TF_LIKELY(x) (__builtin_expect((x), 1))
16 #define TF_UNLIKELY(x) (__builtin_expect((x), 0))
18 #define TF_LIKELY(x) (x)
19 #define TF_UNLIKELY(x) (x)
27namespace tf {
namespace detail {
35inline uint64_t NextCapacity(uint64_t A) {
55 std::is_trivial<T>::value> {};
60class SmallVectorBase {
62 void *BeginX, *EndX, *CapacityX;
65 SmallVectorBase(
void *FirstEl,
size_t Size)
66 : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
70 void grow_pod(
void *FirstEl,
size_t MinSizeInBytes,
size_t TSize){
71 size_t CurSizeBytes = size_in_bytes();
72 size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize;
73 if (NewCapacityInBytes < MinSizeInBytes) {
74 NewCapacityInBytes = MinSizeInBytes;
78 if (BeginX == FirstEl) {
82 memcpy(NewElts, this->BeginX, CurSizeBytes);
85 NewElts =
realloc(this->BeginX, NewCapacityInBytes);
89 this->EndX = (
char*)NewElts+CurSizeBytes;
90 this->BeginX = NewElts;
91 this->CapacityX = (
char*)this->BeginX + NewCapacityInBytes;
96 size_t size_in_bytes()
const {
97 return size_t((
char*)EndX - (
char*)BeginX);
101 size_t capacity_in_bytes()
const {
102 return size_t((
char*)CapacityX - (
char*)BeginX);
105 bool empty()
const {
return BeginX == EndX; }
111template <
typename T,
unsigned N>
struct SmallVectorStorage;
116template <
typename T,
typename =
void>
117class SmallVectorTemplateCommon :
public SmallVectorBase {
120 template <
typename,
unsigned>
friend struct SmallVectorStorage;
131 SmallVectorTemplateCommon(
size_t Size) : SmallVectorBase(&FirstEl, Size) {}
133 void grow_pod(
size_t MinSizeInBytes,
size_t TSize) {
134 SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
139 bool isSmall()
const {
140 return BeginX ==
static_cast<const void*
>(&FirstEl);
144 void resetToSmall() {
145 BeginX = EndX = CapacityX = &FirstEl;
148 void setEnd(T *P) { this->EndX = P; }
151 typedef size_t size_type;
152 typedef ptrdiff_t difference_type;
153 typedef T value_type;
155 typedef const T *const_iterator;
160 typedef T &reference;
161 typedef const T &const_reference;
163 typedef const T *const_pointer;
166 inline iterator
begin() {
return (iterator)this->BeginX; }
167 inline const_iterator
begin()
const {
return (const_iterator)this->BeginX; }
168 inline iterator
end() {
return (iterator)this->EndX; }
169 inline const_iterator
end()
const {
return (const_iterator)this->EndX; }
173 iterator capacity_ptr() {
return (iterator)this->CapacityX; }
174 const_iterator capacity_ptr()
const {
return (const_iterator)this->CapacityX;}
179 reverse_iterator rbegin() {
return reverse_iterator(
end()); }
180 const_reverse_iterator rbegin()
const{
return const_reverse_iterator(
end()); }
181 reverse_iterator rend() {
return reverse_iterator(
begin()); }
182 const_reverse_iterator rend()
const {
return const_reverse_iterator(
begin());}
184 inline size_type size()
const {
return end()-
begin(); }
185 inline size_type max_size()
const {
return size_type(-1) /
sizeof(T); }
188 size_t capacity()
const {
return capacity_ptr() -
begin(); }
191 pointer data() {
return pointer(
begin()); }
193 const_pointer data()
const {
return const_pointer(
begin()); }
195 inline reference operator[](size_type idx) {
200 inline const_reference operator[](size_type idx)
const {
210 const_reference front()
const {
220 const_reference back()
const {
229template <
typename T,
bool isPodLike>
230class SmallVectorTemplateBase :
public SmallVectorTemplateCommon<T> {
233 SmallVectorTemplateBase(
size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
235 static void destroy_range(T *S, T *E) {
244 template<
typename It1,
typename It2>
245 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
252 template<
typename It1,
typename It2>
260 void grow(
size_t MinSize = 0);
263 void push_back(
const T &Elt) {
264 if (TF_UNLIKELY(this->EndX >= this->CapacityX))
266 ::new ((
void*) this->
end()) T(Elt);
267 this->setEnd(this->end()+1);
270 void push_back(T &&Elt) {
271 if (TF_UNLIKELY(this->EndX >= this->CapacityX))
273 ::new ((
void*) this->end()) T(::
std::move(Elt));
274 this->setEnd(this->end()+1);
278 this->setEnd(this->end()-1);
286template <
typename T,
bool isPodLike>
287void SmallVectorTemplateBase<T, isPodLike>::grow(
size_t MinSize) {
288 size_t CurCapacity = this->capacity();
289 size_t CurSize = this->size();
291 size_t NewCapacity = size_t(tf::detail::NextCapacity(CurCapacity+2));
292 if (NewCapacity < MinSize)
293 NewCapacity = MinSize;
294 T *NewElts =
static_cast<T*
>(
std::malloc(NewCapacity*
sizeof(T)));
297 this->uninitialized_move(this->
begin(), this->end(), NewElts);
300 destroy_range(this->
begin(), this->end());
303 if (!this->isSmall())
306 this->setEnd(NewElts+CurSize);
307 this->BeginX = NewElts;
308 this->CapacityX = this->
begin()+NewCapacity;
315class SmallVectorTemplateBase<T, true> :
public SmallVectorTemplateCommon<T> {
317 SmallVectorTemplateBase(
size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
320 static void destroy_range(T *, T *) {}
324 template<
typename It1,
typename It2>
325 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
332 template<
typename It1,
typename It2>
340 template <
typename T1,
typename T2>
342 T1 *I, T1 *E, T2 *Dest,
344 T2>::value>::type * =
nullptr) {
350 memcpy(Dest, I, (E - I) *
sizeof(T));
355 void grow(
size_t MinSize = 0) {
356 this->grow_pod(MinSize*
sizeof(T),
sizeof(T));
359 void push_back(
const T &Elt) {
360 if (TF_UNLIKELY(this->EndX >= this->CapacityX))
362 memcpy(this->end(), &Elt,
sizeof(T));
363 this->setEnd(this->end()+1);
367 this->setEnd(this->end()-1);
375class SmallVectorImpl :
public SmallVectorTemplateBase<T, IsPod<T>::value> {
376 typedef SmallVectorTemplateBase<T, IsPod<T>::value> SuperClass;
378 SmallVectorImpl(
const SmallVectorImpl&) =
delete;
381 typedef typename SuperClass::iterator iterator;
382 typedef typename SuperClass::const_iterator const_iterator;
383 typedef typename SuperClass::size_type size_type;
387 explicit SmallVectorImpl(
unsigned N)
388 : SmallVectorTemplateBase<T, IsPod<T>::value>(N*sizeof(T)) {
394 this->destroy_range(this->
begin(), this->end());
397 if (!this->isSmall())
403 this->destroy_range(this->
begin(), this->end());
404 this->EndX = this->BeginX;
407 void resize(size_type N) {
408 if (N < this->size()) {
409 this->destroy_range(this->
begin()+N, this->end());
410 this->setEnd(this->
begin()+N);
411 }
else if (N > this->size()) {
412 if (this->capacity() < N)
414 for (
auto I = this->end(), E = this->
begin() + N; I != E; ++I)
416 this->setEnd(this->
begin()+N);
420 void resize(size_type N,
const T &NV) {
421 if (N < this->size()) {
422 this->destroy_range(this->
begin()+N, this->end());
423 this->setEnd(this->
begin()+N);
424 }
else if (N > this->size()) {
425 if (this->capacity() < N)
428 this->setEnd(this->
begin()+N);
432 void reserve(size_type N) {
433 if (this->capacity() < N)
443 void swap(SmallVectorImpl &RHS);
446 template<
typename in_iter>
447 void append(in_iter in_start, in_iter in_end) {
450 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
451 this->grow(this->size()+NumInputs);
455 this->setEnd(this->end() + NumInputs);
459 void append(size_type NumInputs,
const T &Elt) {
461 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
462 this->grow(this->size()+NumInputs);
466 this->setEnd(this->end() + NumInputs);
470 append(IL.begin(), IL.end());
473 void assign(size_type NumElts,
const T &Elt) {
475 if (this->capacity() < NumElts)
477 this->setEnd(this->
begin()+NumElts);
486 iterator erase(const_iterator CI) {
488 iterator I =
const_cast<iterator
>(CI);
501 iterator erase(const_iterator CS, const_iterator CE) {
503 iterator S =
const_cast<iterator
>(CS);
504 iterator E =
const_cast<iterator
>(CE);
512 iterator I =
std::move(E, this->end(), S);
514 this->destroy_range(I, this->end());
519 iterator insert(iterator I, T &&Elt) {
520 if (I == this->end()) {
522 return this->end()-1;
528 if (this->EndX >= this->CapacityX) {
529 size_t EltNo = I-this->
begin();
531 I = this->
begin()+EltNo;
534 ::new ((
void*) this->end()) T(::
std::move(this->back()));
536 std::move_backward(I, this->end()-1, this->end());
537 this->setEnd(this->end()+1);
542 if (I <= EltPtr && EltPtr < this->EndX)
545 *I = ::
std::move(*EltPtr);
549 iterator insert(iterator I, const T &Elt) {
550 if (I == this->end()) {
551 this->push_back(Elt);
552 return this->end()-1;
558 if (this->EndX >= this->CapacityX) {
559 size_t EltNo = I-this->
begin();
561 I = this->
begin()+EltNo;
563 ::new ((
void*) this->end()) T(
std::move(this->back()));
565 std::move_backward(I, this->end()-1, this->end());
566 this->setEnd(this->end()+1);
570 const T *EltPtr = &Elt;
571 if (I <= EltPtr && EltPtr < this->EndX)
578 iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
580 size_t InsertElt = I - this->
begin();
582 if (I == this->end()) {
583 append(NumToInsert, Elt);
584 return this->
begin()+InsertElt;
591 reserve(this->size() + NumToInsert);
594 I = this->
begin()+InsertElt;
600 if (
size_t(this->end()-I) >= NumToInsert) {
601 T *OldEnd = this->end();
616 T *OldEnd = this->end();
617 this->setEnd(this->end() + NumToInsert);
618 size_t NumOverwritten = OldEnd-I;
619 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
629 template<
typename ItTy>
630 iterator insert(iterator I, ItTy From, ItTy To) {
632 size_t InsertElt = I - this->
begin();
634 if (I == this->end()) {
636 return this->
begin()+InsertElt;
645 reserve(this->size() + NumToInsert);
648 I = this->
begin()+InsertElt;
654 if (
size_t(this->end()-I) >= NumToInsert) {
655 T *OldEnd = this->end();
670 T *OldEnd = this->end();
671 this->setEnd(this->end() + NumToInsert);
672 size_t NumOverwritten = OldEnd-I;
673 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
676 for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
687 insert(I, IL.begin(), IL.end());
690 template <
typename... ArgTypes>
void emplace_back(ArgTypes &&... Args) {
691 if (TF_UNLIKELY(this->EndX >= this->CapacityX))
693 ::new ((
void *)this->end()) T(
std::forward<ArgTypes>(Args)...);
694 this->setEnd(this->end() + 1);
697 SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
699 SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
701 bool operator==(const SmallVectorImpl &RHS)
const {
702 if (this->size() != RHS.size())
return false;
705 bool operator!=(
const SmallVectorImpl &RHS)
const {
706 return !(*
this == RHS);
709 bool operator<(
const SmallVectorImpl &RHS)
const {
711 RHS.begin(), RHS.end());
723 void set_size(size_type N) {
725 this->setEnd(this->
begin() + N);
731void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
732 if (
this == &RHS)
return;
735 if (!this->isSmall() && !RHS.isSmall()) {
738 std::swap(this->CapacityX, RHS.CapacityX);
741 if (RHS.size() > this->capacity())
742 this->grow(RHS.size());
743 if (this->size() > RHS.capacity())
744 RHS.grow(this->size());
747 size_t NumShared = this->size();
748 if (NumShared > RHS.size()) NumShared = RHS.size();
749 for (size_type i = 0; i != NumShared; ++i)
753 if (this->size() > RHS.size()) {
754 size_t EltDiff = this->size() - RHS.size();
756 RHS.setEnd(RHS.end()+EltDiff);
757 this->destroy_range(this->
begin()+NumShared, this->end());
758 this->setEnd(this->
begin()+NumShared);
759 }
else if (RHS.size() > this->size()) {
760 size_t EltDiff = RHS.size() - this->size();
762 this->setEnd(this->end() + EltDiff);
763 this->destroy_range(RHS.begin()+NumShared, RHS.end());
764 RHS.setEnd(RHS.begin()+NumShared);
769SmallVectorImpl<T> &SmallVectorImpl<T>::
770 operator=(
const SmallVectorImpl<T> &RHS) {
772 if (
this == &RHS)
return *
this;
776 size_t RHSSize = RHS.size();
777 size_t CurSize = this->size();
778 if (CurSize >= RHSSize) {
782 NewEnd =
std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
784 NewEnd = this->
begin();
787 this->destroy_range(NewEnd, this->end());
790 this->setEnd(NewEnd);
797 if (this->capacity() < RHSSize) {
799 this->destroy_range(this->
begin(), this->end());
800 this->setEnd(this->
begin());
803 }
else if (CurSize) {
805 std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
810 this->begin()+CurSize);
813 this->setEnd(this->
begin()+RHSSize);
818SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
820 if (
this == &RHS)
return *
this;
823 if (!RHS.isSmall()) {
824 this->destroy_range(this->
begin(), this->end());
826 this->BeginX = RHS.BeginX;
827 this->EndX = RHS.EndX;
828 this->CapacityX = RHS.CapacityX;
835 size_t RHSSize = RHS.size();
836 size_t CurSize = this->size();
837 if (CurSize >= RHSSize) {
839 iterator NewEnd = this->
begin();
841 NewEnd =
std::move(RHS.begin(), RHS.end(), NewEnd);
844 this->destroy_range(NewEnd, this->end());
845 this->setEnd(NewEnd);
857 if (this->capacity() < RHSSize) {
859 this->destroy_range(this->
begin(), this->end());
860 this->setEnd(this->
begin());
863 }
else if (CurSize) {
865 std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
869 this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
870 this->begin()+CurSize);
873 this->setEnd(this->
begin()+RHSSize);
882template <
typename T,
unsigned N>
883struct SmallVectorStorage {
887 typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
893template <
typename T>
struct SmallVectorStorage<T, 1> {};
898template <
typename T>
struct SmallVectorStorage<T, 0> {};
917template <
typename T,
unsigned N = 2>
920 SmallVectorStorage<T, N> Storage;
934 : SmallVectorImpl<T>(N) {
935 this->assign(Size, Value);
942 template<
typename ItTy>
965 SmallVectorImpl<T>::operator=(RHS);
980 SmallVectorImpl<T>::operator=(RHS);
1017template<
typename T,
unsigned N>
1018static inline size_t capacity_in_bytes(
const SmallVector<T, N> &X) {
1019 return X.capacity_in_bytes();
1026 template<
typename T>
1028 swap(tf::SmallVectorImpl<T> &LHS, tf::SmallVectorImpl<T> &RHS) {
1033 template<
typename T,
unsigned N>
class to define a vector optimized for small array
Definition small_vector.hpp:918
SmallVector(size_t Size, const T &Value=T())
constructs a vector with Size copies of elements with value value
Definition small_vector.hpp:933
const SmallVector & operator=(std::initializer_list< T > IL)
replaces the contents with the copy of the contents of an initializer list IL
Definition small_vector.hpp:1011
SmallVector(ItTy S, ItTy E)
constructs a vector with the contents of the range [S, E)
Definition small_vector.hpp:943
SmallVector(SmallVectorImpl< T > &&RHS)
constructs a vector with the contents of RHS using move semantics
Definition small_vector.hpp:995
const SmallVector & operator=(const SmallVector &RHS)
replaces the contents with a copy of the contents of RHS
Definition small_vector.hpp:979
const SmallVector & operator=(SmallVector &&RHS)
replaces the contents with the contents of RHS using move semantics
Definition small_vector.hpp:987
SmallVector()
constructs an empty vector
Definition small_vector.hpp:927
SmallVector(const SmallVector &RHS)
constructs the vector with the copy of the contents of RHS
Definition small_vector.hpp:963
SmallVector(SmallVector &&RHS)
constructs the vector with the contents of RHS using move semantics
Definition small_vector.hpp:971
SmallVector(std::initializer_list< T > IL)
constructs a vector with the contents of the initializer list IL
Definition small_vector.hpp:956
const SmallVector & operator=(SmallVectorImpl< T > &&RHS)
replaces the contents with the contents of RHS using move semantics
Definition small_vector.hpp:1003
T lexicographical_compare(T... args)
T make_move_iterator(T... args)
T move_backward(T... args)
taskflow namespace
Definition small_vector.hpp:27
T uninitialized_copy(T... args)
T uninitialized_fill(T... args)
T uninitialized_fill_n(T... args)