23 #include <c10/util/AlignOf.h> 24 #include <c10/macros/Macros.h> 31 #include <initializer_list> 35 #include <type_traits> 43 static inline uint64_t NextPowerOf2(uint64_t
A) {
58 void *BeginX, *EndX, *CapacityX;
62 : BeginX(FirstEl), EndX(FirstEl), CapacityX((
char*)FirstEl + Size) {}
66 void grow_pod(
void* FirstEl,
size_t MinSizeInBytes,
size_t TSize);
71 return size_t((
char*)EndX - (
char*)BeginX);
76 return size_t((
char*)CapacityX - (
char*)BeginX);
80 return BeginX == EndX;
87 template <
typename T,
typename =
void>
90 template <
typename,
unsigned>
103 void grow_pod(
size_t MinSizeInBytes,
size_t TSize) {
110 return BeginX ==
static_cast<const void*
>(&FirstEl);
115 BeginX = EndX = CapacityX = &FirstEl;
123 using size_type = size_t;
124 using difference_type = ptrdiff_t;
129 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
130 using reverse_iterator = std::reverse_iterator<iterator>;
161 reverse_iterator rbegin() {
162 return reverse_iterator(end());
164 const_reverse_iterator rbegin()
const {
165 return const_reverse_iterator(end());
167 reverse_iterator rend() {
168 return reverse_iterator(begin());
170 const_reverse_iterator rend()
const {
171 return const_reverse_iterator(begin());
174 size_type size()
const {
175 return end() - begin();
177 size_type max_size()
const {
178 return size_type(-1) /
sizeof(
T);
183 return capacity_ptr() - begin();
197 assert(idx < size());
201 assert(idx < size());
206 assert(idx < size());
210 assert(idx < size());
235 template <
typename T,
bool isPodLike>
240 static void destroy_range(
T* S,
T*
E) {
249 template <
typename It1,
typename It2>
251 std::uninitialized_copy(
252 std::make_move_iterator(I), std::make_move_iterator(E), Dest);
257 template <
typename It1,
typename It2>
259 std::uninitialized_copy(I, E, Dest);
265 void grow(
size_t MinSize = 0);
268 void push_back(
const T& Elt) {
269 if (this->EndX >= this->CapacityX)
271 ::new ((
void*)this->end())
T(Elt);
272 this->setEnd(this->end() + 1);
275 void push_back(
T&& Elt) {
276 if (this->EndX >= this->CapacityX)
278 ::new ((
void*)this->end())
T(::std::move(Elt));
279 this->setEnd(this->end() + 1);
283 this->setEnd(this->end() - 1);
289 template <
typename T,
bool isPodLike>
291 size_t CurCapacity = this->capacity();
292 size_t CurSize = this->size();
294 size_t NewCapacity = size_t(detail::NextPowerOf2(CurCapacity + 2));
295 if (NewCapacity < MinSize)
296 NewCapacity = MinSize;
297 T* NewElts =
static_cast<T*
>(malloc(NewCapacity *
sizeof(
T)));
298 if (NewElts ==
nullptr)
299 throw std::bad_alloc();
302 this->uninitialized_move(this->begin(), this->end(), NewElts);
305 destroy_range(this->begin(), this->end());
308 if (!this->isSmall())
311 this->setEnd(NewElts + CurSize);
312 this->BeginX = NewElts;
313 this->CapacityX = this->begin() + NewCapacity;
318 template <
typename T>
324 static void destroy_range(
T*,
T*) {}
328 template <
typename It1,
typename It2>
331 uninitialized_copy(I, E, Dest);
336 template <
typename It1,
typename It2>
339 std::uninitialized_copy(I, E, Dest);
344 template <
typename T1,
typename T2>
349 typename std::enable_if<
350 std::is_same<
typename std::remove_const<T1>::type, T2>::value>::
357 memcpy(Dest, I, (E - I) *
sizeof(
T));
362 void grow(
size_t MinSize = 0) {
363 this->grow_pod(MinSize *
sizeof(
T),
sizeof(
T));
367 void push_back(
const T& Elt) {
368 if (this->EndX >= this->CapacityX)
370 memcpy(this->end(), &Elt,
sizeof(
T));
371 this->setEnd(this->end() + 1);
375 this->setEnd(this->end() - 1);
381 template <
typename T>
389 using size_type =
typename SuperClass::size_type;
402 this->destroy_range(this->begin(), this->end());
405 if (!this->isSmall())
410 this->destroy_range(this->begin(), this->end());
411 this->EndX = this->BeginX;
414 void resize(size_type N) {
415 if (N < this->size()) {
416 this->destroy_range(this->begin() + N, this->end());
417 this->setEnd(this->begin() + N);
418 }
else if (N > this->size()) {
419 if (this->capacity() < N)
421 auto I = this->end();
422 for (
auto E = this->begin() + N; I !=
E; ++I)
424 this->setEnd(this->begin() + N);
428 void resize(size_type N,
const T& NV) {
429 if (N < this->size()) {
430 this->destroy_range(this->begin() + N, this->end());
431 this->setEnd(this->begin() + N);
432 }
else if (N > this->size()) {
433 if (this->capacity() < N)
435 std::uninitialized_fill(this->end(), this->begin() + N, NV);
436 this->setEnd(this->begin() + N);
440 void reserve(size_type N) {
441 if (this->capacity() < N)
446 T Result = ::std::move(this->back());
456 typename =
typename std::enable_if<std::is_convertible<
457 typename std::iterator_traits<in_iter>::iterator_category,
458 std::input_iterator_tag>::value>::type>
459 void append(in_iter in_start, in_iter in_end) {
460 size_type NumInputs = std::distance(in_start, in_end);
462 if (NumInputs > size_type(this->capacity_ptr() - this->end()))
463 this->grow(this->size() + NumInputs);
466 this->uninitialized_copy(in_start, in_end, this->end());
467 this->setEnd(this->end() + NumInputs);
471 void append(size_type NumInputs,
const T& Elt) {
473 if (NumInputs > size_type(this->capacity_ptr() - this->end()))
474 this->grow(this->size() + NumInputs);
477 std::uninitialized_fill_n(this->end(), NumInputs, Elt);
478 this->setEnd(this->end() + NumInputs);
481 void append(std::initializer_list<T> IL) {
482 append(IL.begin(), IL.end());
488 void assign(size_type NumElts,
const T& Elt) {
490 if (this->capacity() < NumElts)
492 this->setEnd(this->begin() + NumElts);
493 std::uninitialized_fill(this->begin(), this->end(), Elt);
498 typename =
typename std::enable_if<std::is_convertible<
499 typename std::iterator_traits<in_iter>::iterator_category,
500 std::input_iterator_tag>::value>::type>
501 void assign(in_iter in_start, in_iter in_end) {
503 append(in_start, in_end);
506 void assign(std::initializer_list<T> IL) {
515 assert(I >= this->begin() &&
"Iterator to erase is out of bounds.");
516 assert(I < this->end() &&
"Erasing at past-the-end iterator.");
520 std::move(I + 1, this->end(), I);
531 assert(S >= this->begin() &&
"Range to erase is out of bounds.");
532 assert(S <= E &&
"Trying to erase invalid range.");
533 assert(
E <= this->end() &&
"Trying to erase past the end.");
537 iterator I = std::move(E, this->end(), S);
539 this->destroy_range(I, this->end());
545 if (I == this->end()) {
546 this->push_back(::std::move(Elt));
547 return this->end() - 1;
550 assert(I >= this->begin() &&
"Insertion iterator is out of bounds.");
551 assert(I <= this->end() &&
"Inserting past the end of the vector.");
553 if (this->EndX >= this->CapacityX) {
554 size_t EltNo = I - this->begin();
556 I = this->begin() + EltNo;
559 ::new ((
void*)this->end())
T(::std::move(this->back()));
561 std::move_backward(I, this->end() - 1, this->end());
562 this->setEnd(this->end() + 1);
567 if (I <= EltPtr && EltPtr < this->EndX)
570 *I = ::std::move(*EltPtr);
575 if (I == this->end()) {
576 this->push_back(Elt);
577 return this->end() - 1;
580 assert(I >= this->begin() &&
"Insertion iterator is out of bounds.");
581 assert(I <= this->end() &&
"Inserting past the end of the vector.");
583 if (this->EndX >= this->CapacityX) {
584 size_t EltNo = I - this->begin();
586 I = this->begin() + EltNo;
588 ::new ((
void*)this->end())
T(std::move(this->back()));
590 std::move_backward(I, this->end() - 1, this->end());
591 this->setEnd(this->end() + 1);
595 const T* EltPtr = &Elt;
596 if (I <= EltPtr && EltPtr < this->EndX)
605 size_t InsertElt = I - this->begin();
607 if (I == this->end()) {
608 append(NumToInsert, Elt);
609 return this->begin() + InsertElt;
612 assert(I >= this->begin() &&
"Insertion iterator is out of bounds.");
613 assert(I <= this->end() &&
"Inserting past the end of the vector.");
616 reserve(this->size() + NumToInsert);
619 I = this->begin() + InsertElt;
625 if (
size_t(this->end() - I) >= NumToInsert) {
626 T* OldEnd = this->end();
628 std::move_iterator<iterator>(this->end() - NumToInsert),
629 std::move_iterator<iterator>(this->end()));
632 std::move_backward(I, OldEnd - NumToInsert, OldEnd);
634 std::fill_n(I, NumToInsert, Elt);
642 T* OldEnd = this->end();
643 this->setEnd(this->end() + NumToInsert);
644 size_t NumOverwritten = OldEnd - I;
645 this->uninitialized_move(I, OldEnd, this->end() - NumOverwritten);
648 std::fill_n(I, NumOverwritten, Elt);
651 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, Elt);
657 typename =
typename std::enable_if<std::is_convertible<
658 typename std::iterator_traits<ItTy>::iterator_category,
659 std::input_iterator_tag>::value>::type>
662 size_t InsertElt = I - this->begin();
664 if (I == this->end()) {
666 return this->begin() + InsertElt;
669 assert(I >= this->begin() &&
"Insertion iterator is out of bounds.");
670 assert(I <= this->end() &&
"Inserting past the end of the vector.");
672 size_t NumToInsert = std::distance(From, To);
675 reserve(this->size() + NumToInsert);
678 I = this->begin() + InsertElt;
684 if (
size_t(this->end() - I) >= NumToInsert) {
685 T* OldEnd = this->end();
687 std::move_iterator<iterator>(this->end() - NumToInsert),
688 std::move_iterator<iterator>(this->end()));
691 std::move_backward(I, OldEnd - NumToInsert, OldEnd);
693 std::copy(From, To, I);
701 T* OldEnd = this->end();
702 this->setEnd(this->end() + NumToInsert);
703 size_t NumOverwritten = OldEnd - I;
704 this->uninitialized_move(I, OldEnd, this->end() - NumOverwritten);
707 for (
T* J = I; NumOverwritten > 0; --NumOverwritten) {
714 this->uninitialized_copy(From, To, OldEnd);
718 void insert(
iterator I, std::initializer_list<T> IL) {
719 insert(I, IL.begin(), IL.end());
722 template <
typename... ArgTypes>
723 void emplace_back(ArgTypes&&... Args) {
724 if (this->EndX >= this->CapacityX)
726 ::new ((
void*)this->end())
T(std::forward<ArgTypes>(Args)...);
727 this->setEnd(this->end() + 1);
735 if (this->size() != RHS.size())
737 return std::equal(this->begin(), this->end(), RHS.begin());
740 return !(*
this == RHS);
744 return std::lexicographical_compare(
745 this->begin(), this->end(), RHS.begin(), RHS.end());
758 assert(N <= this->capacity());
759 this->setEnd(this->begin() + N);
763 template <
typename T>
769 if (!this->isSmall() && !RHS.
isSmall()) {
770 std::swap(this->BeginX, RHS.BeginX);
771 std::swap(this->EndX, RHS.EndX);
772 std::swap(this->CapacityX, RHS.CapacityX);
775 if (RHS.size() > this->capacity())
776 this->grow(RHS.size());
778 RHS.
grow(this->size());
781 size_t NumShared = this->size();
782 if (NumShared > RHS.size())
783 NumShared = RHS.size();
784 for (size_type i = 0; i != NumShared; ++i)
785 std::swap((*
this)[i], RHS[i]);
788 if (this->size() > RHS.size()) {
789 size_t EltDiff = this->size() - RHS.size();
790 this->uninitialized_copy(this->begin() + NumShared, this->end(), RHS.end());
791 RHS.setEnd(RHS.end() + EltDiff);
792 this->destroy_range(this->begin() + NumShared, this->end());
793 this->setEnd(this->begin() + NumShared);
794 }
else if (RHS.size() > this->size()) {
795 size_t EltDiff = RHS.size() - this->size();
796 this->uninitialized_copy(RHS.begin() + NumShared, RHS.end(), this->end());
797 this->setEnd(this->end() + EltDiff);
798 this->destroy_range(RHS.begin() + NumShared, RHS.end());
799 RHS.setEnd(RHS.begin() + NumShared);
803 template <
typename T>
812 size_t RHSSize = RHS.size();
813 size_t CurSize = this->size();
814 if (CurSize >= RHSSize) {
818 NewEnd = std::copy(RHS.begin(), RHS.begin() + RHSSize, this->begin());
820 NewEnd = this->begin();
823 this->destroy_range(NewEnd, this->end());
826 this->setEnd(NewEnd);
833 if (this->capacity() < RHSSize) {
835 this->destroy_range(this->begin(), this->end());
836 this->setEnd(this->begin());
839 }
else if (CurSize) {
841 std::copy(RHS.begin(), RHS.begin() + CurSize, this->begin());
845 this->uninitialized_copy(
846 RHS.begin() + CurSize, RHS.end(), this->begin() + CurSize);
849 this->setEnd(this->begin() + RHSSize);
853 template <
typename T>
861 this->destroy_range(this->begin(), this->end());
862 if (!this->isSmall())
864 this->BeginX = RHS.BeginX;
865 this->EndX = RHS.EndX;
866 this->CapacityX = RHS.CapacityX;
873 size_t RHSSize = RHS.size();
874 size_t CurSize = this->size();
875 if (CurSize >= RHSSize) {
879 NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
882 this->destroy_range(NewEnd, this->end());
883 this->setEnd(NewEnd);
895 if (this->capacity() < RHSSize) {
897 this->destroy_range(this->begin(), this->end());
898 this->setEnd(this->begin());
901 }
else if (CurSize) {
903 std::move(RHS.begin(), RHS.begin() + CurSize, this->begin());
907 this->uninitialized_move(
908 RHS.begin() + CurSize, RHS.end(), this->begin() + CurSize);
911 this->setEnd(this->begin() + RHSSize);
921 template <
typename T,
unsigned N>
925 template <
typename T>
927 template <
typename T>
938 template <
typename T,
unsigned N>
946 explicit SmallVector(
size_t Size,
const T& Value = T())
948 this->assign(Size, Value);
953 typename =
typename std::enable_if<std::is_convertible<
954 typename std::iterator_traits<ItTy>::iterator_category,
955 std::input_iterator_tag>::value>::type>
960 template <
typename Container>
962 this->append(c.begin(), c.end());
974 const SmallVector& operator=(
const SmallVector& RHS) {
984 template <
typename Container>
985 const SmallVector& operator=(
const Container& RHS) {
986 this->assign(RHS.begin(), RHS.end());
995 const SmallVector& operator=(SmallVector&& RHS) {
1005 template <
typename Container>
1006 const SmallVector& operator=(Container&&
C) {
1007 this->assign(
C.begin(),
C.end());
1011 const SmallVector& operator=(std::initializer_list<T> IL) {
1017 template <
typename T,
unsigned N>
1022 template <
typename T,
unsigned N>
1023 std::ostream& operator<<(std::ostream & out, const SmallVector<T, N>& list) {
1026 for(
auto e : list) {
1040 template <
typename T>
1046 template <
typename T,
unsigned N>
void grow(size_t MinSize=0)
Double the size of the allocated memory, guaranteeing space for at least one more element or MinSize ...
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize)
This is an implementation of the grow() method which only works on POD-like data types and is out of ...
bool isSmall() const
Return true if this is a smallvector which has not had dynamic memory allocated for it...
void append(size_type NumInputs, const T &Elt)
Add the specified range to the end of the SmallVector.
This is the part of SmallVectorTemplateBase which does not depend on whether the type T is a POD...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
size_t size_in_bytes() const
This returns size()*sizeof(T).
const_pointer data() const
Return a pointer to the vector's buffer, even if empty().
SmallVectorTemplateBase<isPodLike = false> - This is where we put method implementations that are des...
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) into the uninitialized memory starting with "Dest", constructing elements as ne...
size_t capacity_in_bytes() const
capacity_in_bytes - This returns capacity()*sizeof(T).
size_t capacity() const
Return the total number of elements in the currently allocated buffer.
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, typename std::enable_if< std::is_same< typename std::remove_const< T1 >::type, T2 >::value >::type *=nullptr)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
void grow(size_t MinSize=0)
Grow the allocated memory (without initializing new elements), doubling the size of the allocated mem...
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
This is all the non-templated stuff common to all SmallVectors.
void resetToSmall()
Put this vector in a state of being small.
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
Flush-To-Zero and Denormals-Are-Zero mode.
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements as ne...
Storage for the SmallVector elements which aren't contained in SmallVectorTemplateCommon.
pointer data()
Return a pointer to the vector's buffer, even if empty().