tvm
array.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
24 #ifndef TVM_RUNTIME_CONTAINER_ARRAY_H_
25 #define TVM_RUNTIME_CONTAINER_ARRAY_H_
26 
27 #include <algorithm>
28 #include <memory>
29 #include <type_traits>
30 #include <utility>
31 #include <vector>
32 
33 #include "./base.h"
34 #include "./optional.h"
35 
36 namespace tvm {
37 namespace runtime {
38 
40 class ArrayNode : public Object, public InplaceArrayBase<ArrayNode, ObjectRef> {
41  public:
43  size_t size() const { return this->size_; }
44 
50  const ObjectRef at(int64_t i) const { return this->operator[](i); }
51 
53  const ObjectRef* begin() const { return static_cast<ObjectRef*>(InplaceArrayBase::AddressOf(0)); }
54 
56  const ObjectRef* end() const { return begin() + size_; }
57 
59  void clear() { ShrinkBy(size_); }
60 
66  void SetItem(int64_t i, ObjectRef item) { this->operator[](i) = std::move(item); }
67 
74  static ObjectPtr<ArrayNode> CopyFrom(int64_t cap, ArrayNode* from) {
75  int64_t size = from->size_;
76  ICHECK_GE(cap, size) << "ValueError: not enough capacity";
77  ObjectPtr<ArrayNode> p = ArrayNode::Empty(cap);
78  ObjectRef* write = p->MutableBegin();
79  ObjectRef* read = from->MutableBegin();
80  // To ensure exception safety, size is only incremented after the initialization succeeds
81  for (int64_t& i = p->size_ = 0; i < size; ++i) {
82  new (write++) ObjectRef(*read++);
83  }
84  return p;
85  }
86 
93  static ObjectPtr<ArrayNode> MoveFrom(int64_t cap, ArrayNode* from) {
94  int64_t size = from->size_;
95  ICHECK_GE(cap, size) << "ValueError: not enough capacity";
96  ObjectPtr<ArrayNode> p = ArrayNode::Empty(cap);
97  ObjectRef* write = p->MutableBegin();
98  ObjectRef* read = from->MutableBegin();
99  // To ensure exception safety, size is only incremented after the initialization succeeds
100  for (int64_t& i = p->size_ = 0; i < size; ++i) {
101  new (write++) ObjectRef(std::move(*read++));
102  }
103  from->size_ = 0;
104  return p;
105  }
106 
113  static ObjectPtr<ArrayNode> CreateRepeated(int64_t n, const ObjectRef& val) {
114  ObjectPtr<ArrayNode> p = ArrayNode::Empty(n);
115  ObjectRef* itr = p->MutableBegin();
116  for (int64_t& i = p->size_ = 0; i < n; ++i) {
117  new (itr++) ObjectRef(val);
118  }
119  return p;
120  }
121 
122  static constexpr const uint32_t _type_index = TypeIndex::kRuntimeArray;
123  static constexpr const char* _type_key = "Array";
125 
126  private:
128  size_t GetSize() const { return this->size_; }
129 
131  ObjectRef* MutableBegin() const {
132  return static_cast<ObjectRef*>(InplaceArrayBase::AddressOf(0));
133  }
134 
136  ObjectRef* MutableEnd() const { return MutableBegin() + size_; }
137 
143  static ObjectPtr<ArrayNode> Empty(int64_t n = kInitSize) {
144  ICHECK_GE(n, 0);
145  ObjectPtr<ArrayNode> p = make_inplace_array_object<ArrayNode, ObjectRef>(n);
146  p->capacity_ = n;
147  p->size_ = 0;
148  return p;
149  }
150 
159  template <typename IterType>
160  ArrayNode* InitRange(int64_t idx, IterType first, IterType last) {
161  ObjectRef* itr = MutableBegin() + idx;
162  for (; first != last; ++first) {
163  ObjectRef ref = *first;
164  new (itr++) ObjectRef(std::move(ref));
165  }
166  return this;
167  }
168 
176  ArrayNode* MoveElementsLeft(int64_t dst, int64_t src_begin, int64_t src_end) {
177  ObjectRef* from = MutableBegin() + src_begin;
178  ObjectRef* to = MutableBegin() + dst;
179  while (src_begin++ != src_end) {
180  *to++ = std::move(*from++);
181  }
182  return this;
183  }
184 
192  ArrayNode* MoveElementsRight(int64_t dst, int64_t src_begin, int64_t src_end) {
193  ObjectRef* from = MutableBegin() + src_end;
194  ObjectRef* to = MutableBegin() + (src_end - src_begin + dst);
195  while (src_begin++ != src_end) {
196  *--to = std::move(*--from);
197  }
198  return this;
199  }
200 
207  ArrayNode* EnlargeBy(int64_t delta, const ObjectRef& val = ObjectRef(nullptr)) {
208  ObjectRef* itr = MutableEnd();
209  while (delta-- > 0) {
210  new (itr++) ObjectRef(val);
211  ++size_;
212  }
213  return this;
214  }
215 
221  ArrayNode* ShrinkBy(int64_t delta) {
222  ObjectRef* itr = MutableEnd();
223  while (delta-- > 0) {
224  (--itr)->ObjectRef::~ObjectRef();
225  --size_;
226  }
227  return this;
228  }
229 
231  int64_t size_;
232 
234  int64_t capacity_;
235 
237  static constexpr int64_t kInitSize = 4;
238 
240  static constexpr int64_t kIncFactor = 2;
241 
242  // CRTP parent class
243  friend InplaceArrayBase<ArrayNode, ObjectRef>;
244 
245  // Reference class
246  template <typename, typename>
247  friend class Array;
248 
249  // To specialize make_object<ArrayNode>
250  friend ObjectPtr<ArrayNode> make_object<>();
251 };
252 
259 template <typename T, typename IterType>
261  : std::bool_constant<std::is_base_of_v<
262  T, std::remove_cv_t<std::remove_reference_t<decltype(*std::declval<IterType>())>>>> {};
263 
264 template <typename T, typename IterType>
265 struct is_valid_iterator<Optional<T>, IterType> : is_valid_iterator<T, IterType> {};
266 
267 template <typename T, typename IterType>
269 
287 template <typename T,
288  typename = typename std::enable_if<std::is_base_of<ObjectRef, T>::value>::type>
289 class Array : public ObjectRef {
290  public:
291  using value_type = T;
292  // constructors
296  Array() { data_ = ArrayNode::Empty(); }
297 
302  Array(Array<T>&& other) : ObjectRef() { // NOLINT(*)
303  data_ = std::move(other.data_);
304  }
305 
310  Array(const Array<T>& other) : ObjectRef() { // NOLINT(*)
311  data_ = other.data_;
312  }
313 
318  explicit Array(ObjectPtr<Object> n) : ObjectRef(n) {}
319 
326  template <typename IterType>
327  Array(IterType first, IterType last) {
328  static_assert(is_valid_iterator_v<T, IterType>,
329  "IterType cannot be inserted into a tvm::Array<T>");
330  Assign(first, last);
331  }
332 
337  Array(std::initializer_list<T> init) { // NOLINT(*)
338  Assign(init.begin(), init.end());
339  }
340 
345  Array(const std::vector<T>& init) { // NOLINT(*)
346  Assign(init.begin(), init.end());
347  }
348 
354  explicit Array(const size_t n, const T& val) { data_ = ArrayNode::CreateRepeated(n, val); }
355 
362  data_ = std::move(other.data_);
363  return *this;
364  }
365 
371  Array<T>& operator=(const Array<T>& other) {
372  data_ = other.data_;
373  return *this;
374  }
375 
376  public:
377  // iterators
378  struct ValueConverter {
379  using ResultType = T;
380  static T convert(const ObjectRef& n) { return DowncastNoCheck<T>(n); }
381  };
382 
385 
387  iterator begin() const { return iterator(GetArrayNode()->begin()); }
388 
390  iterator end() const { return iterator(GetArrayNode()->end()); }
391 
394  // ArrayNode::end() is never nullptr
395  return reverse_iterator(GetArrayNode()->end() - 1);
396  }
397 
400  // ArrayNode::begin() is never nullptr
401  return reverse_iterator(GetArrayNode()->begin() - 1);
402  }
403 
404  public:
405  // const methods in std::vector
411  const T operator[](int64_t i) const {
412  ArrayNode* p = GetArrayNode();
413  ICHECK(p != nullptr) << "ValueError: cannot index a null array";
414  ICHECK(0 <= i && i < p->size_)
415  << "IndexError: indexing " << i << " on an array of size " << p->size_;
416  return DowncastNoCheck<T>(*(p->begin() + i));
417  }
418 
420  size_t size() const {
421  ArrayNode* p = GetArrayNode();
422  return p == nullptr ? 0 : GetArrayNode()->size_;
423  }
424 
426  size_t capacity() const {
427  ArrayNode* p = GetArrayNode();
428  return p == nullptr ? 0 : GetArrayNode()->capacity_;
429  }
430 
432  bool empty() const { return size() == 0; }
433 
435  const T front() const {
436  ArrayNode* p = GetArrayNode();
437  ICHECK(p != nullptr) << "ValueError: cannot index a null array";
438  ICHECK_GT(p->size_, 0) << "IndexError: cannot index an empty array";
439  return DowncastNoCheck<T>(*(p->begin()));
440  }
441 
443  const T back() const {
444  ArrayNode* p = GetArrayNode();
445  ICHECK(p != nullptr) << "ValueError: cannot index a null array";
446  ICHECK_GT(p->size_, 0) << "IndexError: cannot index an empty array";
447  return DowncastNoCheck<T>(*(p->end() - 1));
448  }
449 
450  public:
451  // mutation in std::vector, implements copy-on-write
452 
457  void push_back(const T& item) {
458  ArrayNode* p = CopyOnWrite(1);
459  p->EmplaceInit(p->size_++, item);
460  }
461 
467  void insert(iterator position, const T& val) {
468  ICHECK(data_ != nullptr) << "ValueError: cannot insert a null array";
469  int64_t idx = std::distance(begin(), position);
470  int64_t size = GetArrayNode()->size_;
471  auto addr = CopyOnWrite(1) //
472  ->EnlargeBy(1) //
473  ->MoveElementsRight(idx + 1, idx, size) //
474  ->MutableBegin();
475  new (addr + idx) ObjectRef(val);
476  }
477 
484  template <typename IterType>
485  void insert(iterator position, IterType first, IterType last) {
486  static_assert(is_valid_iterator_v<T, IterType>,
487  "IterType cannot be inserted into a tvm::Array<T>");
488 
489  if (first == last) {
490  return;
491  }
492  ICHECK(data_ != nullptr) << "ValueError: cannot insert a null array";
493  int64_t idx = std::distance(begin(), position);
494  int64_t size = GetArrayNode()->size_;
495  int64_t numel = std::distance(first, last);
496  CopyOnWrite(numel)
497  ->EnlargeBy(numel)
498  ->MoveElementsRight(idx + numel, idx, size)
499  ->InitRange(idx, first, last);
500  }
501 
503  void pop_back() {
504  ICHECK(data_ != nullptr) << "ValueError: cannot pop_back because array is null";
505  int64_t size = GetArrayNode()->size_;
506  ICHECK_GT(size, 0) << "ValueError: cannot pop_back because array is empty";
507  CopyOnWrite()->ShrinkBy(1);
508  }
509 
514  void erase(iterator position) {
515  ICHECK(data_ != nullptr) << "ValueError: cannot erase a null array";
516  int64_t st = std::distance(begin(), position);
517  int64_t size = GetArrayNode()->size_;
518  ICHECK(0 <= st && st < size) << "ValueError: cannot erase at index " << st
519  << ", because Array size is " << size;
520  CopyOnWrite() //
521  ->MoveElementsLeft(st, st + 1, size) //
522  ->ShrinkBy(1);
523  }
524 
530  void erase(iterator first, iterator last) {
531  if (first == last) {
532  return;
533  }
534  ICHECK(data_ != nullptr) << "ValueError: cannot erase a null array";
535  int64_t size = GetArrayNode()->size_;
536  int64_t st = std::distance(begin(), first);
537  int64_t ed = std::distance(begin(), last);
538  ICHECK_LT(st, ed) << "ValueError: cannot erase array in range [" << st << ", " << ed << ")";
539  ICHECK(0 <= st && st <= size && 0 <= ed && ed <= size)
540  << "ValueError: cannot erase array in range [" << st << ", " << ed << ")"
541  << ", because array size is " << size;
542  CopyOnWrite() //
543  ->MoveElementsLeft(st, ed, size) //
544  ->ShrinkBy(ed - st);
545  }
546 
551  void resize(int64_t n) {
552  ICHECK_GE(n, 0) << "ValueError: cannot resize an Array to negative size";
553  if (data_ == nullptr) {
554  SwitchContainer(n);
555  return;
556  }
557  int64_t size = GetArrayNode()->size_;
558  if (size < n) {
559  CopyOnWrite(n - size)->EnlargeBy(n - size);
560  } else if (size > n) {
561  CopyOnWrite()->ShrinkBy(size - n);
562  }
563  }
564 
569  void reserve(int64_t n) {
570  if (data_ == nullptr || n > GetArrayNode()->capacity_) {
571  SwitchContainer(n);
572  }
573  }
574 
576  void clear() {
577  if (data_ != nullptr) {
578  ArrayNode* p = CopyOnWrite();
579  p->clear();
580  }
581  }
582 
583  template <typename... Args>
584  static size_t CalcCapacityImpl() {
585  return 0;
586  }
587 
588  template <typename... Args>
589  static size_t CalcCapacityImpl(Array<T> value, Args... args) {
590  return value.size() + CalcCapacityImpl(args...);
591  }
592 
593  template <typename... Args>
594  static size_t CalcCapacityImpl(T value, Args... args) {
595  return 1 + CalcCapacityImpl(args...);
596  }
597 
598  template <typename... Args>
599  static void AgregateImpl(Array<T>& dest) {} // NOLINT(*)
600 
601  template <typename... Args>
602  static void AgregateImpl(Array<T>& dest, Array<T> value, Args... args) { // NOLINT(*)
603  dest.insert(dest.end(), value.begin(), value.end());
604  AgregateImpl(dest, args...);
605  }
606 
607  template <typename... Args>
608  static void AgregateImpl(Array<T>& dest, T value, Args... args) { // NOLINT(*)
609  dest.push_back(value);
610  AgregateImpl(dest, args...);
611  }
612 
613  public:
614  // Array's own methods
615 
621  void Set(int64_t i, T value) {
622  ArrayNode* p = this->CopyOnWrite();
623  ICHECK(0 <= i && i < p->size_)
624  << "IndexError: indexing " << i << " on an array of size " << p->size_;
625  *(p->MutableBegin() + i) = std::move(value);
626  }
627 
629  ArrayNode* GetArrayNode() const { return static_cast<ArrayNode*>(data_.get()); }
630 
650  template <typename F, typename U = std::invoke_result_t<F, T>>
651  Array<U> Map(F fmap) const {
652  return Array<U>(MapHelper(data_, fmap));
653  }
654 
661  template <typename F, typename = std::enable_if_t<std::is_same_v<T, std::invoke_result_t<F, T>>>>
662  void MutateByApply(F fmutate) {
663  data_ = MapHelper(std::move(data_), fmutate);
664  }
665 
672  template <typename IterType>
673  void Assign(IterType first, IterType last) {
674  int64_t cap = std::distance(first, last);
675  ICHECK_GE(cap, 0) << "ValueError: cannot construct an Array of negative size";
676  ArrayNode* p = GetArrayNode();
677  if (p != nullptr && data_.unique() && p->capacity_ >= cap) {
678  // do not have to make new space
679  p->clear();
680  } else {
681  // create new space
682  data_ = ArrayNode::Empty(cap);
683  p = GetArrayNode();
684  }
685  // To ensure exception safety, size is only incremented after the initialization succeeds
686  ObjectRef* itr = p->MutableBegin();
687  for (int64_t& i = p->size_ = 0; i < cap; ++i, ++first, ++itr) {
688  new (itr) ObjectRef(*first);
689  }
690  }
691 
701  if (data_ == nullptr) {
702  return SwitchContainer(ArrayNode::kInitSize);
703  }
704  if (!data_.unique()) {
705  return SwitchContainer(capacity());
706  }
707  return static_cast<ArrayNode*>(data_.get());
708  }
709 
712 
718  template <typename... Args>
719  static Array<T> Agregate(Args... args) {
720  Array<T> result;
721  result.reserve(CalcCapacityImpl(args...));
722  AgregateImpl(result, args...);
723  return result;
724  }
725 
726  private:
732  ArrayNode* CopyOnWrite(int64_t reserve_extra) {
733  ArrayNode* p = GetArrayNode();
734  if (p == nullptr) {
735  // necessary to get around the constexpr address issue before c++17
736  const int64_t kInitSize = ArrayNode::kInitSize;
737  return SwitchContainer(std::max(kInitSize, reserve_extra));
738  }
739  if (p->capacity_ >= p->size_ + reserve_extra) {
740  return CopyOnWrite();
741  }
742  int64_t cap = p->capacity_ * ArrayNode::kIncFactor;
743  cap = std::max(cap, p->size_ + reserve_extra);
744  return SwitchContainer(cap);
745  }
746 
751  ArrayNode* SwitchContainer(int64_t capacity) {
752  if (data_ == nullptr) {
753  data_ = ArrayNode::Empty(capacity);
754  } else if (data_.unique()) {
756  } else {
758  }
759  return static_cast<ArrayNode*>(data_.get());
760  }
761 
784  template <typename F, typename U = std::invoke_result_t<F, T>>
785  static ObjectPtr<Object> MapHelper(ObjectPtr<Object> data, F fmap) {
786  if (data == nullptr) {
787  return nullptr;
788  }
789 
790  ICHECK(data->IsInstance<ArrayNode>());
791 
792  constexpr bool is_same_output_type = std::is_same_v<T, U>;
793 
794  if constexpr (is_same_output_type) {
795  if (data.unique()) {
796  // Mutate-in-place path. Only allowed if the output type U is
797  // the same as type T, we have a mutable this*, and there are
798  // no other shared copies of the array.
799  auto arr = static_cast<ArrayNode*>(data.get());
800  for (auto it = arr->MutableBegin(); it != arr->MutableEnd(); it++) {
801  T mapped = fmap(DowncastNoCheck<T>(std::move(*it)));
802  *it = std::move(mapped);
803  }
804  return data;
805  }
806  }
807 
808  constexpr bool compatible_types = is_valid_iterator_v<T, U*> || is_valid_iterator_v<U, T*>;
809 
810  ObjectPtr<ArrayNode> output = nullptr;
811  auto arr = static_cast<ArrayNode*>(data.get());
812 
813  auto it = arr->begin();
814  if constexpr (compatible_types) {
815  // Copy-on-write path, if the output Array<U> might be
816  // represented by the same underlying array as the existing
817  // Array<T>. Typically, this is for functions that map `T` to
818  // `T`, but can also apply to functions that map `T` to
819  // `Optional<T>`, or that map `T` to a subclass or superclass of
820  // `T`.
821  bool all_identical = true;
822  for (; it != arr->end(); it++) {
823  U mapped = fmap(DowncastNoCheck<T>(*it));
824  if (!mapped.same_as(*it)) {
825  // At least one mapped element is different than the
826  // original. Therefore, prepare the output array,
827  // consisting of any previous elements that had mapped to
828  // themselves (if any), and the element that didn't map to
829  // itself.
830  all_identical = false;
831  output = ArrayNode::CreateRepeated(arr->size(), U());
832  output->InitRange(0, arr->begin(), it);
833  output->SetItem(it - arr->begin(), std::move(mapped));
834  it++;
835  break;
836  }
837  }
838  if (all_identical) {
839  return data;
840  }
841  } else {
842  // Path for incompatible types. The constexpr check for
843  // compatible types isn't strictly necessary, as the first
844  // mapped.same_as(*it) would return false, but we might as well
845  // avoid it altogether.
846  output = ArrayNode::CreateRepeated(arr->size(), U());
847  }
848 
849  // Normal path for incompatible types, or post-copy path for
850  // copy-on-write instances.
851  //
852  // If the types are incompatible, then at this point `output` is
853  // empty, and `it` points to the first element of the input.
854  //
855  // If the types were compatible, then at this point `output`
856  // contains zero or more elements that mapped to themselves
857  // followed by the first element that does not map to itself, and
858  // `it` points to the element just after the first element that
859  // does not map to itself. Because at least one element has been
860  // changed, we no longer have the opportunity to avoid a copy, so
861  // we don't need to check the result.
862  //
863  // In both cases, `it` points to the next element to be processed,
864  // so we can either start or resume the iteration from that point,
865  // with no further checks on the result.
866  for (; it != arr->end(); it++) {
867  U mapped = fmap(DowncastNoCheck<T>(*it));
868  output->SetItem(it - arr->begin(), std::move(mapped));
869  }
870 
871  return output;
872  }
873 };
874 
875 template <typename T>
876 inline constexpr bool is_tvm_array = false;
877 
878 template <typename T>
879 inline constexpr bool is_tvm_array<Array<T>> = true;
880 
887 template <typename T,
888  typename = typename std::enable_if<std::is_base_of<ObjectRef, T>::value>::type>
889 inline Array<T> Concat(Array<T> lhs, const Array<T>& rhs) {
890  for (const auto& x : rhs) {
891  lhs.push_back(x);
892  }
893  return std::move(lhs);
894 }
895 
896 // Specialize make_object<ArrayNode> to make sure it is correct.
897 template <>
899  return ArrayNode::Empty();
900 }
901 
902 } // namespace runtime
903 
904 // expose the functions to the root namespace.
905 using runtime::Array;
906 using runtime::ArrayNode;
907 } // namespace tvm
908 
909 #endif // TVM_RUNTIME_CONTAINER_ARRAY_H_
array node content in array
Definition: array.h:40
static ObjectPtr< ArrayNode > MoveFrom(int64_t cap, ArrayNode *from)
Constructs a container and move from another.
Definition: array.h:93
void SetItem(int64_t i, ObjectRef item)
Set i-th element of the array in-place.
Definition: array.h:66
const ObjectRef * begin() const
Definition: array.h:53
const ObjectRef * end() const
Definition: array.h:56
size_t size() const
Definition: array.h:43
const ObjectRef at(int64_t i) const
Read i-th element from array.
Definition: array.h:50
static constexpr const char * _type_key
Definition: array.h:123
void clear()
Release reference to all the elements.
Definition: array.h:59
static constexpr const uint32_t _type_index
Definition: array.h:122
static ObjectPtr< ArrayNode > CreateRepeated(int64_t n, const ObjectRef &val)
Constructs a container with n elements. Each element is a copy of val.
Definition: array.h:113
static ObjectPtr< ArrayNode > CopyFrom(int64_t cap, ArrayNode *from)
Constructs a container and copy from another.
Definition: array.h:74
TVM_DECLARE_FINAL_OBJECT_INFO(ArrayNode, Object)
Array, container representing a contiguous sequence of ObjectRefs.
Definition: array.h:289
void clear()
Release reference to all the elements.
Definition: array.h:576
const T back() const
Definition: array.h:443
void erase(iterator position)
Erase an element on the given position.
Definition: array.h:514
static void AgregateImpl(Array< T > &dest, Array< T > value, Args... args)
Definition: array.h:602
void reserve(int64_t n)
Make sure the list has the capacity of at least n.
Definition: array.h:569
reverse_iterator rend() const
Definition: array.h:399
T value_type
Definition: array.h:291
size_t capacity() const
Definition: array.h:426
Array(std::initializer_list< T > init)
constructor from initializer list
Definition: array.h:337
ReverseIterAdapter< ValueConverter, const ObjectRef * > reverse_iterator
Definition: array.h:384
static void AgregateImpl(Array< T > &dest, T value, Args... args)
Definition: array.h:608
const T front() const
Definition: array.h:435
ArrayNode * GetArrayNode() const
Definition: array.h:629
Array< U > Map(F fmap) const
Helper function to apply a map function onto the array.
Definition: array.h:651
Array< T > & operator=(const Array< T > &other)
copy assign operator
Definition: array.h:371
void MutateByApply(F fmutate)
Helper function to apply fmutate to mutate an array.
Definition: array.h:662
void erase(iterator first, iterator last)
Erase a given range of elements.
Definition: array.h:530
iterator end() const
Definition: array.h:390
void insert(iterator position, const T &val)
Insert an element into the given position.
Definition: array.h:467
bool empty() const
Definition: array.h:432
Array(const Array< T > &other)
copy constructor
Definition: array.h:310
Array(const size_t n, const T &val)
Constructs a container with n elements. Each element is a copy of val.
Definition: array.h:354
void resize(int64_t n)
Resize the array.
Definition: array.h:551
Array(Array< T > &&other)
move constructor
Definition: array.h:302
static void AgregateImpl(Array< T > &dest)
Definition: array.h:599
Array< T > & operator=(Array< T > &&other)
move assign operator
Definition: array.h:361
IterAdapter< ValueConverter, const ObjectRef * > iterator
Definition: array.h:383
Array(const std::vector< T > &init)
constructor from vector
Definition: array.h:345
static size_t CalcCapacityImpl(T value, Args... args)
Definition: array.h:594
void push_back(const T &item)
push a new item to the back of the list
Definition: array.h:457
void pop_back()
Remove the last item of the list.
Definition: array.h:503
Array(IterType first, IterType last)
Constructor from iterator.
Definition: array.h:327
void insert(iterator position, IterType first, IterType last)
Insert a range of elements into the given position.
Definition: array.h:485
void Set(int64_t i, T value)
set i-th element of the array.
Definition: array.h:621
void Assign(IterType first, IterType last)
reset the array to content from iterator.
Definition: array.h:673
const T operator[](int64_t i) const
Immutably read i-th element from array.
Definition: array.h:411
static Array< T > Agregate(Args... args)
Agregate arguments into a single Array<T>
Definition: array.h:719
static size_t CalcCapacityImpl()
Definition: array.h:584
ArrayNode * CopyOnWrite()
Copy on write semantics Do nothing if current handle is the unique copy of the array....
Definition: array.h:700
iterator begin() const
Definition: array.h:387
size_t size() const
Definition: array.h:420
reverse_iterator rbegin() const
Definition: array.h:393
Array(ObjectPtr< Object > n)
constructor from pointer
Definition: array.h:318
static size_t CalcCapacityImpl(Array< T > value, Args... args)
Definition: array.h:589
Array()
default constructor
Definition: array.h:296
Base template for classes with array like memory layout.
Definition: base.h:100
void * AddressOf(size_t idx) const
Return the raw pointer to the element at idx.
Definition: base.h:169
const ObjectRef & operator[](size_t idx) const
Access element at index.
Definition: base.h:107
void EmplaceInit(size_t idx, Args &&... args)
Construct a value in place with the arguments.
Definition: base.h:149
iterator adapter that adapts TIter to return another type.
Definition: base.h:188
A custom smart pointer for Object.
Definition: object.h:362
Base class of all object reference.
Definition: object.h:519
ObjectRef()=default
default constructor
ObjectPtr< Object > data_
Internal pointer that backs the reference.
Definition: object.h:605
base class of all object containers.
Definition: object.h:171
Optional container that to represent to a Nullable variant of T.
Definition: optional.h:51
iterator adapter that adapts TIter to return another type.
Definition: base.h:241
constexpr bool is_tvm_array
Definition: array.h:876
ObjectPtr< ArrayNode > make_object()
Definition: array.h:898
Array< T > Concat(Array< T > lhs, const Array< T > &rhs)
Concat two Arrays.
Definition: array.h:889
constexpr bool is_valid_iterator_v
Definition: array.h:268
runtime implementation for LibTorch/TorchScript.
Definition: analyzer.h:36
PrimExpr max(PrimExpr a, PrimExpr b, Span span=Span())
take maximum of two values
Runtime Optional container types.
T ResultType
Definition: array.h:379
static T convert(const ObjectRef &n)
Definition: array.h:380
@ kRuntimeArray
runtime::Array.
Definition: object.h:68
Helper struct for type-checking.
Definition: array.h:262