You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

small_vector.h 30 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /**
  2. * \file dnn/include/megdnn/thin/small_vector.h
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
  12. //
  13. // The LLVM Compiler Infrastructure
  14. //
  15. // This file is distributed under the University of Illinois Open Source
  16. // License. See LICENSE.TXT for details.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. //
  20. // This file defines the SmallVector class.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. /**
  24. * \file include/megdnn/thin/small_vector.h
  25. *
  26. * This file is part of MegDNN, a deep neural network run-time library
  27. * developed by Megvii.
  28. *
  29. * \brief thin megdnn function
  30. *
  31. * \copyright Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  32. */
  33. #pragma once
  34. #include "megdnn/arch.h"
  35. #include <algorithm>
  36. #include <cstdlib>
  37. #include <cstring>
  38. #include <iterator>
  39. #include <limits>
  40. #include <memory>
  41. #include <type_traits>
  42. #include "megdnn/internal/visibility_prologue.h"
  43. namespace megdnn {
  44. class SmallVectorBase {
  45. protected:
  46. void *m_begin_ptr, *m_end_ptr, *m_capacity_ptr;
  47. MEGDNN_NORETURN static void on_invalid_at(size_t idx, size_t size);
  48. protected:
  49. SmallVectorBase(void* first_elm, size_t size)
  50. : m_begin_ptr(first_elm),
  51. m_end_ptr(first_elm),
  52. m_capacity_ptr(static_cast<char*>(first_elm) + size) {}
  53. void grow_pod(void* first_elm_ptr, size_t min_sz_in_bytes,
  54. size_t type_size);
  55. public:
  56. size_t size_in_bytes() const {
  57. return size_t(static_cast<char*>(m_end_ptr) -
  58. static_cast<char*>(m_begin_ptr));
  59. }
  60. size_t capacity_in_bytes() const {
  61. return size_t(static_cast<char*>(m_capacity_ptr) -
  62. static_cast<char*>(m_begin_ptr));
  63. }
  64. bool empty() const { return m_begin_ptr == m_end_ptr; }
  65. };
  66. template <typename T, typename = void>
  67. class SmallVectorTemplateCommon : public SmallVectorBase {
  68. private:
  69. template <typename, unsigned>
  70. friend struct SmallVectorStorage;
  71. using U = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
  72. U m_first_elm;
  73. protected:
  74. SmallVectorTemplateCommon(size_t size)
  75. : SmallVectorBase(&m_first_elm, size) {}
  76. void grow_pod(size_t min_sz_in_bytes, size_t type_size) {
  77. SmallVectorBase::grow_pod(&m_first_elm, min_sz_in_bytes, type_size);
  78. }
  79. bool is_small() {
  80. return m_begin_ptr == static_cast<const void*>(&m_first_elm);
  81. }
  82. void reset_to_small() {
  83. m_begin_ptr = m_end_ptr = m_capacity_ptr = &m_first_elm;
  84. }
  85. void set_end(T* p) { m_end_ptr = p; }
  86. public:
  87. using size_type = size_t;
  88. using difference_type = std::ptrdiff_t;
  89. using value_type = T;
  90. using iterator = T*;
  91. using const_iterator = const T*;
  92. using reverse_iterator = std::reverse_iterator<iterator>;
  93. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  94. using reference = T&;
  95. using const_reference = const T&;
  96. using pointer = T*;
  97. using const_pointer = const T*;
  98. size_t capacity() const { return capacity_ptr() - begin(); }
  99. protected:
  100. iterator capacity_ptr() { return static_cast<iterator>(m_capacity_ptr); }
  101. const_iterator capacity_ptr() const {
  102. return static_cast<const_iterator>(m_capacity_ptr);
  103. }
  104. public:
  105. // forwarding iterator creation
  106. iterator begin() { return static_cast<iterator>(m_begin_ptr); }
  107. const_iterator begin() const {
  108. return static_cast<const_iterator>(m_begin_ptr);
  109. }
  110. const_iterator cbegin() const {
  111. return static_cast<const_iterator>(m_begin_ptr);
  112. }
  113. iterator end() { return static_cast<iterator>(m_end_ptr); }
  114. const_iterator end() const {
  115. return static_cast<const_iterator>(m_end_ptr);
  116. }
  117. const_iterator cend() const {
  118. return static_cast<const_iterator>(m_end_ptr);
  119. }
  120. reference at(size_type idx) {
  121. if (idx >= size()) {
  122. on_invalid_at(idx, size());
  123. }
  124. return begin()[idx];
  125. }
  126. const_reference at(size_type idx) const {
  127. if (idx >= size()) {
  128. on_invalid_at(idx, size());
  129. }
  130. return begin()[idx];
  131. }
  132. reference operator[](size_type idx) { return begin()[idx]; }
  133. const_reference operator[](size_type idx) const { return begin()[idx]; }
  134. reference front() { return begin()[0]; }
  135. const_reference front() const { return begin()[0]; }
  136. reference back() { return rbegin()[0]; }
  137. const_reference back() const { return rbegin()[0]; }
  138. // reverse iterator creation method.
  139. reverse_iterator rbegin() { return reverse_iterator(end()); }
  140. const_reverse_iterator rbegin() const {
  141. return const_reverse_iterator(end());
  142. }
  143. reverse_iterator rend() { return reverse_iterator(begin()); }
  144. const_reverse_iterator rend() const {
  145. return const_reverse_iterator(begin());
  146. }
  147. pointer data() { return pointer(begin()); }
  148. const_pointer data() const { return const_pointer(begin()); }
  149. size_type size() const { return end() - begin(); }
  150. size_type max_size() const {
  151. return std::numeric_limits<size_type>::max() / sizeof(T);
  152. }
  153. template <typename in_iter>
  154. in_iter find(in_iter first, in_iter last, const T& value) const {
  155. while (first != last) {
  156. if (*first == value)
  157. return first;
  158. ++first;
  159. }
  160. return last;
  161. }
  162. };
  163. template <typename T, bool is_pod>
  164. class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
  165. protected:
  166. SmallVectorTemplateBase(size_t size) : SmallVectorTemplateCommon<T>(size) {}
  167. static void destroy_range(T* start, T* end) {
  168. while (start != end) {
  169. --end;
  170. end->~T();
  171. }
  172. }
  173. template <typename It1, typename It2>
  174. static void uninitialized_move(It1 first, It1 last, It2 dest) {
  175. std::uninitialized_copy(std::make_move_iterator(first),
  176. std::make_move_iterator(last), dest);
  177. }
  178. template <typename It1, typename It2>
  179. static void uninitialized_copy(It1 first, It1 last, It2 dest) {
  180. std::uninitialized_copy(first, last, dest);
  181. }
  182. void grow(size_t min_sz = 0);
  183. public:
  184. void push_back(const T& _elm) {
  185. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  186. T elm = _elm;
  187. this->grow();
  188. new (static_cast<void*>(this->end())) T(std::move(elm));
  189. } else {
  190. new (static_cast<void*>(this->end())) T(_elm);
  191. }
  192. this->set_end(this->end() + 1);
  193. }
  194. void push_back(T&& elm) {
  195. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  196. this->grow();
  197. }
  198. new (static_cast<void*>(this->end())) T(std::move(elm));
  199. this->set_end(this->end() + 1);
  200. }
  201. void pop_back() {
  202. this->set_end(this->end() - 1);
  203. this->end()->~T();
  204. }
  205. };
  206. template <typename T, bool is_pod>
  207. void SmallVectorTemplateBase<T, is_pod>::grow(size_t min_sz) {
  208. size_t cur_capacity = this->capacity();
  209. size_t cur_sz = this->size();
  210. size_t new_capacity = (cur_capacity + 2) * 2;
  211. if (new_capacity < min_sz) {
  212. new_capacity = min_sz;
  213. }
  214. T* elms = static_cast<T*>(malloc(new_capacity * sizeof(T)));
  215. this->uninitialized_move(this->begin(), this->end(), elms);
  216. this->destroy_range(this->begin(), this->end());
  217. if (!this->is_small()) {
  218. free(this->begin());
  219. }
  220. this->m_begin_ptr = elms;
  221. this->set_end(elms + cur_sz);
  222. this->m_capacity_ptr = this->begin() + new_capacity;
  223. }
  224. template <typename T>
  225. class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
  226. protected:
  227. SmallVectorTemplateBase(size_t size) : SmallVectorTemplateCommon<T>(size) {}
  228. static void destroy_range(T*, T*) {}
  229. template <typename It1, typename It2>
  230. static void uninitialized_move(It1 first, It1 last, It2 dest) {
  231. uninitialized_copy(first, last, dest);
  232. }
  233. template <typename It1, typename It2>
  234. static void uninitialized_copy(It1 first, It1 last, It2 dest) {
  235. std::uninitialized_copy(first, last, dest);
  236. }
  237. template <typename T1, typename T2>
  238. static void uninitialized_copy(
  239. T1* first, T1* last, T2* dest,
  240. typename std::enable_if<std::is_same<
  241. typename std::remove_const<T1>::type, T2>::value>::type* =
  242. nullptr) {
  243. if (first != last)
  244. memcpy(dest, first, (last - first) * sizeof(T));
  245. }
  246. void grow(size_t min_sz = 0) {
  247. this->grow_pod(min_sz * sizeof(T), sizeof(T));
  248. }
  249. public:
  250. void push_back(const T& _elm) {
  251. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  252. T elm = _elm;
  253. this->grow();
  254. memcpy(this->end(), &elm, sizeof(T));
  255. } else {
  256. memcpy(this->end(), &_elm, sizeof(T));
  257. }
  258. this->set_end(this->end() + 1);
  259. }
  260. void pop_back() { this->set_end(this->end() - 1); }
  261. };
  262. /*!
  263. * \brief the implementation class of SmallVector
  264. *
  265. * SmallVector<T, N> can be converted to SmallVectorImpl<T> to erase N
  266. */
  267. template <typename T>
  268. class SmallVectorImpl
  269. : public SmallVectorTemplateBase<T, std::is_pod<T>::value> {
  270. using SuperClass = SmallVectorTemplateBase<T, std::is_pod<T>::value>;
  271. public:
  272. using iterator = typename SuperClass::iterator;
  273. using const_iterator = typename SuperClass::const_iterator;
  274. using size_type = typename SuperClass::size_type;
  275. protected:
  276. explicit SmallVectorImpl(unsigned n)
  277. : SmallVectorTemplateBase<T, std::is_pod<T>::value>(n * sizeof(T)) {
  278. }
  279. public:
  280. SmallVectorImpl(const SmallVectorImpl&) = delete;
  281. ~SmallVectorImpl() {
  282. this->destroy_range(this->begin(), this->end());
  283. if (!this->is_small())
  284. free(this->begin());
  285. }
  286. void clear() {
  287. this->destroy_range(this->begin(), this->end());
  288. this->m_end_ptr = this->m_begin_ptr;
  289. }
  290. void resize(size_type n) {
  291. if (n < this->size()) {
  292. this->destroy_range(this->begin() + n, this->end());
  293. this->set_end(this->begin() + n);
  294. } else if (n > this->size()) {
  295. if (this->capacity() < n)
  296. this->grow(n);
  297. for (auto it = this->end(), end = this->begin() + n; it != end;
  298. ++it)
  299. new (&*it) T();
  300. this->set_end(this->begin() + n);
  301. }
  302. }
  303. void resize(size_type n, const T& _nv) {
  304. T nv = _nv;
  305. if (n < this->size()) {
  306. this->destroy_range(this->begin() + n, this->end());
  307. this->set_end(this->begin() + n);
  308. } else if (n > this->size()) {
  309. if (this->capacity() < n)
  310. this->grow(n);
  311. std::uninitialized_fill(this->end(), this->begin() + n, nv);
  312. this->set_end(this->begin() + n);
  313. }
  314. }
  315. void reserve(size_type n) {
  316. if (this->capacity() < n) {
  317. this->grow(n);
  318. }
  319. }
  320. T pop_back_val() {
  321. T result = std::move(this->back());
  322. this->pop_back();
  323. return result;
  324. }
  325. void swap(SmallVectorImpl<T>& rhs);
  326. /// Add the specified range to the end of the SmallVector.
  327. template <typename in_iter,
  328. typename = typename std::enable_if<std::is_convertible<
  329. typename std::iterator_traits<in_iter>::iterator_category,
  330. std::input_iterator_tag>::value>::type>
  331. void append(in_iter in_start, in_iter in_end) {
  332. size_type num_inputs = std::distance(in_start, in_end);
  333. // Grow allocated space if needed.
  334. if (num_inputs > size_type(this->capacity_ptr() - this->end()))
  335. this->grow(this->size() + num_inputs);
  336. // Copy the new elements over.
  337. this->uninitialized_copy(in_start, in_end, this->end());
  338. this->set_end(this->end() + num_inputs);
  339. }
  340. /// Add the specified range to the end of the SmallVector.
  341. void append(size_type num_inputs, const T& _elm) {
  342. T elm = _elm;
  343. // Grow allocated space if needed.
  344. if (num_inputs > size_type(this->capacity_ptr() - this->end()))
  345. this->grow(this->size() + num_inputs);
  346. // Copy the new elements over.
  347. std::uninitialized_fill_n(this->end(), num_inputs, elm);
  348. this->set_end(this->end() + num_inputs);
  349. }
  350. void append(std::initializer_list<T> init_list) {
  351. append(init_list.begin(), init_list.end());
  352. }
  353. // FIXME: Consider assigning over existing elements, rather than clearing &
  354. // re-initializing them - for all assign(...) variants.
  355. void assign(size_type num_elms, const T& _elm) {
  356. T elm = _elm;
  357. clear();
  358. if (this->capacity() < num_elms)
  359. this->grow(num_elms);
  360. this->set_end(this->begin() + num_elms);
  361. std::uninitialized_fill(this->begin(), this->end(), elm);
  362. }
  363. template <typename in_iter,
  364. typename = typename std::enable_if<std::is_convertible<
  365. typename std::iterator_traits<in_iter>::iterator_category,
  366. std::input_iterator_tag>::value>::type>
  367. void assign(in_iter in_start, in_iter in_end) {
  368. clear();
  369. append(in_start, in_end);
  370. }
  371. void assign(std::initializer_list<T> init_list) {
  372. clear();
  373. append(init_list);
  374. }
  375. iterator erase(const_iterator cit) {
  376. // Just cast away constness because this is a non-const member function.
  377. iterator it = const_cast<iterator>(cit);
  378. iterator n = it;
  379. // Shift all elms down one.
  380. std::move(it + 1, this->end(), it);
  381. // Drop the last elm.
  382. this->pop_back();
  383. return (n);
  384. }
  385. iterator erase(const_iterator c_first, const_iterator c_last) {
  386. // Just cast away constness because this is a non-const member function.
  387. iterator first = const_cast<iterator>(c_first);
  388. iterator last = const_cast<iterator>(c_last);
  389. iterator n = first;
  390. // Shift all elms down.
  391. iterator it = std::move(last, this->end(), first);
  392. // Drop the last elms.
  393. this->destroy_range(it, this->end());
  394. this->set_end(it);
  395. return (n);
  396. }
  397. iterator insert(iterator it, T&& elm) {
  398. if (it == this->end()) { // Important special case for empty vector.
  399. this->push_back(std::move(elm));
  400. return this->end() - 1;
  401. }
  402. if (this->m_end_ptr >= this->m_capacity_ptr) {
  403. size_t elm_idx = it - this->begin();
  404. this->grow();
  405. it = this->begin() + elm_idx;
  406. }
  407. new (static_cast<void*>(this->end())) T(std::move(this->back()));
  408. // Push everything else over.
  409. std::move_backward(it, this->end() - 1, this->end());
  410. this->set_end(this->end() + 1);
  411. // If we just moved the element we're inserting, be sure to update
  412. // the reference.
  413. T* elm_ptr = &elm;
  414. if (it <= elm_ptr && elm_ptr < this->m_end_ptr)
  415. ++elm_ptr;
  416. *it = std::move(*elm_ptr);
  417. return it;
  418. }
  419. iterator insert(iterator it, const T& _elm) {
  420. if (it == this->end()) { // Important special case for empty vector.
  421. this->push_back(_elm);
  422. return this->end() - 1;
  423. }
  424. T elm = _elm;
  425. if (this->m_end_ptr >= this->m_capacity_ptr) {
  426. size_t elm_idx = it - this->begin();
  427. this->grow();
  428. it = this->begin() + elm_idx;
  429. }
  430. new (static_cast<void*>(this->end())) T(std::move(this->back()));
  431. // Push everything else over.
  432. std::move_backward(it, this->end() - 1, this->end());
  433. this->set_end(this->end() + 1);
  434. // If we just moved the element we're inserting, be sure to update
  435. // the reference.
  436. const T* elm_ptr = &elm;
  437. if (it <= elm_ptr && elm_ptr < this->m_end_ptr)
  438. ++elm_ptr;
  439. *it = *elm_ptr;
  440. return it;
  441. }
  442. iterator insert(iterator it, size_type num_to_insert, const T& _elm) {
  443. // Convert iterator to elm# to avoid invalidating iterator
  444. // when we reserve()
  445. size_t elm_idx = it - this->begin();
  446. if (it == this->end()) { // Important special case for empty vector.
  447. append(num_to_insert, _elm);
  448. return this->begin() + elm_idx;
  449. }
  450. T elm = _elm;
  451. // Ensure there is enough space.
  452. reserve(this->size() + num_to_insert);
  453. // Uninvalidate the iterator.
  454. it = this->begin() + elm_idx;
  455. // If there are more elements between the insertion point and
  456. // the end of the range than there are being inserted,
  457. // we can use a simple approach to insertion.
  458. // Since we already reserved space, we know that this won't
  459. // reallocate the vector.
  460. if (size_t(this->end() - it) >= num_to_insert) {
  461. T* old_end = this->end();
  462. append(std::move_iterator<iterator>(this->end() - num_to_insert),
  463. std::move_iterator<iterator>(this->end()));
  464. // Copy the existing elements that get replaced.
  465. std::move_backward(it, old_end - num_to_insert, old_end);
  466. std::fill_n(it, num_to_insert, elm);
  467. return it;
  468. }
  469. // Otherwise, we're inserting more elements than exist already,
  470. // and we're not inserting at the end.
  471. // Move over the elements that we're about to overwrite.
  472. T* old_end = this->end();
  473. this->set_end(this->end() + num_to_insert);
  474. size_t num_overwritten = old_end - it;
  475. this->uninitialized_move(it, old_end, this->end() - num_overwritten);
  476. // Replace the overwritten part.
  477. std::fill_n(it, num_overwritten, elm);
  478. // Insert the non-overwritten middle part.
  479. std::uninitialized_fill_n(old_end, num_to_insert - num_overwritten,
  480. elm);
  481. return it;
  482. }
  483. template <
  484. typename IterType,
  485. typename = typename std::enable_if<std::is_convertible<
  486. typename std::iterator_traits<IterType>::iterator_category,
  487. std::input_iterator_tag>::value>::type>
  488. iterator insert(iterator it, IterType from, IterType to) {
  489. // Convert iterator to elm# to avoid invalidating iterator
  490. // when we reserve()
  491. size_t elm_idx = it - this->begin();
  492. if (it == this->end()) { // Important special case for empty vector.
  493. append(from, to);
  494. return this->begin() + elm_idx;
  495. }
  496. size_t num_to_insert = std::distance(from, to);
  497. // Ensure there is enough space.
  498. reserve(this->size() + num_to_insert);
  499. // Uninvalidate the iterator.
  500. it = this->begin() + elm_idx;
  501. // If there are more elements between the insertion point and
  502. // the end of the range than there are being inserted,
  503. // we can use a simple approach to insertion.
  504. // Since we already reserved space, we know that this won't
  505. // reallocate the vector.
  506. if (size_t(this->end() - it) >= num_to_insert) {
  507. T* old_end = this->end();
  508. append(std::move_iterator<iterator>(this->end() - num_to_insert),
  509. std::move_iterator<iterator>(this->end()));
  510. // Copy the existing elements that get replaced.
  511. std::move_backward(it, old_end - num_to_insert, old_end);
  512. std::copy(from, to, it);
  513. return it;
  514. }
  515. // Otherwise, we're inserting more elements than exist already,
  516. // and we're not inserting at the end.
  517. // Move over the elements that we're about to overwrite.
  518. T* old_end = this->end();
  519. this->set_end(this->end() + num_to_insert);
  520. size_t num_overwritten = old_end - it;
  521. this->uninitialized_move(it, old_end, this->end() - num_overwritten);
  522. // Replace the overwritten part.
  523. for (T* iter = it; num_overwritten > 0; --num_overwritten) {
  524. *iter = *from;
  525. ++iter;
  526. ++from;
  527. }
  528. // Insert the non-overwritten middle part.
  529. this->uninitialized_copy(from, to, old_end);
  530. return it;
  531. }
  532. void insert(iterator it, std::initializer_list<T> init_list) {
  533. insert(it, init_list.begin(), init_list.end());
  534. }
  535. template <typename... ArgTypes>
  536. void emplace_back(ArgTypes&&... args) {
  537. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  538. this->grow();
  539. }
  540. new (static_cast<void*>(this->end()))
  541. T(std::forward<ArgTypes>(args)...);
  542. this->set_end(this->end() + 1);
  543. }
  544. SmallVectorImpl& operator=(const SmallVectorImpl& rhs);
  545. SmallVectorImpl& operator=(SmallVectorImpl&& rhs);
  546. bool operator==(const SmallVectorImpl<T>& rhs) const {
  547. if (this->size() != rhs.size())
  548. return false;
  549. return std::equal(this->begin(), this->end(), rhs.begin());
  550. }
  551. bool operator!=(const SmallVectorImpl<T>& rhs) const {
  552. return !(*this == rhs);
  553. }
  554. bool operator<(const SmallVectorImpl<T>& rhs) const {
  555. return std::lexicographical_compare(this->begin(), this->end(),
  556. rhs.begin(), rhs.end());
  557. }
  558. };
  559. template <typename T>
  560. void SmallVectorImpl<T>::swap(SmallVectorImpl<T>& rhs) {
  561. if (this == &rhs)
  562. return;
  563. // We can only avoid copying elements if neither vector is small.
  564. if (!this->is_small() && !rhs.is_small()) {
  565. std::swap(this->m_begin_ptr, rhs.m_begin_ptr);
  566. std::swap(this->m_end_ptr, rhs.m_end_ptr);
  567. std::swap(this->m_capacity_ptr, rhs.m_capacity_ptr);
  568. return;
  569. }
  570. if (rhs.size() > this->capacity())
  571. this->grow(rhs.size());
  572. if (this->size() > rhs.capacity())
  573. rhs.grow(this->size());
  574. // Swap the shared elements.
  575. size_t num_shared = this->size();
  576. if (num_shared > rhs.size())
  577. num_shared = rhs.size();
  578. for (size_type i = 0; i != num_shared; ++i)
  579. std::swap((*this)[i], rhs[i]);
  580. // Copy over the extra elms.
  581. if (this->size() > rhs.size()) {
  582. size_t elm_diff = this->size() - rhs.size();
  583. this->uninitialized_move(this->begin() + num_shared, this->end(),
  584. rhs.end());
  585. rhs.set_end(rhs.end() + elm_diff);
  586. this->destroy_range(this->begin() + num_shared, this->end());
  587. this->set_end(this->begin() + num_shared);
  588. } else if (rhs.size() > this->size()) {
  589. size_t elm_diff = rhs.size() - this->size();
  590. this->uninitialized_move(rhs.begin() + num_shared, rhs.end(),
  591. this->end());
  592. this->set_end(this->end() + elm_diff);
  593. this->destroy_range(rhs.begin() + num_shared, rhs.end());
  594. rhs.set_end(rhs.begin() + num_shared);
  595. }
  596. }
  597. template <typename T>
  598. SmallVectorImpl<T>& SmallVectorImpl<T>::operator=(
  599. const SmallVectorImpl<T>& rhs) {
  600. if (this == &rhs)
  601. return *this;
  602. size_t rhs_sz = rhs.size();
  603. size_t cur_sz = this->size();
  604. if (cur_sz >= rhs_sz) {
  605. iterator new_end;
  606. if (rhs_sz) {
  607. new_end = std::copy(rhs.begin(), rhs.end(), this->begin());
  608. } else {
  609. new_end = this->begin();
  610. }
  611. this->destroy_range(new_end, this->end());
  612. this->set_end(new_end);
  613. return *this;
  614. }
  615. if (this->capacity() < rhs_sz) {
  616. // save time for no copy when growing
  617. this->destroy_range(this->begin(), this->end());
  618. this->set_end(this->begin());
  619. cur_sz = 0;
  620. this->grow(rhs_sz);
  621. } else if (cur_sz) {
  622. std::copy(rhs.begin(), rhs.begin() + cur_sz, this->begin());
  623. }
  624. std::uninitialized_copy(rhs.begin() + cur_sz, rhs.end(),
  625. this->begin() + cur_sz);
  626. this->set_end(this->begin() + rhs_sz);
  627. return *this;
  628. }
  629. template <typename T>
  630. SmallVectorImpl<T>& SmallVectorImpl<T>::operator=(SmallVectorImpl<T>&& rhs) {
  631. // avoid self assignment
  632. if (this == &rhs)
  633. return *this;
  634. // copy ptr when rhs is small
  635. if (!rhs.is_small()) {
  636. this->destroy_range(this->begin(), this->end());
  637. if (!this->is_small())
  638. free(this->begin());
  639. this->m_begin_ptr = rhs.m_begin_ptr;
  640. this->m_end_ptr = rhs.m_end_ptr;
  641. this->m_capacity_ptr = rhs.m_capacity_ptr;
  642. rhs.reset_to_small();
  643. return *this;
  644. }
  645. size_t rhs_sz = rhs.size();
  646. size_t cur_sz = this->size();
  647. if (cur_sz >= rhs_sz) {
  648. iterator new_end = this->begin();
  649. if (rhs_sz) {
  650. new_end = std::move(rhs.begin(), rhs.end(), new_end);
  651. }
  652. this->destroy_range(new_end, this->end());
  653. this->set_end(new_end);
  654. rhs.clear();
  655. return *this;
  656. }
  657. if (this->capacity() < rhs_sz) {
  658. this->destroy_range(this->begin(), this->end());
  659. this->set_end(this->begin());
  660. cur_sz = 0;
  661. this->grow(rhs_sz);
  662. } else if (cur_sz) {
  663. std::move(rhs.begin(), rhs.begin() + cur_sz, this->begin());
  664. }
  665. this->uninitialized_move(rhs.begin() + cur_sz, rhs.end(),
  666. this->begin() + cur_sz);
  667. this->set_end(this->begin() + rhs_sz);
  668. rhs.clear();
  669. return *this;
  670. }
  671. template <typename T, unsigned N>
  672. struct SmallVectorStorage {
  673. typename SmallVectorTemplateCommon<T>::U inline_elms[N - 1];
  674. };
  675. template <typename T>
  676. struct SmallVectorStorage<T, 1> {};
  677. template <typename T>
  678. struct SmallVectorStorage<T, 0> {};
  679. /*!
  680. * \brief This is a 'vector' (really, a variable-sized array), optimized for the
  681. * case when the array is small.
  682. *
  683. * It contains some number of elements in-place,
  684. * which allows it to avoid heap allocation when the actual number of elements
  685. * is below that threshold. This allows normal "small" cases to be fast without
  686. * losing generality for large inputs.
  687. *
  688. * Note that this does not attempt to be exception safe.
  689. *
  690. * SmallVector<T, N>& can be converted to SmallVectorImpl<T>& to erase the
  691. * template param \p N; this is useful for function params.
  692. *
  693. * \tparam T emelment type
  694. * \tparam N number of elements to be stored in the class object
  695. */
  696. template <typename T, unsigned N = 4>
  697. class SmallVector : public SmallVectorImpl<T> {
  698. SmallVectorStorage<T, N> m_storage;
  699. public:
  700. SmallVector() : SmallVectorImpl<T>(N) {}
  701. explicit SmallVector(size_t size, const T& value = T())
  702. : SmallVectorImpl<T>(N) {
  703. this->assign(size, value);
  704. }
  705. template <
  706. typename IterType,
  707. typename = typename std::enable_if<std::is_convertible<
  708. typename std::iterator_traits<IterType>::iterator_category,
  709. std::input_iterator_tag>::value>::type>
  710. SmallVector(IterType first, IterType last) : SmallVectorImpl<T>(N) {
  711. this->append(first, last);
  712. }
  713. SmallVector(std::initializer_list<T> init_list) : SmallVectorImpl<T>(N) {
  714. this->assign(init_list);
  715. }
  716. SmallVector(const SmallVector& rhs) : SmallVectorImpl<T>(N) {
  717. if (!rhs.empty())
  718. SmallVectorImpl<T>::operator=(rhs);
  719. }
  720. ~SmallVector() {}
  721. const SmallVector& operator=(const SmallVector& rhs) {
  722. SmallVectorImpl<T>::operator=(rhs);
  723. return *this;
  724. }
  725. SmallVector(SmallVector&& rhs) : SmallVectorImpl<T>(N) {
  726. if (!rhs.empty())
  727. SmallVectorImpl<T>::operator=(std::move(rhs));
  728. }
  729. SmallVector(SmallVectorImpl<T>&& rhs) : SmallVectorImpl<T>(N) {
  730. if (!rhs.empty())
  731. SmallVectorImpl<T>::operator=(std::move(rhs));
  732. }
  733. const SmallVector& operator=(SmallVector&& rhs) {
  734. SmallVectorImpl<T>::operator=(std::move(rhs));
  735. return *this;
  736. }
  737. const SmallVector& operator=(SmallVectorImpl<T>&& rhs) {
  738. SmallVectorImpl<T>::operator=(std::move(rhs));
  739. return *this;
  740. }
  741. const SmallVector& operator=(std::initializer_list<T> init_list) {
  742. this->assign(init_list);
  743. return *this;
  744. }
  745. };
  746. template <typename T, unsigned n>
  747. static inline size_t capacity_in_bytes(const SmallVector<T, n>& vec) {
  748. return vec.capacity_in_bytes();
  749. }
  750. template <typename T>
  751. inline typename SmallVectorImpl<T>::const_iterator find(
  752. const SmallVectorImpl<T>& vec, const T& value) {
  753. return vec.find(vec.begin(), vec.end(), value);
  754. }
  755. } // end namespace megdnn
  756. #include "megdnn/internal/visibility_epilogue.h"
  757. namespace std {
  758. /// Implement std::swap in terms of SmallVector swap.
  759. template <typename T>
  760. inline void swap(megdnn::SmallVectorImpl<T>& lhs,
  761. megdnn::SmallVectorImpl<T>& rhs) {
  762. lhs.swap(rhs);
  763. }
  764. /// Implement std::swap in terms of SmallVector swap.
  765. template <typename T, unsigned N>
  766. inline void swap(megdnn::SmallVector<T, N>& lhs,
  767. megdnn::SmallVector<T, N>& rhs) {
  768. lhs.swap(rhs);
  769. }
  770. } // end namespace std
  771. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台

Contributors (1)